1# We specify a custom path in XDG_CONFIG_HOME, which only works on some systems. 2# UNSUPPORTED: system-windows 3# UNSUPPORTED: system-darwin 4 5# RUN: rm -rf %t 6# RUN: mkdir -p %t/clangd 7# RUN: cp -r %S/Inputs/include-cleaner %t/include 8# RUN: echo '-I%t/include' > %t/compile_flags.txt 9# Create a config file enabling include-cleaner features. 10# RUN: echo $'Diagnostics:\n UnusedIncludes: Strict\n MissingIncludes: Strict' >> %t/clangd/config.yaml 11 12# RUN: env XDG_CONFIG_HOME=%t clangd -lit-test -enable-config --compile-commands-dir=%t < %s | FileCheck -strict-whitespace %s 13{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"processId":123,"rootPath":"clangd","capabilities":{"workspace":{"workspaceEdit":{"documentChanges":true, "changeAnnotationSupport":{"groupsOnLabel":true}}}},"trace":"off"}} 14--- 15{ 16 "jsonrpc": "2.0", 17 "method": "textDocument/didOpen", 18 "params": { 19 "textDocument": { 20 "uri": "test:///simple.cpp", 21 "languageId": "cpp", 22 "text": "#include \"all1.h\"\n#include \"all2.h\"\n Foo* foo; Bar* bar;" 23 } 24 } 25} 26# First, the diagnostic from the config file. 27# CHECK: "method": "textDocument/publishDiagnostics", 28# CHECK-NEXT: "params": { 29# CHECK-NEXT: "diagnostics": [], 30 31# Then, diagnostic from the main cpp file. 32# CHECK: "method": "textDocument/publishDiagnostics", 33# CHECK-NEXT: "params": { 34# CHECK-NEXT: "diagnostics": [ 35# CHECK-NEXT: { 36# CHECK-NEXT: "code": "missing-includes", 37# CHECK-NEXT: "codeDescription": { 38# CHECK-NEXT: "href": "{{.*}}" 39# CHECK-NEXT: }, 40# CHECK-NEXT: "message": "No header providing \"Foo\" is directly included (fixes available)", 41# CHECK-NEXT: "range": { 42# CHECK-NEXT: "end": { 43# CHECK-NEXT: "character": 4, 44# CHECK-NEXT: "line": 2 45# CHECK-NEXT: }, 46# CHECK-NEXT: "start": { 47# CHECK-NEXT: "character": 1, 48# CHECK-NEXT: "line": 2 49# CHECK-NEXT: } 50# CHECK-NEXT: }, 51# CHECK-NEXT: "severity": 3, 52# CHECK-NEXT: "source": "clangd" 53# CHECK-NEXT: }, 54# CHECK-NEXT: { 55# CHECK-NEXT: "code": "missing-includes", 56# CHECK-NEXT: "codeDescription": { 57# CHECK-NEXT: "href": "{{.*}}" 58# CHECK-NEXT: }, 59# CHECK-NEXT: "message": "No header providing \"Bar\" is directly included (fixes available)", 60# CHECK-NEXT: "range": { 61# CHECK-NEXT: "end": { 62# CHECK-NEXT: "character": 14, 63# CHECK-NEXT: "line": 2 64# CHECK-NEXT: }, 65# CHECK-NEXT: "start": { 66# CHECK-NEXT: "character": 11, 67# CHECK-NEXT: "line": 2 68# CHECK-NEXT: } 69# CHECK-NEXT: }, 70# CHECK-NEXT: "severity": 3, 71# CHECK-NEXT: "source": "clangd" 72# CHECK-NEXT: }, 73# CHECK-NEXT: { 74# CHECK-NEXT: "code": "unused-includes", 75# CHECK-NEXT: "codeDescription": { 76# CHECK-NEXT: "href": "{{.*}}" 77# CHECK-NEXT: }, 78# CHECK-NEXT: "message": "Included header all1.h is not used directly (fixes available)", 79# CHECK-NEXT: "range": { 80# CHECK-NEXT: "end": { 81# CHECK-NEXT: "character": 17, 82# CHECK-NEXT: "line": 0 83# CHECK-NEXT: }, 84# CHECK-NEXT: "start": { 85# CHECK-NEXT: "character": 0, 86# CHECK-NEXT: "line": 0 87# CHECK-NEXT: } 88# CHECK-NEXT: }, 89# CHECK-NEXT: "severity": 2, 90# CHECK-NEXT: "source": "clangd", 91# CHECK-NEXT: "tags": [ 92# CHECK-NEXT: 1 93# CHECK-NEXT: ] 94# CHECK-NEXT: }, 95# CHECK-NEXT: { 96# CHECK-NEXT: "code": "unused-includes", 97# CHECK-NEXT: "codeDescription": { 98# CHECK-NEXT: "href": "{{.*}}" 99# CHECK-NEXT: }, 100# CHECK-NEXT: "message": "Included header all2.h is not used directly (fixes available)", 101# CHECK-NEXT: "range": { 102# CHECK-NEXT: "end": { 103# CHECK-NEXT: "character": 17, 104# CHECK-NEXT: "line": 1 105# CHECK-NEXT: }, 106# CHECK-NEXT: "start": { 107# CHECK-NEXT: "character": 0, 108# CHECK-NEXT: "line": 1 109# CHECK-NEXT: } 110# CHECK-NEXT: }, 111# CHECK-NEXT: "severity": 2, 112# CHECK-NEXT: "source": "clangd", 113# CHECK-NEXT: "tags": [ 114# CHECK-NEXT: 1 115# CHECK-NEXT: ] 116# CHECK-NEXT: } 117# CHECK-NEXT: ], 118# CHECK-NEXT: "uri": "file://{{.*}}/simple.cpp", 119# CHECK-NEXT: "version": 0 120# CHECK-NEXT: } 121--- 122{"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"}]}}} 123# CHECK: "id": 2, 124# CHECK-NEXT: "jsonrpc": "2.0", 125# CHECK-NEXT: "result": [ 126# CHECK-NEXT: { 127# CHECK-NEXT: "arguments": [ 128# CHECK-NEXT: { 129# CHECK-NEXT: "documentChanges": [ 130# CHECK-NEXT: { 131# CHECK-NEXT: "edits": [ 132# CHECK-NEXT: { 133# CHECK-NEXT: "newText": "#include {{.*}}foo.h{{.*}}", 134# CHECK-NEXT: "range": { 135# CHECK-NEXT: "end": { 136# CHECK-NEXT: "character": 0, 137# CHECK-NEXT: "line": 2 138# CHECK-NEXT: }, 139# CHECK-NEXT: "start": { 140# CHECK-NEXT: "character": 0, 141# CHECK-NEXT: "line": 2 142# CHECK-NEXT: } 143# CHECK-NEXT: } 144# CHECK-NEXT: } 145# CHECK-NEXT: ], 146# CHECK-NEXT: "textDocument": { 147# CHECK-NEXT: "uri": "file://{{.*}}/simple.cpp", 148# CHECK-NEXT: "version": 0 149# CHECK-NEXT: } 150# CHECK-NEXT: } 151# CHECK-NEXT: ] 152# CHECK-NEXT: } 153# CHECK-NEXT: ], 154# CHECK-NEXT: "command": "clangd.applyFix", 155# CHECK-NEXT: "title": "Apply fix: #include {{.*}}foo.h{{.*}}" 156# CHECK-NEXT: }, 157# CHECK-NEXT: { 158# CHECK-NEXT: "arguments": [ 159# CHECK-NEXT: { 160# CHECK-NEXT: "documentChanges": [ 161# CHECK-NEXT: { 162# CHECK-NEXT: "edits": [ 163# CHECK-NEXT: { 164# CHECK-NEXT: "newText": "#include {{.*}}bar.h{{.*}}", 165# CHECK-NEXT: "range": { 166# CHECK-NEXT: "end": { 167# CHECK-NEXT: "character": 0, 168# CHECK-NEXT: "line": 2 169# CHECK-NEXT: }, 170# CHECK-NEXT: "start": { 171# CHECK-NEXT: "character": 0, 172# CHECK-NEXT: "line": 2 173# CHECK-NEXT: } 174# CHECK-NEXT: } 175# CHECK-NEXT: }, 176# CHECK-NEXT: { 177# CHECK-NEXT: "newText": "#include {{.*}}foo.h{{.*}}", 178# CHECK-NEXT: "range": { 179# CHECK-NEXT: "end": { 180# CHECK-NEXT: "character": 0, 181# CHECK-NEXT: "line": 2 182# CHECK-NEXT: }, 183# CHECK-NEXT: "start": { 184# CHECK-NEXT: "character": 0, 185# CHECK-NEXT: "line": 2 186# CHECK-NEXT: } 187# CHECK-NEXT: } 188# CHECK-NEXT: } 189# CHECK-NEXT: ], 190# CHECK-NEXT: "textDocument": { 191# CHECK-NEXT: "uri": "file://{{.*}}/simple.cpp", 192# CHECK-NEXT: "version": 0 193# CHECK-NEXT: } 194# CHECK-NEXT: } 195# CHECK-NEXT: ] 196# CHECK-NEXT: } 197# CHECK-NEXT: ], 198# CHECK-NEXT: "command": "clangd.applyFix", 199# CHECK-NEXT: "title": "Apply fix: add all missing includes" 200# CHECK-NEXT: }, 201# CHECK-NEXT: { 202# CHECK-NEXT: "arguments": [ 203# CHECK-NEXT: { 204# CHECK-NEXT: "documentChanges": [ 205# CHECK-NEXT: { 206# CHECK-NEXT: "edits": [ 207# CHECK-NEXT: { 208# CHECK-NEXT: "newText": "", 209# CHECK-NEXT: "range": { 210# CHECK-NEXT: "end": { 211# CHECK-NEXT: "character": 0, 212# CHECK-NEXT: "line": 1 213# CHECK-NEXT: }, 214# CHECK-NEXT: "start": { 215# CHECK-NEXT: "character": 0, 216# CHECK-NEXT: "line": 0 217# CHECK-NEXT: } 218# CHECK-NEXT: } 219# CHECK-NEXT: }, 220# CHECK-NEXT: { 221# CHECK-NEXT: "newText": "", 222# CHECK-NEXT: "range": { 223# CHECK-NEXT: "end": { 224# CHECK-NEXT: "character": 0, 225# CHECK-NEXT: "line": 2 226# CHECK-NEXT: }, 227# CHECK-NEXT: "start": { 228# CHECK-NEXT: "character": 0, 229# CHECK-NEXT: "line": 1 230# CHECK-NEXT: } 231# CHECK-NEXT: } 232# CHECK-NEXT: }, 233# CHECK-NEXT: { 234# CHECK-NEXT: "newText": "#include {{.*}}bar.h{{.*}}", 235# CHECK-NEXT: "range": { 236# CHECK-NEXT: "end": { 237# CHECK-NEXT: "character": 0, 238# CHECK-NEXT: "line": 2 239# CHECK-NEXT: }, 240# CHECK-NEXT: "start": { 241# CHECK-NEXT: "character": 0, 242# CHECK-NEXT: "line": 2 243# CHECK-NEXT: } 244# CHECK-NEXT: } 245# CHECK-NEXT: }, 246# CHECK-NEXT: { 247# CHECK-NEXT: "newText": "#include {{.*}}foo.h{{.*}}", 248# CHECK-NEXT: "range": { 249# CHECK-NEXT: "end": { 250# CHECK-NEXT: "character": 0, 251# CHECK-NEXT: "line": 2 252# CHECK-NEXT: }, 253# CHECK-NEXT: "start": { 254# CHECK-NEXT: "character": 0, 255# CHECK-NEXT: "line": 2 256# CHECK-NEXT: } 257# CHECK-NEXT: } 258# CHECK-NEXT: } 259# CHECK-NEXT: ], 260# CHECK-NEXT: "textDocument": { 261# CHECK-NEXT: "uri": "file://{{.*}}/simple.cpp", 262# CHECK-NEXT: "version": 0 263# CHECK-NEXT: } 264# CHECK-NEXT: } 265# CHECK-NEXT: ] 266# CHECK-NEXT: } 267# CHECK-NEXT: ], 268# CHECK-NEXT: "command": "clangd.applyFix", 269# CHECK-NEXT: "title": "Apply fix: fix all includes" 270# CHECK-NEXT: } 271# CHECK-NEXT: ] 272--- 273{"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"}]}}} 274# CHECK: "id": 3, 275# CHECK-NEXT: "jsonrpc": "2.0", 276# CHECK-NEXT: "result": [ 277# CHECK-NEXT: { 278# CHECK-NEXT: "arguments": [ 279# CHECK-NEXT: { 280# CHECK-NEXT: "documentChanges": [ 281# CHECK-NEXT: { 282# CHECK-NEXT: "edits": [ 283# CHECK-NEXT: { 284# CHECK-NEXT: "newText": "", 285# CHECK-NEXT: "range": { 286# CHECK-NEXT: "end": { 287# CHECK-NEXT: "character": 0, 288# CHECK-NEXT: "line": 1 289# CHECK-NEXT: }, 290# CHECK-NEXT: "start": { 291# CHECK-NEXT: "character": 0, 292# CHECK-NEXT: "line": 0 293# CHECK-NEXT: } 294# CHECK-NEXT: } 295# CHECK-NEXT: } 296# CHECK-NEXT: ], 297# CHECK-NEXT: "textDocument": { 298# CHECK-NEXT: "uri": "file://{{.*}}/simple.cpp", 299# CHECK-NEXT: "version": 0 300# CHECK-NEXT: } 301# CHECK-NEXT: } 302# CHECK-NEXT: ] 303# CHECK-NEXT: } 304# CHECK-NEXT: ], 305# CHECK-NEXT: "command": "clangd.applyFix", 306# CHECK-NEXT: "title": "Apply fix: remove #include directive" 307# CHECK-NEXT: }, 308# CHECK-NEXT: { 309# CHECK-NEXT: "arguments": [ 310# CHECK-NEXT: { 311# CHECK-NEXT: "documentChanges": [ 312# CHECK-NEXT: { 313# CHECK-NEXT: "edits": [ 314# CHECK-NEXT: { 315# CHECK-NEXT: "newText": "", 316# CHECK-NEXT: "range": { 317# CHECK-NEXT: "end": { 318# CHECK-NEXT: "character": 0, 319# CHECK-NEXT: "line": 1 320# CHECK-NEXT: }, 321# CHECK-NEXT: "start": { 322# CHECK-NEXT: "character": 0, 323# CHECK-NEXT: "line": 0 324# CHECK-NEXT: } 325# CHECK-NEXT: } 326# CHECK-NEXT: }, 327# CHECK-NEXT: { 328# CHECK-NEXT: "newText": "", 329# CHECK-NEXT: "range": { 330# CHECK-NEXT: "end": { 331# CHECK-NEXT: "character": 0, 332# CHECK-NEXT: "line": 2 333# CHECK-NEXT: }, 334# CHECK-NEXT: "start": { 335# CHECK-NEXT: "character": 0, 336# CHECK-NEXT: "line": 1 337# CHECK-NEXT: } 338# CHECK-NEXT: } 339# CHECK-NEXT: } 340# CHECK-NEXT: ], 341# CHECK-NEXT: "textDocument": { 342# CHECK-NEXT: "uri": "file://{{.*}}/simple.cpp", 343# CHECK-NEXT: "version": 0 344# CHECK-NEXT: } 345# CHECK-NEXT: } 346# CHECK-NEXT: ] 347# CHECK-NEXT: } 348# CHECK-NEXT: ], 349# CHECK-NEXT: "command": "clangd.applyFix", 350# CHECK-NEXT: "title": "Apply fix: remove all unused includes" 351# CHECK-NEXT: }, 352# CHECK-NEXT: { 353# CHECK-NEXT: "arguments": [ 354# CHECK-NEXT: { 355# CHECK-NEXT: "documentChanges": [ 356# CHECK-NEXT: { 357# CHECK-NEXT: "edits": [ 358# CHECK-NEXT: { 359# CHECK-NEXT: "newText": "", 360# CHECK-NEXT: "range": { 361# CHECK-NEXT: "end": { 362# CHECK-NEXT: "character": 0, 363# CHECK-NEXT: "line": 1 364# CHECK-NEXT: }, 365# CHECK-NEXT: "start": { 366# CHECK-NEXT: "character": 0, 367# CHECK-NEXT: "line": 0 368# CHECK-NEXT: } 369# CHECK-NEXT: } 370# CHECK-NEXT: }, 371# CHECK-NEXT: { 372# CHECK-NEXT: "newText": "", 373# CHECK-NEXT: "range": { 374# CHECK-NEXT: "end": { 375# CHECK-NEXT: "character": 0, 376# CHECK-NEXT: "line": 2 377# CHECK-NEXT: }, 378# CHECK-NEXT: "start": { 379# CHECK-NEXT: "character": 0, 380# CHECK-NEXT: "line": 1 381# CHECK-NEXT: } 382# CHECK-NEXT: } 383# CHECK-NEXT: }, 384# CHECK-NEXT: { 385# CHECK-NEXT: "newText": "#include {{.*}}bar.h{{.*}}", 386# CHECK-NEXT: "range": { 387# CHECK-NEXT: "end": { 388# CHECK-NEXT: "character": 0, 389# CHECK-NEXT: "line": 2 390# CHECK-NEXT: }, 391# CHECK-NEXT: "start": { 392# CHECK-NEXT: "character": 0, 393# CHECK-NEXT: "line": 2 394# CHECK-NEXT: } 395# CHECK-NEXT: } 396# CHECK-NEXT: }, 397# CHECK-NEXT: { 398# CHECK-NEXT: "newText": "#include {{.*}}foo.h{{.*}}", 399# CHECK-NEXT: "range": { 400# CHECK-NEXT: "end": { 401# CHECK-NEXT: "character": 0, 402# CHECK-NEXT: "line": 2 403# CHECK-NEXT: }, 404# CHECK-NEXT: "start": { 405# CHECK-NEXT: "character": 0, 406# CHECK-NEXT: "line": 2 407# CHECK-NEXT: } 408# CHECK-NEXT: } 409# CHECK-NEXT: } 410# CHECK-NEXT: ], 411# CHECK-NEXT: "textDocument": { 412# CHECK-NEXT: "uri": "file://{{.*}}/simple.cpp", 413# CHECK-NEXT: "version": 0 414# CHECK-NEXT: } 415# CHECK-NEXT: } 416# CHECK-NEXT: ] 417# CHECK-NEXT: } 418# CHECK-NEXT: ], 419# CHECK-NEXT: "command": "clangd.applyFix", 420# CHECK-NEXT: "title": "Apply fix: fix all includes" 421# CHECK-NEXT: } 422# CHECK-NEXT: ] 423--- 424{"jsonrpc":"2.0","id":4,"method":"shutdown"} 425--- 426{"jsonrpc":"2.0","method":"exit"} 427