1 //===- unittest/Format/SortIncludesTest.cpp - Include sort unit tests -----===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "FormatTestUtils.h"
11 #include "clang/Format/Format.h"
12 #include "llvm/Support/Debug.h"
13 #include "gtest/gtest.h"
15 #define DEBUG_TYPE "format-test"
21 class SortIncludesTest : public ::testing::Test {
23 std::vector<tooling::Range> GetCodeRange(StringRef Code) {
24 return std::vector<tooling::Range>(1, tooling::Range(0, Code.size()));
27 std::string sort(StringRef Code, std::vector<tooling::Range> Ranges,
28 StringRef FileName = "input.cc") {
29 auto Replaces = sortIncludes(FmtStyle, Code, Ranges, FileName);
30 Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
31 auto Sorted = applyAllReplacements(Code, Replaces);
32 EXPECT_TRUE(static_cast<bool>(Sorted));
33 auto Result = applyAllReplacements(
34 *Sorted, reformat(FmtStyle, *Sorted, Ranges, FileName));
35 EXPECT_TRUE(static_cast<bool>(Result));
39 std::string sort(StringRef Code, StringRef FileName = "input.cpp") {
40 return sort(Code, GetCodeRange(Code), FileName);
43 unsigned newCursor(llvm::StringRef Code, unsigned Cursor) {
44 sortIncludes(FmtStyle, Code, GetCodeRange(Code), "input.cpp", &Cursor);
48 FormatStyle FmtStyle = getLLVMStyle();
49 tooling::IncludeStyle &Style = FmtStyle.IncludeStyle;
52 TEST_F(SortIncludesTest, BasicSorting) {
53 EXPECT_EQ("#include \"a.h\"\n"
56 sort("#include \"a.h\"\n"
58 "#include \"b.h\"\n"));
60 EXPECT_EQ("// comment\n"
66 {tooling::Range(25, 1)}));
69 TEST_F(SortIncludesTest, NoReplacementsForValidIncludes) {
70 // Identical #includes have led to a failure with an unstable sort.
71 std::string Code = "#include <a>\n"
77 EXPECT_TRUE(sortIncludes(FmtStyle, Code, GetCodeRange(Code), "a.cc").empty());
80 TEST_F(SortIncludesTest, SortedIncludesInMultipleBlocksAreMerged) {
81 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
82 EXPECT_EQ("#include \"a.h\"\n"
85 sort("#include \"a.h\"\n"
89 "#include \"b.h\"\n"));
91 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
92 EXPECT_EQ("#include \"a.h\"\n"
95 sort("#include \"a.h\"\n"
99 "#include \"b.h\"\n"));
102 TEST_F(SortIncludesTest, SupportClangFormatOff) {
103 EXPECT_EQ("#include <a>\n"
106 "// clang-format off\n"
110 "// clang-format on\n",
111 sort("#include <b>\n"
114 "// clang-format off\n"
118 "// clang-format on\n"));
121 TEST_F(SortIncludesTest, IncludeSortingCanBeDisabled) {
122 FmtStyle.SortIncludes = false;
123 EXPECT_EQ("#include \"a.h\"\n"
125 "#include \"b.h\"\n",
126 sort("#include \"a.h\"\n"
128 "#include \"b.h\"\n"));
131 TEST_F(SortIncludesTest, MixIncludeAndImport) {
132 EXPECT_EQ("#include \"a.h\"\n"
134 "#include \"c.h\"\n",
135 sort("#include \"a.h\"\n"
137 "#import \"b.h\"\n"));
140 TEST_F(SortIncludesTest, FixTrailingComments) {
141 EXPECT_EQ("#include \"a.h\" // comment\n"
142 "#include \"bb.h\" // comment\n"
143 "#include \"ccc.h\"\n",
144 sort("#include \"a.h\" // comment\n"
145 "#include \"ccc.h\"\n"
146 "#include \"bb.h\" // comment\n"));
149 TEST_F(SortIncludesTest, LeadingWhitespace) {
150 EXPECT_EQ("#include \"a.h\"\n"
152 "#include \"c.h\"\n",
153 sort(" #include \"a.h\"\n"
154 " #include \"c.h\"\n"
155 " #include \"b.h\"\n"));
156 EXPECT_EQ("#include \"a.h\"\n"
158 "#include \"c.h\"\n",
159 sort("# include \"a.h\"\n"
160 "# include \"c.h\"\n"
161 "# include \"b.h\"\n"));
164 TEST_F(SortIncludesTest, GreaterInComment) {
165 EXPECT_EQ("#include \"a.h\"\n"
166 "#include \"b.h\" // >\n"
167 "#include \"c.h\"\n",
168 sort("#include \"a.h\"\n"
170 "#include \"b.h\" // >\n"));
173 TEST_F(SortIncludesTest, SortsLocallyInEachBlock) {
174 EXPECT_EQ("#include \"a.h\"\n"
177 "#include \"b.h\"\n",
178 sort("#include \"a.h\"\n"
181 "#include \"b.h\"\n"));
184 TEST_F(SortIncludesTest, SortsAllBlocksWhenMerging) {
185 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
186 EXPECT_EQ("#include \"a.h\"\n"
188 "#include \"c.h\"\n",
189 sort("#include \"a.h\"\n"
192 "#include \"b.h\"\n"));
195 TEST_F(SortIncludesTest, CommentsAlwaysSeparateGroups) {
196 EXPECT_EQ("#include \"a.h\"\n"
199 "#include \"b.h\"\n",
200 sort("#include \"c.h\"\n"
203 "#include \"b.h\"\n"));
205 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
206 EXPECT_EQ("#include \"a.h\"\n"
209 "#include \"b.h\"\n",
210 sort("#include \"c.h\"\n"
213 "#include \"b.h\"\n"));
215 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
216 EXPECT_EQ("#include \"a.h\"\n"
219 "#include \"b.h\"\n",
220 sort("#include \"c.h\"\n"
223 "#include \"b.h\"\n"));
226 TEST_F(SortIncludesTest, HandlesAngledIncludesAsSeparateBlocks) {
227 EXPECT_EQ("#include \"a.h\"\n"
231 sort("#include <d.h>\n"
234 "#include \"a.h\"\n"));
236 FmtStyle = getGoogleStyle(FormatStyle::LK_Cpp);
237 EXPECT_EQ("#include <b.h>\n"
240 "#include \"c.h\"\n",
241 sort("#include <d.h>\n"
244 "#include \"a.h\"\n"));
247 TEST_F(SortIncludesTest, RegroupsAngledIncludesInSeparateBlocks) {
248 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
249 EXPECT_EQ("#include \"a.h\"\n"
254 sort("#include <d.h>\n"
257 "#include \"a.h\"\n"));
260 TEST_F(SortIncludesTest, HandlesMultilineIncludes) {
261 EXPECT_EQ("#include \"a.h\"\n"
263 "#include \"c.h\"\n",
264 sort("#include \"a.h\"\n"
267 "#include \"b.h\"\n"));
270 TEST_F(SortIncludesTest, LeavesMainHeaderFirst) {
271 Style.IncludeIsMainRegex = "([-_](test|unittest))?$";
272 EXPECT_EQ("#include \"llvm/a.h\"\n"
274 "#include \"c.h\"\n",
275 sort("#include \"llvm/a.h\"\n"
277 "#include \"b.h\"\n",
279 EXPECT_EQ("#include \"llvm/a.h\"\n"
281 "#include \"c.h\"\n",
282 sort("#include \"llvm/a.h\"\n"
284 "#include \"b.h\"\n",
286 EXPECT_EQ("#include \"llvm/input.h\"\n"
288 "#include \"c.h\"\n",
289 sort("#include \"llvm/input.h\"\n"
291 "#include \"b.h\"\n",
294 // Don't allow prefixes.
295 EXPECT_EQ("#include \"b.h\"\n"
297 "#include \"llvm/not_a.h\"\n",
298 sort("#include \"llvm/not_a.h\"\n"
300 "#include \"b.h\"\n",
303 // Don't do this for _main and other suffixes.
304 EXPECT_EQ("#include \"b.h\"\n"
306 "#include \"llvm/a.h\"\n",
307 sort("#include \"llvm/a.h\"\n"
309 "#include \"b.h\"\n",
312 // Don't do this in headers.
313 EXPECT_EQ("#include \"b.h\"\n"
315 "#include \"llvm/a.h\"\n",
316 sort("#include \"llvm/a.h\"\n"
318 "#include \"b.h\"\n",
321 // Only do this in the first #include block.
322 EXPECT_EQ("#include <a>\n"
326 "#include \"llvm/a.h\"\n",
327 sort("#include <a>\n"
329 "#include \"llvm/a.h\"\n"
331 "#include \"b.h\"\n",
334 // Only recognize the first #include with a matching basename as main include.
335 EXPECT_EQ("#include \"a.h\"\n"
338 "#include \"llvm/a.h\"\n",
339 sort("#include \"b.h\"\n"
342 "#include \"llvm/a.h\"\n",
346 TEST_F(SortIncludesTest, RecognizeMainHeaderInAllGroups) {
347 Style.IncludeIsMainRegex = "([-_](test|unittest))?$";
348 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
350 EXPECT_EQ("#include \"c.h\"\n"
352 "#include \"b.h\"\n",
353 sort("#include \"b.h\"\n"
356 "#include \"c.h\"\n",
360 TEST_F(SortIncludesTest, MainHeaderIsSeparatedWhenRegroupping) {
361 Style.IncludeIsMainRegex = "([-_](test|unittest))?$";
362 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
364 EXPECT_EQ("#include \"a.h\"\n"
367 "#include \"c.h\"\n",
368 sort("#include \"b.h\"\n"
371 "#include \"c.h\"\n",
375 TEST_F(SortIncludesTest, SupportCaseInsensitiveMatching) {
376 // Setup an regex for main includes so we can cover those as well.
377 Style.IncludeIsMainRegex = "([-_](test|unittest))?$";
379 // Ensure both main header detection and grouping work in a case insensitive
381 EXPECT_EQ("#include \"llvm/A.h\"\n"
384 "#include \"LLVM/z.h\"\n"
385 "#include \"llvm/X.h\"\n"
386 "#include \"GTest/GTest.h\"\n"
387 "#include \"gmock/gmock.h\"\n",
388 sort("#include \"c.h\"\n"
390 "#include \"GTest/GTest.h\"\n"
391 "#include \"llvm/A.h\"\n"
392 "#include \"gmock/gmock.h\"\n"
393 "#include \"llvm/X.h\"\n"
394 "#include \"LLVM/z.h\"\n",
398 TEST_F(SortIncludesTest, NegativePriorities) {
399 Style.IncludeCategories = {{".*important_os_header.*", -1}, {".*", 1}};
400 EXPECT_EQ("#include \"important_os_header.h\"\n"
401 "#include \"c_main.h\"\n"
402 "#include \"a_other.h\"\n",
403 sort("#include \"c_main.h\"\n"
404 "#include \"a_other.h\"\n"
405 "#include \"important_os_header.h\"\n",
408 // check stable when re-run
409 EXPECT_EQ("#include \"important_os_header.h\"\n"
410 "#include \"c_main.h\"\n"
411 "#include \"a_other.h\"\n",
412 sort("#include \"important_os_header.h\"\n"
413 "#include \"c_main.h\"\n"
414 "#include \"a_other.h\"\n",
418 TEST_F(SortIncludesTest, PriorityGroupsAreSeparatedWhenRegroupping) {
419 Style.IncludeCategories = {{".*important_os_header.*", -1}, {".*", 1}};
420 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
422 EXPECT_EQ("#include \"important_os_header.h\"\n"
424 "#include \"c_main.h\"\n"
426 "#include \"a_other.h\"\n",
427 sort("#include \"c_main.h\"\n"
428 "#include \"a_other.h\"\n"
429 "#include \"important_os_header.h\"\n",
432 // check stable when re-run
433 EXPECT_EQ("#include \"important_os_header.h\"\n"
435 "#include \"c_main.h\"\n"
437 "#include \"a_other.h\"\n",
438 sort("#include \"important_os_header.h\"\n"
440 "#include \"c_main.h\"\n"
442 "#include \"a_other.h\"\n",
446 TEST_F(SortIncludesTest, CalculatesCorrectCursorPosition) {
447 std::string Code = "#include <ccc>\n" // Start of line: 0
448 "#include <bbbbbb>\n" // Start of line: 15
449 "#include <a>\n"; // Start of line: 33
450 EXPECT_EQ(31u, newCursor(Code, 0));
451 EXPECT_EQ(13u, newCursor(Code, 15));
452 EXPECT_EQ(0u, newCursor(Code, 33));
454 EXPECT_EQ(41u, newCursor(Code, 10));
455 EXPECT_EQ(23u, newCursor(Code, 25));
456 EXPECT_EQ(10u, newCursor(Code, 43));
459 TEST_F(SortIncludesTest, DeduplicateIncludes) {
460 EXPECT_EQ("#include <a>\n"
463 sort("#include <a>\n"
470 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
471 EXPECT_EQ("#include <a>\n"
474 sort("#include <a>\n"
482 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
483 EXPECT_EQ("#include <a>\n"
486 sort("#include <a>\n"
495 TEST_F(SortIncludesTest, SortAndDeduplicateIncludes) {
496 EXPECT_EQ("#include <a>\n"
499 sort("#include <b>\n"
506 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Merge;
507 EXPECT_EQ("#include <a>\n"
510 sort("#include <b>\n"
518 Style.IncludeBlocks = tooling::IncludeStyle::IBS_Regroup;
519 EXPECT_EQ("#include <a>\n"
522 sort("#include <b>\n"
531 TEST_F(SortIncludesTest, CalculatesCorrectCursorPositionAfterDeduplicate) {
532 std::string Code = "#include <b>\n" // Start of line: 0
533 "#include <a>\n" // Start of line: 13
534 "#include <b>\n" // Start of line: 26
535 "#include <b>\n" // Start of line: 39
536 "#include <c>\n" // Start of line: 52
537 "#include <b>\n"; // Start of line: 65
538 std::string Expected = "#include <a>\n" // Start of line: 0
539 "#include <b>\n" // Start of line: 13
540 "#include <c>\n"; // Start of line: 26
541 EXPECT_EQ(Expected, sort(Code));
542 // Cursor on 'i' in "#include <a>".
543 EXPECT_EQ(1u, newCursor(Code, 14));
544 // Cursor on 'b' in "#include <b>".
545 EXPECT_EQ(23u, newCursor(Code, 10));
546 EXPECT_EQ(23u, newCursor(Code, 36));
547 EXPECT_EQ(23u, newCursor(Code, 49));
548 EXPECT_EQ(23u, newCursor(Code, 36));
549 EXPECT_EQ(23u, newCursor(Code, 75));
550 // Cursor on '#' in "#include <c>".
551 EXPECT_EQ(26u, newCursor(Code, 52));
554 TEST_F(SortIncludesTest, DeduplicateLocallyInEachBlock) {
555 EXPECT_EQ("#include <a>\n"
560 sort("#include <a>\n"
568 TEST_F(SortIncludesTest, ValidAffactedRangesAfterDeduplicatingIncludes) {
569 std::string Code = "#include <a>\n"
575 std::vector<tooling::Range> Ranges = {tooling::Range(0, 52)};
576 auto Replaces = sortIncludes(FmtStyle, Code, Ranges, "input.cpp");
577 Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
578 EXPECT_EQ(1u, Ranges.size());
579 EXPECT_EQ(0u, Ranges[0].getOffset());
580 EXPECT_EQ(26u, Ranges[0].getLength());
583 TEST_F(SortIncludesTest, DoNotSortLikelyXml) {
595 } // end namespace format
596 } // end namespace clang