| # 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"} |