xref: /llvm-project/clang-tools-extra/clangd/test/include-cleaner-batch-fix.test (revision 2336f792bc5a1d9195c1bd995b6040c13e73d4e7)
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