1 | //===- unittest/Format/SortIncludesTest.cpp - Include sort unit tests -----===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "FormatTestUtils.h" |
10 | #include "clang/Format/Format.h" |
11 | #include "llvm/ADT/StringRef.h" |
12 | #include "llvm/Support/Debug.h" |
13 | #include "gtest/gtest.h" |
14 | |
15 | #define DEBUG_TYPE "format-test" |
16 | |
17 | namespace clang { |
18 | namespace format { |
19 | namespace { |
20 | |
21 | class SortIncludesTest : public ::testing::Test { |
22 | protected: |
23 | std::vector<tooling::Range> GetCodeRange(StringRef Code) { |
24 | return std::vector<tooling::Range>(1, tooling::Range(0, Code.size())); |
25 | } |
26 | |
27 | std::string sort(StringRef Code, std::vector<tooling::Range> Ranges, |
28 | StringRef FileName = "input.cc" , |
29 | unsigned ExpectedNumRanges = 1) { |
30 | auto Replaces = sortIncludes(Style: FmtStyle, Code, Ranges, FileName); |
31 | Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges); |
32 | EXPECT_EQ(ExpectedNumRanges, Replaces.size()); |
33 | auto Sorted = applyAllReplacements(Code, Replaces); |
34 | EXPECT_TRUE(static_cast<bool>(Sorted)); |
35 | auto Result = applyAllReplacements( |
36 | Code: *Sorted, Replaces: reformat(Style: FmtStyle, Code: *Sorted, Ranges, FileName)); |
37 | EXPECT_TRUE(static_cast<bool>(Result)); |
38 | return *Result; |
39 | } |
40 | |
41 | std::string sort(StringRef Code, StringRef FileName = "input.cpp" , |
42 | unsigned ExpectedNumRanges = 1) { |
43 | return sort(Code, Ranges: GetCodeRange(Code), FileName, ExpectedNumRanges); |
44 | } |
45 | |
46 | unsigned newCursor(llvm::StringRef Code, unsigned Cursor) { |
47 | sortIncludes(Style: FmtStyle, Code, Ranges: GetCodeRange(Code), FileName: "input.cpp" , Cursor: &Cursor); |
48 | return Cursor; |
49 | } |
50 | |
51 | FormatStyle FmtStyle = getLLVMStyle(); |
52 | tooling::IncludeStyle &Style = FmtStyle.IncludeStyle; |
53 | }; |
54 | |
55 | TEST_F(SortIncludesTest, BasicSorting) { |
56 | EXPECT_EQ("#include \"a.h\"\n" |
57 | "#include \"b.h\"\n" |
58 | "#include \"c.h\"" , |
59 | sort("#include \"a.h\"\n" |
60 | "#include \"c.h\"\n" |
61 | "#include \"b.h\"" )); |
62 | |
63 | EXPECT_EQ("// comment\n" |
64 | "#include <a>\n" |
65 | "#include <b>" , |
66 | sort("// comment\n" |
67 | "#include <b>\n" |
68 | "#include <a>" , |
69 | {tooling::Range(25, 1)})); |
70 | } |
71 | |
72 | TEST_F(SortIncludesTest, TrailingComments) { |
73 | EXPECT_EQ("#include \"a.h\"\n" |
74 | "#include \"b.h\" /* long\n" |
75 | " * long\n" |
76 | " * comment*/\n" |
77 | "#include \"c.h\"\n" |
78 | "#include \"d.h\"" , |
79 | sort("#include \"a.h\"\n" |
80 | "#include \"c.h\"\n" |
81 | "#include \"b.h\" /* long\n" |
82 | " * long\n" |
83 | " * comment*/\n" |
84 | "#include \"d.h\"" )); |
85 | } |
86 | |
87 | TEST_F(SortIncludesTest, SortedIncludesUsingSortPriorityAttribute) { |
88 | FmtStyle.IncludeStyle.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; |
89 | FmtStyle.IncludeStyle.IncludeCategories = { |
90 | {.Regex: "^<sys/param\\.h>" , .Priority: 1, .SortPriority: 0, .RegexIsCaseSensitive: false}, |
91 | {.Regex: "^<sys/types\\.h>" , .Priority: 1, .SortPriority: 1, .RegexIsCaseSensitive: false}, |
92 | {.Regex: "^<sys.*/" , .Priority: 1, .SortPriority: 2, .RegexIsCaseSensitive: false}, |
93 | {.Regex: "^<uvm/" , .Priority: 2, .SortPriority: 3, .RegexIsCaseSensitive: false}, |
94 | {.Regex: "^<machine/" , .Priority: 3, .SortPriority: 4, .RegexIsCaseSensitive: false}, |
95 | {.Regex: "^<dev/" , .Priority: 4, .SortPriority: 5, .RegexIsCaseSensitive: false}, |
96 | {.Regex: "^<net.*/" , .Priority: 5, .SortPriority: 6, .RegexIsCaseSensitive: false}, |
97 | {.Regex: "^<protocols/" , .Priority: 5, .SortPriority: 7, .RegexIsCaseSensitive: false}, |
98 | {.Regex: "^<(fs|miscfs|msdosfs|nfs|ntfs|ufs)/" , .Priority: 6, .SortPriority: 8, .RegexIsCaseSensitive: false}, |
99 | {.Regex: "^<(x86|amd64|i386|xen)/" , .Priority: 7, .SortPriority: 8, .RegexIsCaseSensitive: false}, |
100 | {.Regex: "<path" , .Priority: 9, .SortPriority: 11, .RegexIsCaseSensitive: false}, |
101 | {.Regex: "^<[^/].*\\.h>" , .Priority: 8, .SortPriority: 10, .RegexIsCaseSensitive: false}, |
102 | {.Regex: "^\".*\\.h\"" , .Priority: 10, .SortPriority: 12, .RegexIsCaseSensitive: false}}; |
103 | EXPECT_EQ("#include <sys/param.h>\n" |
104 | "#include <sys/types.h>\n" |
105 | "#include <sys/ioctl.h>\n" |
106 | "#include <sys/socket.h>\n" |
107 | "#include <sys/stat.h>\n" |
108 | "#include <sys/wait.h>\n" |
109 | "\n" |
110 | "#include <net/if.h>\n" |
111 | "#include <net/if_dl.h>\n" |
112 | "#include <net/route.h>\n" |
113 | "#include <netinet/in.h>\n" |
114 | "#include <protocols/rwhod.h>\n" |
115 | "\n" |
116 | "#include <assert.h>\n" |
117 | "#include <errno.h>\n" |
118 | "#include <inttypes.h>\n" |
119 | "#include <stdio.h>\n" |
120 | "#include <stdlib.h>\n" |
121 | "\n" |
122 | "#include <paths.h>\n" |
123 | "\n" |
124 | "#include \"pathnames.h\"" , |
125 | sort("#include <sys/param.h>\n" |
126 | "#include <sys/types.h>\n" |
127 | "#include <sys/ioctl.h>\n" |
128 | "#include <net/if_dl.h>\n" |
129 | "#include <net/route.h>\n" |
130 | "#include <netinet/in.h>\n" |
131 | "#include <sys/socket.h>\n" |
132 | "#include <sys/stat.h>\n" |
133 | "#include <sys/wait.h>\n" |
134 | "#include <net/if.h>\n" |
135 | "#include <protocols/rwhod.h>\n" |
136 | "#include <assert.h>\n" |
137 | "#include <paths.h>\n" |
138 | "#include \"pathnames.h\"\n" |
139 | "#include <errno.h>\n" |
140 | "#include <inttypes.h>\n" |
141 | "#include <stdio.h>\n" |
142 | "#include <stdlib.h>" )); |
143 | } |
144 | TEST_F(SortIncludesTest, SortPriorityNotDefined) { |
145 | FmtStyle = getLLVMStyle(); |
146 | EXPECT_EQ("#include \"FormatTestUtils.h\"\n" |
147 | "#include \"clang/Format/Format.h\"\n" |
148 | "#include \"llvm/ADT/None.h\"\n" |
149 | "#include \"llvm/Support/Debug.h\"\n" |
150 | "#include \"gtest/gtest.h\"" , |
151 | sort("#include \"clang/Format/Format.h\"\n" |
152 | "#include \"llvm/ADT/None.h\"\n" |
153 | "#include \"FormatTestUtils.h\"\n" |
154 | "#include \"gtest/gtest.h\"\n" |
155 | "#include \"llvm/Support/Debug.h\"" )); |
156 | } |
157 | |
158 | TEST_F(SortIncludesTest, NoReplacementsForValidIncludes) { |
159 | // Identical #includes have led to a failure with an unstable sort. |
160 | std::string Code = "#include <a>\n" |
161 | "#include <b>\n" |
162 | "#include <c>\n" |
163 | "#include <d>\n" |
164 | "#include <e>\n" |
165 | "#include <f>\n" ; |
166 | EXPECT_TRUE(sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a.cc" ).empty()); |
167 | } |
168 | |
169 | TEST_F(SortIncludesTest, MainFileHeader) { |
170 | std::string Code = "#include <string>\n" |
171 | "\n" |
172 | "#include \"a/extra_action.proto.h\"\n" ; |
173 | FmtStyle = getGoogleStyle(Language: FormatStyle::LK_Cpp); |
174 | EXPECT_TRUE( |
175 | sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a/extra_action.cc" ) |
176 | .empty()); |
177 | |
178 | EXPECT_EQ("#include \"foo.bar.h\"\n" |
179 | "\n" |
180 | "#include \"a.h\"" , |
181 | sort("#include \"a.h\"\n" |
182 | "#include \"foo.bar.h\"" , |
183 | "foo.bar.cc" )); |
184 | } |
185 | |
186 | TEST_F(SortIncludesTest, SortedIncludesInMultipleBlocksAreMerged) { |
187 | Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; |
188 | EXPECT_EQ("#include \"a.h\"\n" |
189 | "#include \"b.h\"\n" |
190 | "#include \"c.h\"" , |
191 | sort("#include \"a.h\"\n" |
192 | "#include \"c.h\"\n" |
193 | "\n" |
194 | "\n" |
195 | "#include \"b.h\"" )); |
196 | |
197 | Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; |
198 | EXPECT_EQ("#include \"a.h\"\n" |
199 | "#include \"b.h\"\n" |
200 | "#include \"c.h\"" , |
201 | sort("#include \"a.h\"\n" |
202 | "#include \"c.h\"\n" |
203 | "\n" |
204 | "\n" |
205 | "#include \"b.h\"" )); |
206 | } |
207 | |
208 | TEST_F(SortIncludesTest, SupportClangFormatOff) { |
209 | EXPECT_EQ("#include <a>\n" |
210 | "#include <b>\n" |
211 | "#include <c>\n" |
212 | "// clang-format off\n" |
213 | "#include <b>\n" |
214 | "#include <a>\n" |
215 | "#include <c>\n" |
216 | "// clang-format on" , |
217 | sort("#include <b>\n" |
218 | "#include <a>\n" |
219 | "#include <c>\n" |
220 | "// clang-format off\n" |
221 | "#include <b>\n" |
222 | "#include <a>\n" |
223 | "#include <c>\n" |
224 | "// clang-format on" )); |
225 | |
226 | Style.IncludeBlocks = Style.IBS_Merge; |
227 | std::string Code = "// clang-format off\r\n" |
228 | "#include \"d.h\"\r\n" |
229 | "#include \"b.h\"\r\n" |
230 | "// clang-format on\r\n" |
231 | "\r\n" |
232 | "#include \"c.h\"\r\n" |
233 | "#include \"a.h\"\r\n" |
234 | "#include \"e.h\"\r\n" ; |
235 | |
236 | std::string Expected = "// clang-format off\r\n" |
237 | "#include \"d.h\"\r\n" |
238 | "#include \"b.h\"\r\n" |
239 | "// clang-format on\r\n" |
240 | "\r\n" |
241 | "#include \"e.h\"\r\n" |
242 | "#include \"a.h\"\r\n" |
243 | "#include \"c.h\"\r\n" ; |
244 | |
245 | EXPECT_EQ(Expected, sort(Code, "e.cpp" , 1)); |
246 | } |
247 | |
248 | TEST_F(SortIncludesTest, SupportClangFormatOffCStyle) { |
249 | EXPECT_EQ("#include <a>\n" |
250 | "#include <b>\n" |
251 | "#include <c>\n" |
252 | "/* clang-format off */\n" |
253 | "#include <b>\n" |
254 | "#include <a>\n" |
255 | "#include <c>\n" |
256 | "/* clang-format on */" , |
257 | sort("#include <b>\n" |
258 | "#include <a>\n" |
259 | "#include <c>\n" |
260 | "/* clang-format off */\n" |
261 | "#include <b>\n" |
262 | "#include <a>\n" |
263 | "#include <c>\n" |
264 | "/* clang-format on */" )); |
265 | |
266 | // Not really turning it off |
267 | EXPECT_EQ("#include <a>\n" |
268 | "#include <b>\n" |
269 | "#include <c>\n" |
270 | "/* clang-format offically */\n" |
271 | "#include <a>\n" |
272 | "#include <b>\n" |
273 | "#include <c>\n" |
274 | "/* clang-format onwards */" , |
275 | sort("#include <b>\n" |
276 | "#include <a>\n" |
277 | "#include <c>\n" |
278 | "/* clang-format offically */\n" |
279 | "#include <b>\n" |
280 | "#include <a>\n" |
281 | "#include <c>\n" |
282 | "/* clang-format onwards */" , |
283 | "input.h" , 2)); |
284 | } |
285 | |
286 | TEST_F(SortIncludesTest, IncludeSortingCanBeDisabled) { |
287 | FmtStyle.SortIncludes = FormatStyle::SI_Never; |
288 | EXPECT_EQ("#include \"a.h\"\n" |
289 | "#include \"c.h\"\n" |
290 | "#include \"b.h\"" , |
291 | sort("#include \"a.h\"\n" |
292 | "#include \"c.h\"\n" |
293 | "#include \"b.h\"" , |
294 | "input.h" , 0)); |
295 | } |
296 | |
297 | TEST_F(SortIncludesTest, MixIncludeAndImport) { |
298 | EXPECT_EQ("#include \"a.h\"\n" |
299 | "#import \"b.h\"\n" |
300 | "#include \"c.h\"" , |
301 | sort("#include \"a.h\"\n" |
302 | "#include \"c.h\"\n" |
303 | "#import \"b.h\"" )); |
304 | } |
305 | |
306 | TEST_F(SortIncludesTest, FixTrailingComments) { |
307 | EXPECT_EQ("#include \"a.h\" // comment\n" |
308 | "#include \"bb.h\" // comment\n" |
309 | "#include \"ccc.h\"" , |
310 | sort("#include \"a.h\" // comment\n" |
311 | "#include \"ccc.h\"\n" |
312 | "#include \"bb.h\" // comment" )); |
313 | } |
314 | |
315 | TEST_F(SortIncludesTest, LeadingWhitespace) { |
316 | EXPECT_EQ("#include \"a.h\"\n" |
317 | "#include \"b.h\"\n" |
318 | "#include \"c.h\"" , |
319 | sort(" #include \"a.h\"\n" |
320 | " #include \"c.h\"\n" |
321 | " #include \"b.h\"" )); |
322 | EXPECT_EQ("#include \"a.h\"\n" |
323 | "#include \"b.h\"\n" |
324 | "#include \"c.h\"" , |
325 | sort("# include \"a.h\"\n" |
326 | "# include \"c.h\"\n" |
327 | "# include \"b.h\"" )); |
328 | EXPECT_EQ("#include \"a.h\"" , sort("#include \"a.h\"\n" |
329 | " #include \"a.h\"" )); |
330 | } |
331 | |
332 | TEST_F(SortIncludesTest, TrailingWhitespace) { |
333 | EXPECT_EQ("#include \"a.h\"\n" |
334 | "#include \"b.h\"\n" |
335 | "#include \"c.h\"" , |
336 | sort("#include \"a.h\" \n" |
337 | "#include \"c.h\" \n" |
338 | "#include \"b.h\" " )); |
339 | EXPECT_EQ("#include \"a.h\"" , sort("#include \"a.h\"\n" |
340 | "#include \"a.h\" " )); |
341 | } |
342 | |
343 | TEST_F(SortIncludesTest, GreaterInComment) { |
344 | EXPECT_EQ("#include \"a.h\"\n" |
345 | "#include \"b.h\" // >\n" |
346 | "#include \"c.h\"" , |
347 | sort("#include \"a.h\"\n" |
348 | "#include \"c.h\"\n" |
349 | "#include \"b.h\" // >" )); |
350 | } |
351 | |
352 | TEST_F(SortIncludesTest, SortsLocallyInEachBlock) { |
353 | EXPECT_EQ("#include \"a.h\"\n" |
354 | "#include \"c.h\"\n" |
355 | "\n" |
356 | "#include \"b.h\"" , |
357 | sort("#include \"a.h\"\n" |
358 | "#include \"c.h\"\n" |
359 | "\n" |
360 | "#include \"b.h\"" , |
361 | "input.h" , 0)); |
362 | } |
363 | |
364 | TEST_F(SortIncludesTest, SortsAllBlocksWhenMerging) { |
365 | Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; |
366 | EXPECT_EQ("#include \"a.h\"\n" |
367 | "#include \"b.h\"\n" |
368 | "#include \"c.h\"" , |
369 | sort("#include \"a.h\"\n" |
370 | "#include \"c.h\"\n" |
371 | "\n" |
372 | "#include \"b.h\"" )); |
373 | } |
374 | |
375 | TEST_F(SortIncludesTest, CommentsAlwaysSeparateGroups) { |
376 | EXPECT_EQ("#include \"a.h\"\n" |
377 | "#include \"c.h\"\n" |
378 | "// comment\n" |
379 | "#include \"b.h\"" , |
380 | sort("#include \"c.h\"\n" |
381 | "#include \"a.h\"\n" |
382 | "// comment\n" |
383 | "#include \"b.h\"" )); |
384 | |
385 | Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; |
386 | EXPECT_EQ("#include \"a.h\"\n" |
387 | "#include \"c.h\"\n" |
388 | "// comment\n" |
389 | "#include \"b.h\"" , |
390 | sort("#include \"c.h\"\n" |
391 | "#include \"a.h\"\n" |
392 | "// comment\n" |
393 | "#include \"b.h\"" )); |
394 | |
395 | Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; |
396 | EXPECT_EQ("#include \"a.h\"\n" |
397 | "#include \"c.h\"\n" |
398 | "// comment\n" |
399 | "#include \"b.h\"" , |
400 | sort("#include \"c.h\"\n" |
401 | "#include \"a.h\"\n" |
402 | "// comment\n" |
403 | "#include \"b.h\"" )); |
404 | } |
405 | |
406 | TEST_F(SortIncludesTest, HandlesAngledIncludesAsSeparateBlocks) { |
407 | EXPECT_EQ("#include \"a.h\"\n" |
408 | "#include \"c.h\"\n" |
409 | "#include <array>\n" |
410 | "#include <b.h>\n" |
411 | "#include <d.h>\n" |
412 | "#include <vector>" , |
413 | sort("#include <vector>\n" |
414 | "#include <d.h>\n" |
415 | "#include <array>\n" |
416 | "#include <b.h>\n" |
417 | "#include \"c.h\"\n" |
418 | "#include \"a.h\"" )); |
419 | |
420 | FmtStyle = getGoogleStyle(Language: FormatStyle::LK_Cpp); |
421 | EXPECT_EQ("#include <b.h>\n" |
422 | "#include <d.h>\n" |
423 | "\n" |
424 | "#include <array>\n" |
425 | "#include <vector>\n" |
426 | "\n" |
427 | "#include \"a.h\"\n" |
428 | "#include \"c.h\"" , |
429 | sort("#include <vector>\n" |
430 | "#include <d.h>\n" |
431 | "#include <array>\n" |
432 | "#include <b.h>\n" |
433 | "#include \"c.h\"\n" |
434 | "#include \"a.h\"" )); |
435 | } |
436 | |
437 | TEST_F(SortIncludesTest, RegroupsAngledIncludesInSeparateBlocks) { |
438 | Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; |
439 | EXPECT_EQ("#include \"a.h\"\n" |
440 | "#include \"c.h\"\n" |
441 | "\n" |
442 | "#include <b.h>\n" |
443 | "#include <d.h>" , |
444 | sort("#include <d.h>\n" |
445 | "#include <b.h>\n" |
446 | "#include \"c.h\"\n" |
447 | "#include \"a.h\"" )); |
448 | } |
449 | |
450 | TEST_F(SortIncludesTest, HandlesMultilineIncludes) { |
451 | EXPECT_EQ("#include \"a.h\"\n" |
452 | "#include \"b.h\"\n" |
453 | "#include \"c.h\"" , |
454 | sort("#include \"a.h\"\n" |
455 | "#include \\\n" |
456 | "\"c.h\"\n" |
457 | "#include \"b.h\"" )); |
458 | } |
459 | |
460 | TEST_F(SortIncludesTest, HandlesTrailingCommentsWithAngleBrackets) { |
461 | // Regression test from the discussion at https://reviews.llvm.org/D121370. |
462 | EXPECT_EQ("#include <cstdint>\n" |
463 | "\n" |
464 | "#include \"util/bar.h\"\n" |
465 | "#include \"util/foo/foo.h\" // foo<T>" , |
466 | sort("#include <cstdint>\n" |
467 | "\n" |
468 | "#include \"util/bar.h\"\n" |
469 | "#include \"util/foo/foo.h\" // foo<T>" , |
470 | /*FileName=*/"input.cc" , |
471 | /*ExpectedNumRanges=*/0)); |
472 | } |
473 | |
474 | TEST_F(SortIncludesTest, LeavesMainHeaderFirst) { |
475 | Style.IncludeIsMainRegex = "([-_](test|unittest))?$" ; |
476 | EXPECT_EQ("#include \"llvm/a.h\"\n" |
477 | "#include \"b.h\"\n" |
478 | "#include \"c.h\"" , |
479 | sort("#include \"llvm/a.h\"\n" |
480 | "#include \"c.h\"\n" |
481 | "#include \"b.h\"" , |
482 | "a.cc" )); |
483 | EXPECT_EQ("#include \"llvm/a.h\"\n" |
484 | "#include \"b.h\"\n" |
485 | "#include \"c.h\"" , |
486 | sort("#include \"llvm/a.h\"\n" |
487 | "#include \"c.h\"\n" |
488 | "#include \"b.h\"" , |
489 | "a_test.cc" )); |
490 | EXPECT_EQ("#include \"llvm/input.h\"\n" |
491 | "#include \"b.h\"\n" |
492 | "#include \"c.h\"" , |
493 | sort("#include \"llvm/input.h\"\n" |
494 | "#include \"c.h\"\n" |
495 | "#include \"b.h\"" , |
496 | "input.mm" )); |
497 | |
498 | // Don't allow prefixes. |
499 | EXPECT_EQ("#include \"b.h\"\n" |
500 | "#include \"c.h\"\n" |
501 | "#include \"llvm/not_a.h\"" , |
502 | sort("#include \"llvm/not_a.h\"\n" |
503 | "#include \"c.h\"\n" |
504 | "#include \"b.h\"" , |
505 | "a.cc" )); |
506 | |
507 | // Don't do this for _main and other suffixes. |
508 | EXPECT_EQ("#include \"b.h\"\n" |
509 | "#include \"c.h\"\n" |
510 | "#include \"llvm/a.h\"" , |
511 | sort("#include \"llvm/a.h\"\n" |
512 | "#include \"c.h\"\n" |
513 | "#include \"b.h\"" , |
514 | "a_main.cc" )); |
515 | |
516 | // Don't do this in headers. |
517 | EXPECT_EQ("#include \"b.h\"\n" |
518 | "#include \"c.h\"\n" |
519 | "#include \"llvm/a.h\"" , |
520 | sort("#include \"llvm/a.h\"\n" |
521 | "#include \"c.h\"\n" |
522 | "#include \"b.h\"" , |
523 | "a.h" )); |
524 | |
525 | // Only do this in the first #include block. |
526 | EXPECT_EQ("#include <a>\n" |
527 | "\n" |
528 | "#include \"b.h\"\n" |
529 | "#include \"c.h\"\n" |
530 | "#include \"llvm/a.h\"" , |
531 | sort("#include <a>\n" |
532 | "\n" |
533 | "#include \"llvm/a.h\"\n" |
534 | "#include \"c.h\"\n" |
535 | "#include \"b.h\"" , |
536 | "a.cc" )); |
537 | |
538 | // Only recognize the first #include with a matching basename as main include. |
539 | EXPECT_EQ("#include \"a.h\"\n" |
540 | "#include \"b.h\"\n" |
541 | "#include \"c.h\"\n" |
542 | "#include \"llvm/a.h\"" , |
543 | sort("#include \"b.h\"\n" |
544 | "#include \"a.h\"\n" |
545 | "#include \"c.h\"\n" |
546 | "#include \"llvm/a.h\"" , |
547 | "a.cc" )); |
548 | } |
549 | |
550 | TEST_F(SortIncludesTest, LeavesMainHeaderFirstInAdditionalExtensions) { |
551 | Style.IncludeIsMainRegex = "([-_](test|unittest))?|(Impl)?$" ; |
552 | EXPECT_EQ("#include \"b.h\"\n" |
553 | "#include \"c.h\"\n" |
554 | "#include \"llvm/a.h\"" , |
555 | sort("#include \"llvm/a.h\"\n" |
556 | "#include \"c.h\"\n" |
557 | "#include \"b.h\"" , |
558 | "a_test.xxx" )); |
559 | EXPECT_EQ("#include \"b.h\"\n" |
560 | "#include \"c.h\"\n" |
561 | "#include \"llvm/a.h\"" , |
562 | sort("#include \"llvm/a.h\"\n" |
563 | "#include \"c.h\"\n" |
564 | "#include \"b.h\"" , |
565 | "aImpl.hpp" )); |
566 | |
567 | // .cpp extension is considered "main" by default |
568 | EXPECT_EQ("#include \"llvm/a.h\"\n" |
569 | "#include \"b.h\"\n" |
570 | "#include \"c.h\"" , |
571 | sort("#include \"llvm/a.h\"\n" |
572 | "#include \"c.h\"\n" |
573 | "#include \"b.h\"" , |
574 | "aImpl.cpp" )); |
575 | EXPECT_EQ("#include \"llvm/a.h\"\n" |
576 | "#include \"b.h\"\n" |
577 | "#include \"c.h\"" , |
578 | sort("#include \"llvm/a.h\"\n" |
579 | "#include \"c.h\"\n" |
580 | "#include \"b.h\"" , |
581 | "a_test.cpp" )); |
582 | |
583 | // Allow additional filenames / extensions |
584 | Style.IncludeIsMainSourceRegex = "(Impl\\.hpp)|(\\.xxx)$" ; |
585 | EXPECT_EQ("#include \"llvm/a.h\"\n" |
586 | "#include \"b.h\"\n" |
587 | "#include \"c.h\"" , |
588 | sort("#include \"llvm/a.h\"\n" |
589 | "#include \"c.h\"\n" |
590 | "#include \"b.h\"" , |
591 | "a_test.xxx" )); |
592 | EXPECT_EQ("#include \"llvm/a.h\"\n" |
593 | "#include \"b.h\"\n" |
594 | "#include \"c.h\"" , |
595 | sort("#include \"llvm/a.h\"\n" |
596 | "#include \"c.h\"\n" |
597 | "#include \"b.h\"" , |
598 | "aImpl.hpp" )); |
599 | } |
600 | |
601 | TEST_F(SortIncludesTest, RecognizeMainHeaderInAllGroups) { |
602 | Style.IncludeIsMainRegex = "([-_](test|unittest))?$" ; |
603 | Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; |
604 | |
605 | EXPECT_EQ("#include \"c.h\"\n" |
606 | "#include \"a.h\"\n" |
607 | "#include \"b.h\"" , |
608 | sort("#include \"b.h\"\n" |
609 | "\n" |
610 | "#include \"a.h\"\n" |
611 | "#include \"c.h\"" , |
612 | "c.cc" )); |
613 | } |
614 | |
615 | TEST_F(SortIncludesTest, MainHeaderIsSeparatedWhenRegroupping) { |
616 | Style.IncludeIsMainRegex = "([-_](test|unittest))?$" ; |
617 | Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; |
618 | |
619 | EXPECT_EQ("#include \"a.h\"\n" |
620 | "\n" |
621 | "#include \"b.h\"\n" |
622 | "#include \"c.h\"" , |
623 | sort("#include \"b.h\"\n" |
624 | "\n" |
625 | "#include \"a.h\"\n" |
626 | "#include \"c.h\"" , |
627 | "a.cc" )); |
628 | } |
629 | |
630 | TEST_F(SortIncludesTest, SupportOptionalCaseSensitiveSorting) { |
631 | EXPECT_FALSE(FmtStyle.SortIncludes == FormatStyle::SI_CaseInsensitive); |
632 | |
633 | FmtStyle.SortIncludes = FormatStyle::SI_CaseInsensitive; |
634 | |
635 | EXPECT_EQ("#include \"A/B.h\"\n" |
636 | "#include \"A/b.h\"\n" |
637 | "#include \"a/b.h\"\n" |
638 | "#include \"B/A.h\"\n" |
639 | "#include \"B/a.h\"" , |
640 | sort("#include \"B/a.h\"\n" |
641 | "#include \"B/A.h\"\n" |
642 | "#include \"A/B.h\"\n" |
643 | "#include \"a/b.h\"\n" |
644 | "#include \"A/b.h\"" , |
645 | "a.h" )); |
646 | |
647 | Style.IncludeBlocks = clang::tooling::IncludeStyle::IBS_Regroup; |
648 | Style.IncludeCategories = { |
649 | {.Regex: "^\"" , .Priority: 1, .SortPriority: 0, .RegexIsCaseSensitive: false}, {.Regex: "^<.*\\.h>$" , .Priority: 2, .SortPriority: 0, .RegexIsCaseSensitive: false}, {.Regex: "^<" , .Priority: 3, .SortPriority: 0, .RegexIsCaseSensitive: false}}; |
650 | |
651 | StringRef UnsortedCode = "#include \"qt.h\"\n" |
652 | "#include <algorithm>\n" |
653 | "#include <qtwhatever.h>\n" |
654 | "#include <Qtwhatever.h>\n" |
655 | "#include <Algorithm>\n" |
656 | "#include \"vlib.h\"\n" |
657 | "#include \"Vlib.h\"\n" |
658 | "#include \"AST.h\"" ; |
659 | |
660 | EXPECT_EQ("#include \"AST.h\"\n" |
661 | "#include \"qt.h\"\n" |
662 | "#include \"Vlib.h\"\n" |
663 | "#include \"vlib.h\"\n" |
664 | "\n" |
665 | "#include <Qtwhatever.h>\n" |
666 | "#include <qtwhatever.h>\n" |
667 | "\n" |
668 | "#include <Algorithm>\n" |
669 | "#include <algorithm>" , |
670 | sort(UnsortedCode)); |
671 | } |
672 | |
673 | TEST_F(SortIncludesTest, SupportCaseInsensitiveMatching) { |
674 | // Setup an regex for main includes so we can cover those as well. |
675 | Style.IncludeIsMainRegex = "([-_](test|unittest))?$" ; |
676 | |
677 | // Ensure both main header detection and grouping work in a case insensitive |
678 | // manner. |
679 | EXPECT_EQ("#include \"llvm/A.h\"\n" |
680 | "#include \"b.h\"\n" |
681 | "#include \"c.h\"\n" |
682 | "#include \"LLVM/z.h\"\n" |
683 | "#include \"llvm/X.h\"\n" |
684 | "#include \"GTest/GTest.h\"\n" |
685 | "#include \"gmock/gmock.h\"" , |
686 | sort("#include \"c.h\"\n" |
687 | "#include \"b.h\"\n" |
688 | "#include \"GTest/GTest.h\"\n" |
689 | "#include \"llvm/A.h\"\n" |
690 | "#include \"gmock/gmock.h\"\n" |
691 | "#include \"llvm/X.h\"\n" |
692 | "#include \"LLVM/z.h\"" , |
693 | "a_TEST.cc" )); |
694 | } |
695 | |
696 | TEST_F(SortIncludesTest, SupportOptionalCaseSensitiveMachting) { |
697 | Style.IncludeBlocks = clang::tooling::IncludeStyle::IBS_Regroup; |
698 | Style.IncludeCategories = {{.Regex: "^\"" , .Priority: 1, .SortPriority: 0, .RegexIsCaseSensitive: false}, |
699 | {.Regex: "^<.*\\.h>$" , .Priority: 2, .SortPriority: 0, .RegexIsCaseSensitive: false}, |
700 | {.Regex: "^<Q[A-Z][^\\.]*>" , .Priority: 3, .SortPriority: 0, .RegexIsCaseSensitive: false}, |
701 | {.Regex: "^<Qt[^\\.]*>" , .Priority: 4, .SortPriority: 0, .RegexIsCaseSensitive: false}, |
702 | {.Regex: "^<" , .Priority: 5, .SortPriority: 0, .RegexIsCaseSensitive: false}}; |
703 | |
704 | StringRef UnsortedCode = "#include <QWidget>\n" |
705 | "#include \"qt.h\"\n" |
706 | "#include <algorithm>\n" |
707 | "#include <windows.h>\n" |
708 | "#include <QLabel>\n" |
709 | "#include \"qa.h\"\n" |
710 | "#include <queue>\n" |
711 | "#include <qtwhatever.h>\n" |
712 | "#include <QtGlobal>" ; |
713 | |
714 | EXPECT_EQ("#include \"qa.h\"\n" |
715 | "#include \"qt.h\"\n" |
716 | "\n" |
717 | "#include <qtwhatever.h>\n" |
718 | "#include <windows.h>\n" |
719 | "\n" |
720 | "#include <QLabel>\n" |
721 | "#include <QWidget>\n" |
722 | "#include <QtGlobal>\n" |
723 | "#include <queue>\n" |
724 | "\n" |
725 | "#include <algorithm>" , |
726 | sort(UnsortedCode)); |
727 | |
728 | Style.IncludeCategories[2].RegexIsCaseSensitive = true; |
729 | Style.IncludeCategories[3].RegexIsCaseSensitive = true; |
730 | EXPECT_EQ("#include \"qa.h\"\n" |
731 | "#include \"qt.h\"\n" |
732 | "\n" |
733 | "#include <qtwhatever.h>\n" |
734 | "#include <windows.h>\n" |
735 | "\n" |
736 | "#include <QLabel>\n" |
737 | "#include <QWidget>\n" |
738 | "\n" |
739 | "#include <QtGlobal>\n" |
740 | "\n" |
741 | "#include <algorithm>\n" |
742 | "#include <queue>" , |
743 | sort(UnsortedCode)); |
744 | } |
745 | |
746 | TEST_F(SortIncludesTest, NegativePriorities) { |
747 | Style.IncludeCategories = {{.Regex: ".*important_os_header.*" , .Priority: -1, .SortPriority: 0, .RegexIsCaseSensitive: false}, |
748 | {.Regex: ".*" , .Priority: 1, .SortPriority: 0, .RegexIsCaseSensitive: false}}; |
749 | EXPECT_EQ("#include \"important_os_header.h\"\n" |
750 | "#include \"c_main.h\"\n" |
751 | "#include \"a_other.h\"" , |
752 | sort("#include \"c_main.h\"\n" |
753 | "#include \"a_other.h\"\n" |
754 | "#include \"important_os_header.h\"" , |
755 | "c_main.cc" )); |
756 | |
757 | // check stable when re-run |
758 | EXPECT_EQ("#include \"important_os_header.h\"\n" |
759 | "#include \"c_main.h\"\n" |
760 | "#include \"a_other.h\"" , |
761 | sort("#include \"important_os_header.h\"\n" |
762 | "#include \"c_main.h\"\n" |
763 | "#include \"a_other.h\"" , |
764 | "c_main.cc" , 0)); |
765 | } |
766 | |
767 | TEST_F(SortIncludesTest, PriorityGroupsAreSeparatedWhenRegroupping) { |
768 | Style.IncludeCategories = {{.Regex: ".*important_os_header.*" , .Priority: -1, .SortPriority: 0, .RegexIsCaseSensitive: false}, |
769 | {.Regex: ".*" , .Priority: 1, .SortPriority: 0, .RegexIsCaseSensitive: false}}; |
770 | Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; |
771 | |
772 | EXPECT_EQ("#include \"important_os_header.h\"\n" |
773 | "\n" |
774 | "#include \"c_main.h\"\n" |
775 | "\n" |
776 | "#include \"a_other.h\"" , |
777 | sort("#include \"c_main.h\"\n" |
778 | "#include \"a_other.h\"\n" |
779 | "#include \"important_os_header.h\"" , |
780 | "c_main.cc" )); |
781 | |
782 | // check stable when re-run |
783 | EXPECT_EQ("#include \"important_os_header.h\"\n" |
784 | "\n" |
785 | "#include \"c_main.h\"\n" |
786 | "\n" |
787 | "#include \"a_other.h\"" , |
788 | sort("#include \"important_os_header.h\"\n" |
789 | "\n" |
790 | "#include \"c_main.h\"\n" |
791 | "\n" |
792 | "#include \"a_other.h\"" , |
793 | "c_main.cc" , 0)); |
794 | } |
795 | |
796 | TEST_F(SortIncludesTest, CalculatesCorrectCursorPosition) { |
797 | std::string Code = "#include <ccc>\n" // Start of line: 0 |
798 | "#include <bbbbbb>\n" // Start of line: 15 |
799 | "#include <a>\n" ; // Start of line: 33 |
800 | EXPECT_EQ(31u, newCursor(Code, 0)); |
801 | EXPECT_EQ(13u, newCursor(Code, 15)); |
802 | EXPECT_EQ(0u, newCursor(Code, 33)); |
803 | |
804 | EXPECT_EQ(41u, newCursor(Code, 10)); |
805 | EXPECT_EQ(23u, newCursor(Code, 25)); |
806 | EXPECT_EQ(10u, newCursor(Code, 43)); |
807 | } |
808 | |
809 | TEST_F(SortIncludesTest, CalculatesCorrectCursorPositionWithRegrouping) { |
810 | Style.IncludeBlocks = Style.IBS_Regroup; |
811 | std::string Code = "#include \"b\"\n" // Start of line: 0 |
812 | "\n" // Start of line: 13 |
813 | "#include \"aa\"\n" // Start of line: 14 |
814 | "int i;" ; // Start of line: 28 |
815 | std::string Expected = "#include \"aa\"\n" // Start of line: 0 |
816 | "#include \"b\"\n" // Start of line: 14 |
817 | "int i;" ; // Start of line: 27 |
818 | EXPECT_EQ(Expected, sort(Code)); |
819 | EXPECT_EQ(12u, newCursor(Code, 26)); // Closing quote of "aa" |
820 | EXPECT_EQ(26u, newCursor(Code, 27)); // Newline after "aa" |
821 | EXPECT_EQ(27u, newCursor(Code, 28)); // Start of last line |
822 | } |
823 | |
824 | TEST_F(SortIncludesTest, DeduplicateIncludes) { |
825 | EXPECT_EQ("#include <a>\n" |
826 | "#include <b>\n" |
827 | "#include <c>" , |
828 | sort("#include <a>\n" |
829 | "#include <b>\n" |
830 | "#include <b>\n" |
831 | "#include <b>\n" |
832 | "#include <b>\n" |
833 | "#include <c>" )); |
834 | |
835 | Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; |
836 | EXPECT_EQ("#include <a>\n" |
837 | "#include <b>\n" |
838 | "#include <c>" , |
839 | sort("#include <a>\n" |
840 | "#include <b>\n" |
841 | "\n" |
842 | "#include <b>\n" |
843 | "\n" |
844 | "#include <b>\n" |
845 | "#include <c>" )); |
846 | |
847 | Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; |
848 | EXPECT_EQ("#include <a>\n" |
849 | "#include <b>\n" |
850 | "#include <c>" , |
851 | sort("#include <a>\n" |
852 | "#include <b>\n" |
853 | "\n" |
854 | "#include <b>\n" |
855 | "\n" |
856 | "#include <b>\n" |
857 | "#include <c>" )); |
858 | } |
859 | |
860 | TEST_F(SortIncludesTest, SortAndDeduplicateIncludes) { |
861 | EXPECT_EQ("#include <a>\n" |
862 | "#include <b>\n" |
863 | "#include <c>" , |
864 | sort("#include <b>\n" |
865 | "#include <a>\n" |
866 | "#include <b>\n" |
867 | "#include <b>\n" |
868 | "#include <c>\n" |
869 | "#include <b>" )); |
870 | |
871 | Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge; |
872 | EXPECT_EQ("#include <a>\n" |
873 | "#include <b>\n" |
874 | "#include <c>" , |
875 | sort("#include <b>\n" |
876 | "#include <a>\n" |
877 | "\n" |
878 | "#include <b>\n" |
879 | "\n" |
880 | "#include <c>\n" |
881 | "#include <b>" )); |
882 | |
883 | Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; |
884 | EXPECT_EQ("#include <a>\n" |
885 | "#include <b>\n" |
886 | "#include <c>" , |
887 | sort("#include <b>\n" |
888 | "#include <a>\n" |
889 | "\n" |
890 | "#include <b>\n" |
891 | "\n" |
892 | "#include <c>\n" |
893 | "#include <b>" )); |
894 | } |
895 | |
896 | TEST_F(SortIncludesTest, CalculatesCorrectCursorPositionAfterDeduplicate) { |
897 | std::string Code = "#include <b>\n" // Start of line: 0 |
898 | "#include <a>\n" // Start of line: 13 |
899 | "#include <b>\n" // Start of line: 26 |
900 | "#include <b>\n" // Start of line: 39 |
901 | "#include <c>\n" // Start of line: 52 |
902 | "#include <b>\n" ; // Start of line: 65 |
903 | std::string Expected = "#include <a>\n" // Start of line: 0 |
904 | "#include <b>\n" // Start of line: 13 |
905 | "#include <c>\n" ; // Start of line: 26 |
906 | EXPECT_EQ(Expected, sort(Code)); |
907 | // Cursor on 'i' in "#include <a>". |
908 | EXPECT_EQ(1u, newCursor(Code, 14)); |
909 | // Cursor on 'b' in "#include <b>". |
910 | EXPECT_EQ(23u, newCursor(Code, 10)); |
911 | EXPECT_EQ(23u, newCursor(Code, 36)); |
912 | EXPECT_EQ(23u, newCursor(Code, 49)); |
913 | EXPECT_EQ(23u, newCursor(Code, 36)); |
914 | EXPECT_EQ(23u, newCursor(Code, 75)); |
915 | // Cursor on '#' in "#include <c>". |
916 | EXPECT_EQ(26u, newCursor(Code, 52)); |
917 | } |
918 | |
919 | TEST_F(SortIncludesTest, DeduplicateLocallyInEachBlock) { |
920 | EXPECT_EQ("#include <a>\n" |
921 | "#include <b>\n" |
922 | "\n" |
923 | "#include <b>\n" |
924 | "#include <c>" , |
925 | sort("#include <a>\n" |
926 | "#include <b>\n" |
927 | "\n" |
928 | "#include <c>\n" |
929 | "#include <b>\n" |
930 | "#include <b>" )); |
931 | } |
932 | |
933 | TEST_F(SortIncludesTest, ValidAffactedRangesAfterDeduplicatingIncludes) { |
934 | std::string Code = "#include <a>\n" |
935 | "#include <b>\n" |
936 | "#include <a>\n" |
937 | "#include <a>\n" |
938 | "\n" |
939 | " int x ;" ; |
940 | std::vector<tooling::Range> Ranges = {tooling::Range(0, 52)}; |
941 | auto Replaces = sortIncludes(Style: FmtStyle, Code, Ranges, FileName: "input.cpp" ); |
942 | Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges); |
943 | EXPECT_EQ(1u, Ranges.size()); |
944 | EXPECT_EQ(0u, Ranges[0].getOffset()); |
945 | EXPECT_EQ(26u, Ranges[0].getLength()); |
946 | } |
947 | |
948 | TEST_F(SortIncludesTest, DoNotSortLikelyXml) { |
949 | EXPECT_EQ("<!--;\n" |
950 | "#include <b>\n" |
951 | "#include <a>\n" |
952 | "-->" , |
953 | sort("<!--;\n" |
954 | "#include <b>\n" |
955 | "#include <a>\n" |
956 | "-->" , |
957 | "input.h" , 0)); |
958 | } |
959 | |
960 | TEST_F(SortIncludesTest, DoNotOutputReplacementsForSortedBlocksWithRegrouping) { |
961 | Style.IncludeBlocks = Style.IBS_Regroup; |
962 | std::string Code = R"( |
963 | #include "b.h" |
964 | |
965 | #include <a.h> |
966 | )" ; |
967 | EXPECT_EQ(Code, sort(Code, "input.h" , 0)); |
968 | } |
969 | |
970 | TEST_F(SortIncludesTest, |
971 | DoNotOutputReplacementsForSortedBlocksWithRegroupingWindows) { |
972 | Style.IncludeBlocks = Style.IBS_Regroup; |
973 | std::string Code = "#include \"b.h\"\r\n" |
974 | "\r\n" |
975 | "#include <a.h>\r\n" ; |
976 | EXPECT_EQ(Code, sort(Code, "input.h" , 0)); |
977 | } |
978 | |
979 | TEST_F(SortIncludesTest, MainIncludeChar) { |
980 | std::string Code = "#include <a>\n" |
981 | "#include \"quote/input.h\"\n" |
982 | "#include <angle-bracket/input.h>\n" ; |
983 | |
984 | // Default behavior |
985 | EXPECT_EQ("#include \"quote/input.h\"\n" |
986 | "#include <a>\n" |
987 | "#include <angle-bracket/input.h>\n" , |
988 | sort(Code, "input.cc" , 1)); |
989 | |
990 | Style.MainIncludeChar = tooling::IncludeStyle::MICD_Quote; |
991 | EXPECT_EQ("#include \"quote/input.h\"\n" |
992 | "#include <a>\n" |
993 | "#include <angle-bracket/input.h>\n" , |
994 | sort(Code, "input.cc" , 1)); |
995 | |
996 | Style.MainIncludeChar = tooling::IncludeStyle::MICD_AngleBracket; |
997 | EXPECT_EQ("#include <angle-bracket/input.h>\n" |
998 | "#include \"quote/input.h\"\n" |
999 | "#include <a>\n" , |
1000 | sort(Code, "input.cc" , 1)); |
1001 | } |
1002 | |
1003 | TEST_F(SortIncludesTest, MainIncludeCharAnyPickQuote) { |
1004 | Style.MainIncludeChar = tooling::IncludeStyle::MICD_Any; |
1005 | EXPECT_EQ("#include \"input.h\"\n" |
1006 | "#include <a>\n" |
1007 | "#include <b>\n" , |
1008 | sort("#include <a>\n" |
1009 | "#include \"input.h\"\n" |
1010 | "#include <b>\n" , |
1011 | "input.cc" , 1)); |
1012 | } |
1013 | |
1014 | TEST_F(SortIncludesTest, MainIncludeCharAnyPickAngleBracket) { |
1015 | Style.MainIncludeChar = tooling::IncludeStyle::MICD_Any; |
1016 | EXPECT_EQ("#include <input.h>\n" |
1017 | "#include <a>\n" |
1018 | "#include <b>\n" , |
1019 | sort("#include <a>\n" |
1020 | "#include <input.h>\n" |
1021 | "#include <b>\n" , |
1022 | "input.cc" , 1)); |
1023 | } |
1024 | |
1025 | TEST_F(SortIncludesTest, MainIncludeCharQuoteAndRegroup) { |
1026 | Style.IncludeCategories = { |
1027 | {.Regex: "lib-a" , .Priority: 1, .SortPriority: 0, .RegexIsCaseSensitive: false}, {.Regex: "lib-b" , .Priority: 2, .SortPriority: 0, .RegexIsCaseSensitive: false}, {.Regex: "lib-c" , .Priority: 3, .SortPriority: 0, .RegexIsCaseSensitive: false}}; |
1028 | Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; |
1029 | Style.MainIncludeChar = tooling::IncludeStyle::MICD_Quote; |
1030 | |
1031 | EXPECT_EQ("#include \"lib-b/input.h\"\n" |
1032 | "\n" |
1033 | "#include <lib-a/h-1.h>\n" |
1034 | "#include <lib-a/h-3.h>\n" |
1035 | "#include <lib-a/input.h>\n" |
1036 | "\n" |
1037 | "#include <lib-b/h-1.h>\n" |
1038 | "#include <lib-b/h-3.h>\n" |
1039 | "\n" |
1040 | "#include <lib-c/h-1.h>\n" |
1041 | "#include <lib-c/h-2.h>\n" |
1042 | "#include <lib-c/h-3.h>\n" , |
1043 | sort("#include <lib-c/h-1.h>\n" |
1044 | "#include <lib-c/h-2.h>\n" |
1045 | "#include <lib-c/h-3.h>\n" |
1046 | "#include <lib-b/h-1.h>\n" |
1047 | "#include \"lib-b/input.h\"\n" |
1048 | "#include <lib-b/h-3.h>\n" |
1049 | "#include <lib-a/h-1.h>\n" |
1050 | "#include <lib-a/input.h>\n" |
1051 | "#include <lib-a/h-3.h>\n" , |
1052 | "input.cc" )); |
1053 | } |
1054 | |
1055 | TEST_F(SortIncludesTest, MainIncludeCharAngleBracketAndRegroup) { |
1056 | Style.IncludeCategories = { |
1057 | {.Regex: "lib-a" , .Priority: 1, .SortPriority: 0, .RegexIsCaseSensitive: false}, {.Regex: "lib-b" , .Priority: 2, .SortPriority: 0, .RegexIsCaseSensitive: false}, {.Regex: "lib-c" , .Priority: 3, .SortPriority: 0, .RegexIsCaseSensitive: false}}; |
1058 | Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup; |
1059 | Style.MainIncludeChar = tooling::IncludeStyle::MICD_AngleBracket; |
1060 | |
1061 | EXPECT_EQ("#include <lib-a/input.h>\n" |
1062 | "\n" |
1063 | "#include <lib-a/h-1.h>\n" |
1064 | "#include <lib-a/h-3.h>\n" |
1065 | "\n" |
1066 | "#include \"lib-b/input.h\"\n" |
1067 | "#include <lib-b/h-1.h>\n" |
1068 | "#include <lib-b/h-3.h>\n" |
1069 | "\n" |
1070 | "#include <lib-c/h-1.h>\n" |
1071 | "#include <lib-c/h-2.h>\n" |
1072 | "#include <lib-c/h-3.h>\n" , |
1073 | sort("#include <lib-c/h-1.h>\n" |
1074 | "#include <lib-c/h-2.h>\n" |
1075 | "#include <lib-c/h-3.h>\n" |
1076 | "#include <lib-b/h-1.h>\n" |
1077 | "#include \"lib-b/input.h\"\n" |
1078 | "#include <lib-b/h-3.h>\n" |
1079 | "#include <lib-a/h-1.h>\n" |
1080 | "#include <lib-a/input.h>\n" |
1081 | "#include <lib-a/h-3.h>\n" , |
1082 | "input.cc" )); |
1083 | } |
1084 | |
1085 | TEST_F(SortIncludesTest, DoNotRegroupGroupsInGoogleObjCStyle) { |
1086 | FmtStyle = getGoogleStyle(Language: FormatStyle::LK_ObjC); |
1087 | |
1088 | EXPECT_EQ("#include <a.h>\n" |
1089 | "#include <b.h>\n" |
1090 | "#include \"a.h\"" , |
1091 | sort("#include <b.h>\n" |
1092 | "#include <a.h>\n" |
1093 | "#include \"a.h\"" )); |
1094 | } |
1095 | |
1096 | TEST_F(SortIncludesTest, DoNotTreatPrecompiledHeadersAsFirstBlock) { |
1097 | Style.IncludeBlocks = Style.IBS_Merge; |
1098 | std::string Code = "#include \"d.h\"\r\n" |
1099 | "#include \"b.h\"\r\n" |
1100 | "#pragma hdrstop\r\n" |
1101 | "\r\n" |
1102 | "#include \"c.h\"\r\n" |
1103 | "#include \"a.h\"\r\n" |
1104 | "#include \"e.h\"\r\n" ; |
1105 | |
1106 | std::string Expected = "#include \"b.h\"\r\n" |
1107 | "#include \"d.h\"\r\n" |
1108 | "#pragma hdrstop\r\n" |
1109 | "\r\n" |
1110 | "#include \"e.h\"\r\n" |
1111 | "#include \"a.h\"\r\n" |
1112 | "#include \"c.h\"\r\n" ; |
1113 | |
1114 | EXPECT_EQ(Expected, sort(Code, "e.cpp" , 2)); |
1115 | |
1116 | Code = "#include \"d.h\"\n" |
1117 | "#include \"b.h\"\n" |
1118 | "#pragma hdrstop( \"c:\\projects\\include\\myinc.pch\" )\n" |
1119 | "\n" |
1120 | "#include \"c.h\"\n" |
1121 | "#include \"a.h\"\n" |
1122 | "#include \"e.h\"\n" ; |
1123 | |
1124 | Expected = "#include \"b.h\"\n" |
1125 | "#include \"d.h\"\n" |
1126 | "#pragma hdrstop(\"c:\\projects\\include\\myinc.pch\")\n" |
1127 | "\n" |
1128 | "#include \"e.h\"\n" |
1129 | "#include \"a.h\"\n" |
1130 | "#include \"c.h\"\n" ; |
1131 | |
1132 | EXPECT_EQ(Expected, sort(Code, "e.cpp" , 2)); |
1133 | } |
1134 | |
1135 | TEST_F(SortIncludesTest, skipUTF8ByteOrderMarkMerge) { |
1136 | Style.IncludeBlocks = Style.IBS_Merge; |
1137 | std::string Code = "\xEF\xBB\xBF#include \"d.h\"\r\n" |
1138 | "#include \"b.h\"\r\n" |
1139 | "\r\n" |
1140 | "#include \"c.h\"\r\n" |
1141 | "#include \"a.h\"\r\n" |
1142 | "#include \"e.h\"\r\n" ; |
1143 | |
1144 | std::string Expected = "\xEF\xBB\xBF#include \"e.h\"\r\n" |
1145 | "#include \"a.h\"\r\n" |
1146 | "#include \"b.h\"\r\n" |
1147 | "#include \"c.h\"\r\n" |
1148 | "#include \"d.h\"\r\n" ; |
1149 | |
1150 | EXPECT_EQ(Expected, sort(Code, "e.cpp" , 1)); |
1151 | } |
1152 | |
1153 | TEST_F(SortIncludesTest, skipUTF8ByteOrderMarkPreserve) { |
1154 | Style.IncludeBlocks = Style.IBS_Preserve; |
1155 | std::string Code = "\xEF\xBB\xBF#include \"d.h\"\r\n" |
1156 | "#include \"b.h\"\r\n" |
1157 | "\r\n" |
1158 | "#include \"c.h\"\r\n" |
1159 | "#include \"a.h\"\r\n" |
1160 | "#include \"e.h\"\r\n" ; |
1161 | |
1162 | std::string Expected = "\xEF\xBB\xBF#include \"b.h\"\r\n" |
1163 | "#include \"d.h\"\r\n" |
1164 | "\r\n" |
1165 | "#include \"a.h\"\r\n" |
1166 | "#include \"c.h\"\r\n" |
1167 | "#include \"e.h\"\r\n" ; |
1168 | |
1169 | EXPECT_EQ(Expected, sort(Code, "e.cpp" , 2)); |
1170 | } |
1171 | |
1172 | TEST_F(SortIncludesTest, MergeLines) { |
1173 | Style.IncludeBlocks = Style.IBS_Merge; |
1174 | std::string Code = "#include \"c.h\"\r\n" |
1175 | "#include \"b\\\r\n" |
1176 | ".h\"\r\n" |
1177 | "#include \"a.h\"\r\n" ; |
1178 | |
1179 | std::string Expected = "#include \"a.h\"\r\n" |
1180 | "#include \"b\\\r\n" |
1181 | ".h\"\r\n" |
1182 | "#include \"c.h\"\r\n" ; |
1183 | |
1184 | EXPECT_EQ(Expected, sort(Code, "a.cpp" , 1)); |
1185 | } |
1186 | |
1187 | TEST_F(SortIncludesTest, DisableFormatDisablesIncludeSorting) { |
1188 | StringRef Sorted = "#include <a.h>\n" |
1189 | "#include <b.h>\n" ; |
1190 | StringRef Unsorted = "#include <b.h>\n" |
1191 | "#include <a.h>\n" ; |
1192 | EXPECT_EQ(Sorted, sort(Unsorted)); |
1193 | FmtStyle.DisableFormat = true; |
1194 | EXPECT_EQ(Unsorted, sort(Unsorted, "input.cpp" , 0)); |
1195 | } |
1196 | |
1197 | TEST_F(SortIncludesTest, DisableRawStringLiteralSorting) { |
1198 | |
1199 | EXPECT_EQ("const char *t = R\"(\n" |
1200 | "#include <b.h>\n" |
1201 | "#include <a.h>\n" |
1202 | ")\";" , |
1203 | sort("const char *t = R\"(\n" |
1204 | "#include <b.h>\n" |
1205 | "#include <a.h>\n" |
1206 | ")\";" , |
1207 | "test.cxx" , 0)); |
1208 | EXPECT_EQ("const char *t = R\"x(\n" |
1209 | "#include <b.h>\n" |
1210 | "#include <a.h>\n" |
1211 | ")x\";" , |
1212 | sort("const char *t = R\"x(\n" |
1213 | "#include <b.h>\n" |
1214 | "#include <a.h>\n" |
1215 | ")x\";" , |
1216 | "test.cxx" , 0)); |
1217 | EXPECT_EQ("const char *t = R\"xyz(\n" |
1218 | "#include <b.h>\n" |
1219 | "#include <a.h>\n" |
1220 | ")xyz\";" , |
1221 | sort("const char *t = R\"xyz(\n" |
1222 | "#include <b.h>\n" |
1223 | "#include <a.h>\n" |
1224 | ")xyz\";" , |
1225 | "test.cxx" , 0)); |
1226 | |
1227 | EXPECT_EQ("#include <a.h>\n" |
1228 | "#include <b.h>\n" |
1229 | "const char *t = R\"(\n" |
1230 | "#include <b.h>\n" |
1231 | "#include <a.h>\n" |
1232 | ")\";\n" |
1233 | "#include <c.h>\n" |
1234 | "#include <d.h>\n" |
1235 | "const char *t = R\"x(\n" |
1236 | "#include <f.h>\n" |
1237 | "#include <e.h>\n" |
1238 | ")x\";\n" |
1239 | "#include <g.h>\n" |
1240 | "#include <h.h>\n" |
1241 | "const char *t = R\"xyz(\n" |
1242 | "#include <j.h>\n" |
1243 | "#include <i.h>\n" |
1244 | ")xyz\";\n" |
1245 | "#include <k.h>\n" |
1246 | "#include <l.h>" , |
1247 | sort("#include <b.h>\n" |
1248 | "#include <a.h>\n" |
1249 | "const char *t = R\"(\n" |
1250 | "#include <b.h>\n" |
1251 | "#include <a.h>\n" |
1252 | ")\";\n" |
1253 | "#include <d.h>\n" |
1254 | "#include <c.h>\n" |
1255 | "const char *t = R\"x(\n" |
1256 | "#include <f.h>\n" |
1257 | "#include <e.h>\n" |
1258 | ")x\";\n" |
1259 | "#include <h.h>\n" |
1260 | "#include <g.h>\n" |
1261 | "const char *t = R\"xyz(\n" |
1262 | "#include <j.h>\n" |
1263 | "#include <i.h>\n" |
1264 | ")xyz\";\n" |
1265 | "#include <l.h>\n" |
1266 | "#include <k.h>" , |
1267 | "test.cc" , 4)); |
1268 | |
1269 | EXPECT_EQ("const char *t = R\"AMZ029amz(\n" |
1270 | "#include <b.h>\n" |
1271 | "#include <a.h>\n" |
1272 | ")AMZ029amz\";" , |
1273 | sort("const char *t = R\"AMZ029amz(\n" |
1274 | "#include <b.h>\n" |
1275 | "#include <a.h>\n" |
1276 | ")AMZ029amz\";" , |
1277 | "test.cxx" , 0)); |
1278 | |
1279 | EXPECT_EQ("const char *t = R\"-AMZ029amz(\n" |
1280 | "#include <b.h>\n" |
1281 | "#include <a.h>\n" |
1282 | ")-AMZ029amz\";" , |
1283 | sort("const char *t = R\"-AMZ029amz(\n" |
1284 | "#include <b.h>\n" |
1285 | "#include <a.h>\n" |
1286 | ")-AMZ029amz\";" , |
1287 | "test.cxx" , 0)); |
1288 | |
1289 | EXPECT_EQ("const char *t = R\"AMZ029amz-(\n" |
1290 | "#include <b.h>\n" |
1291 | "#include <a.h>\n" |
1292 | ")AMZ029amz-\";" , |
1293 | sort("const char *t = R\"AMZ029amz-(\n" |
1294 | "#include <b.h>\n" |
1295 | "#include <a.h>\n" |
1296 | ")AMZ029amz-\";" , |
1297 | "test.cxx" , 0)); |
1298 | |
1299 | EXPECT_EQ("const char *t = R\"AM|029amz-(\n" |
1300 | "#include <b.h>\n" |
1301 | "#include <a.h>\n" |
1302 | ")AM|029amz-\";" , |
1303 | sort("const char *t = R\"AM|029amz-(\n" |
1304 | "#include <b.h>\n" |
1305 | "#include <a.h>\n" |
1306 | ")AM|029amz-\";" , |
1307 | "test.cxx" , 0)); |
1308 | |
1309 | EXPECT_EQ("const char *t = R\"AM[029amz-(\n" |
1310 | "#include <b.h>\n" |
1311 | "#include <a.h>\n" |
1312 | ")AM[029amz-\";" , |
1313 | sort("const char *t = R\"AM[029amz-(\n" |
1314 | "#include <b.h>\n" |
1315 | "#include <a.h>\n" |
1316 | ")AM[029amz-\";" , |
1317 | "test.cxx" , 0)); |
1318 | |
1319 | EXPECT_EQ("const char *t = R\"AM]029amz-(\n" |
1320 | "#include <b.h>\n" |
1321 | "#include <a.h>\n" |
1322 | ")AM]029amz-\";" , |
1323 | sort("const char *t = R\"AM]029amz-(\n" |
1324 | "#include <b.h>\n" |
1325 | "#include <a.h>\n" |
1326 | ")AM]029amz-\";" , |
1327 | "test.cxx" , 0)); |
1328 | |
1329 | #define X "AMZ029amz{}+!%*=_:;',.<>|/?#~-$" |
1330 | |
1331 | EXPECT_EQ("const char *t = R\"" X "(\n" |
1332 | "#include <b.h>\n" |
1333 | "#include <a.h>\n" |
1334 | ")" X "\";" , |
1335 | sort("const char *t = R\"" X "(\n" |
1336 | "#include <b.h>\n" |
1337 | "#include <a.h>\n" |
1338 | ")" X "\";" , |
1339 | "test.cxx" , 0)); |
1340 | |
1341 | #undef X |
1342 | } |
1343 | |
1344 | } // end namespace |
1345 | } // end namespace format |
1346 | } // end namespace clang |
1347 | |