# We specify a custom path in XDG_CONFIG_HOME, which only works on some systems.
# UNSUPPORTED: system-windows
# UNSUPPORTED: system-darwin
# RUN: rm -rf %t
# RUN: mkdir -p %t/clangd
# RUN: cp -r %S/Inputs/include-cleaner %t/include
# RUN: echo '-I%t/include' > %t/compile_flags.txt
# Create a config file enabling include-cleaner features.
# RUN: echo $'Diagnostics:\n UnusedIncludes: Strict\n MissingIncludes: Strict' >> %t/clangd/config.yaml
# RUN: env XDG_CONFIG_HOME=%t clangd -lit-test -enable-config --compile-commands-dir=%t < %s | FileCheck -strict-whitespace %s
{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{"workspace":{"workspaceEdit":{"documentChanges":true, "changeAnnotationSupport":{"groupsOnLabel":true}}}},"trace":"off"}}
---
{
"jsonrpc": "2.0",
"method": "textDocument/didOpen",
"params": {
"textDocument": {
"uri": "test:///simple.cpp",
"languageId": "cpp",
"text": "#include \"all1.h\"\n#include \"all2.h\"\n Foo* foo; Bar* bar;"
}
}
}
# First, the diagnostic from the config file.
# CHECK: "method": "textDocument/publishDiagnostics",
# CHECK-NEXT: "params": {
# CHECK-NEXT: "diagnostics": [],
# Then, diagnostic from the main cpp file.
# CHECK: "method": "textDocument/publishDiagnostics",
# CHECK-NEXT: "params": {
# CHECK-NEXT: "diagnostics": [
# CHECK-NEXT: {
# CHECK-NEXT: "code": "missing-includes",
# CHECK-NEXT: "codeDescription": {
# CHECK-NEXT: "href": "{{.*}}"
# CHECK-NEXT: },
# CHECK-NEXT: "message": "No header providing \"Foo\" is directly included (fixes available)",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 4,
# CHECK-NEXT: "line": 2
# CHECK-NEXT: },
# CHECK-NEXT: "start": {
# CHECK-NEXT: "character": 1,
# CHECK-NEXT: "line": 2
# CHECK-NEXT: }
# CHECK-NEXT: },
# CHECK-NEXT: "severity": 3,
# CHECK-NEXT: "source": "clangd"
# CHECK-NEXT: },
# CHECK-NEXT: {
# CHECK-NEXT: "code": "missing-includes",
# CHECK-NEXT: "codeDescription": {
# CHECK-NEXT: "href": "{{.*}}"
# CHECK-NEXT: },
# CHECK-NEXT: "message": "No header providing \"Bar\" is directly included (fixes available)",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 14,
# CHECK-NEXT: "line": 2
# CHECK-NEXT: },
# CHECK-NEXT: "start": {
# CHECK-NEXT: "character": 11,
# CHECK-NEXT: "line": 2
# CHECK-NEXT: }
# CHECK-NEXT: },
# CHECK-NEXT: "severity": 3,
# CHECK-NEXT: "source": "clangd"
# CHECK-NEXT: },
# CHECK-NEXT: {
# CHECK-NEXT: "code": "unused-includes",
# CHECK-NEXT: "codeDescription": {
# CHECK-NEXT: "href": "{{.*}}"
# CHECK-NEXT: },
# CHECK-NEXT: "message": "Included header all1.h is not used directly (fixes available)",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 17,
# CHECK-NEXT: "line": 0
# CHECK-NEXT: },
# CHECK-NEXT: "start": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 0
# CHECK-NEXT: }
# CHECK-NEXT: },
# CHECK-NEXT: "severity": 2,
# CHECK-NEXT: "source": "clangd",
# CHECK-NEXT: "tags": [
# CHECK-NEXT: 1
# CHECK-NEXT: ]
# CHECK-NEXT: },
# CHECK-NEXT: {
# CHECK-NEXT: "code": "unused-includes",
# CHECK-NEXT: "codeDescription": {
# CHECK-NEXT: "href": "{{.*}}"
# CHECK-NEXT: },
# CHECK-NEXT: "message": "Included header all2.h is not used directly (fixes available)",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 17,
# CHECK-NEXT: "line": 1
# CHECK-NEXT: },
# CHECK-NEXT: "start": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 1
# CHECK-NEXT: }
# CHECK-NEXT: },
# CHECK-NEXT: "severity": 2,
# CHECK-NEXT: "source": "clangd",
# CHECK-NEXT: "tags": [
# CHECK-NEXT: 1
# CHECK-NEXT: ]
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "uri": "file://{{.*}}/simple.cpp",
# CHECK-NEXT: "version": 0
# CHECK-NEXT: }
---
{"jsonrpc":"2.0","id":2,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"test:///simple.cpp"},"range":{"start":{"line":2,"character":1},"end":{"line":2,"character":4}},"context":{"diagnostics":[{"range":{"start": {"line": 2, "character": 1}, "end": {"line": 2, "character": 4}},"severity":3,"message":"No header providing \"Foo\" is directly included (fixes available)", "code": "missing-includes", "source": "clangd"}]}}}
# CHECK: "id": 2,
# CHECK-NEXT: "jsonrpc": "2.0",
# CHECK-NEXT: "result": [
# CHECK-NEXT: {
# CHECK-NEXT: "arguments": [
# CHECK-NEXT: {
# CHECK-NEXT: "documentChanges": [
# CHECK-NEXT: {
# CHECK-NEXT: "edits": [
# CHECK-NEXT: {
# CHECK-NEXT: "newText": "#include {{.*}}foo.h{{.*}}",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 2
# CHECK-NEXT: },
# CHECK-NEXT: "start": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 2
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "textDocument": {
# CHECK-NEXT: "uri": "file://{{.*}}/simple.cpp",
# CHECK-NEXT: "version": 0
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "command": "clangd.applyFix",
# CHECK-NEXT: "title": "Apply fix: #include {{.*}}foo.h{{.*}}"
# CHECK-NEXT: },
# CHECK-NEXT: {
# CHECK-NEXT: "arguments": [
# CHECK-NEXT: {
# CHECK-NEXT: "documentChanges": [
# CHECK-NEXT: {
# CHECK-NEXT: "edits": [
# CHECK-NEXT: {
# CHECK-NEXT: "newText": "#include {{.*}}bar.h{{.*}}",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 2
# CHECK-NEXT: },
# CHECK-NEXT: "start": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 2
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: },
# CHECK-NEXT: {
# CHECK-NEXT: "newText": "#include {{.*}}foo.h{{.*}}",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 2
# CHECK-NEXT: },
# CHECK-NEXT: "start": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 2
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "textDocument": {
# CHECK-NEXT: "uri": "file://{{.*}}/simple.cpp",
# CHECK-NEXT: "version": 0
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "command": "clangd.applyFix",
# CHECK-NEXT: "title": "Apply fix: add all missing includes"
# CHECK-NEXT: },
# CHECK-NEXT: {
# CHECK-NEXT: "arguments": [
# CHECK-NEXT: {
# CHECK-NEXT: "documentChanges": [
# CHECK-NEXT: {
# CHECK-NEXT: "edits": [
# CHECK-NEXT: {
# CHECK-NEXT: "newText": "",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 1
# CHECK-NEXT: },
# CHECK-NEXT: "start": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 0
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: },
# CHECK-NEXT: {
# CHECK-NEXT: "newText": "",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 2
# CHECK-NEXT: },
# CHECK-NEXT: "start": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 1
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: },
# CHECK-NEXT: {
# CHECK-NEXT: "newText": "#include {{.*}}bar.h{{.*}}",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 2
# CHECK-NEXT: },
# CHECK-NEXT: "start": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 2
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: },
# CHECK-NEXT: {
# CHECK-NEXT: "newText": "#include {{.*}}foo.h{{.*}}",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 2
# CHECK-NEXT: },
# CHECK-NEXT: "start": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 2
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "textDocument": {
# CHECK-NEXT: "uri": "file://{{.*}}/simple.cpp",
# CHECK-NEXT: "version": 0
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "command": "clangd.applyFix",
# CHECK-NEXT: "title": "Apply fix: fix all includes"
# CHECK-NEXT: }
# CHECK-NEXT: ]
---
{"jsonrpc":"2.0","id":3,"method":"textDocument/codeAction","params":{"textDocument":{"uri":"test:///simple.cpp"},"range":{"start":{"line":0,"character":0},"end":{"line":0,"character":17}},"context":{"diagnostics":[{"range":{"start": {"line": 0, "character": 0}, "end": {"line": 0, "character": 17}},"severity":2,"message":"Included header all1.h is not used directly (fixes available)", "code": "unused-includes", "source": "clangd"}]}}}
# CHECK: "id": 3,
# CHECK-NEXT: "jsonrpc": "2.0",
# CHECK-NEXT: "result": [
# CHECK-NEXT: {
# CHECK-NEXT: "arguments": [
# CHECK-NEXT: {
# CHECK-NEXT: "documentChanges": [
# CHECK-NEXT: {
# CHECK-NEXT: "edits": [
# CHECK-NEXT: {
# CHECK-NEXT: "newText": "",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 1
# CHECK-NEXT: },
# CHECK-NEXT: "start": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 0
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "textDocument": {
# CHECK-NEXT: "uri": "file://{{.*}}/simple.cpp",
# CHECK-NEXT: "version": 0
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "command": "clangd.applyFix",
# CHECK-NEXT: "title": "Apply fix: remove #include directive"
# CHECK-NEXT: },
# CHECK-NEXT: {
# CHECK-NEXT: "arguments": [
# CHECK-NEXT: {
# CHECK-NEXT: "documentChanges": [
# CHECK-NEXT: {
# CHECK-NEXT: "edits": [
# CHECK-NEXT: {
# CHECK-NEXT: "newText": "",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 1
# CHECK-NEXT: },
# CHECK-NEXT: "start": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 0
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: },
# CHECK-NEXT: {
# CHECK-NEXT: "newText": "",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 2
# CHECK-NEXT: },
# CHECK-NEXT: "start": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 1
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "textDocument": {
# CHECK-NEXT: "uri": "file://{{.*}}/simple.cpp",
# CHECK-NEXT: "version": 0
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "command": "clangd.applyFix",
# CHECK-NEXT: "title": "Apply fix: remove all unused includes"
# CHECK-NEXT: },
# CHECK-NEXT: {
# CHECK-NEXT: "arguments": [
# CHECK-NEXT: {
# CHECK-NEXT: "documentChanges": [
# CHECK-NEXT: {
# CHECK-NEXT: "edits": [
# CHECK-NEXT: {
# CHECK-NEXT: "newText": "",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 1
# CHECK-NEXT: },
# CHECK-NEXT: "start": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 0
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: },
# CHECK-NEXT: {
# CHECK-NEXT: "newText": "",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 2
# CHECK-NEXT: },
# CHECK-NEXT: "start": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 1
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: },
# CHECK-NEXT: {
# CHECK-NEXT: "newText": "#include {{.*}}bar.h{{.*}}",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 2
# CHECK-NEXT: },
# CHECK-NEXT: "start": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 2
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: },
# CHECK-NEXT: {
# CHECK-NEXT: "newText": "#include {{.*}}foo.h{{.*}}",
# CHECK-NEXT: "range": {
# CHECK-NEXT: "end": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 2
# CHECK-NEXT: },
# CHECK-NEXT: "start": {
# CHECK-NEXT: "character": 0,
# CHECK-NEXT: "line": 2
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "textDocument": {
# CHECK-NEXT: "uri": "file://{{.*}}/simple.cpp",
# CHECK-NEXT: "version": 0
# CHECK-NEXT: }
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: }
# CHECK-NEXT: ],
# CHECK-NEXT: "command": "clangd.applyFix",
# CHECK-NEXT: "title": "Apply fix: fix all includes"
# CHECK-NEXT: }
# CHECK-NEXT: ]
---
{"jsonrpc":"2.0","id":4,"method":"shutdown"}
---
{"jsonrpc":"2.0","method":"exit"}