1 //===- unittest/Format/SortIncludesTest.cpp - Include sort unit tests -----===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "FormatTestUtils.h"
11 #include "clang/Format/Format.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     auto Replaces = sortIncludes(Style, 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(Style, *Sorted, Ranges, FileName));
35     EXPECT_TRUE(static_cast<bool>(Result));
36     return *Result;
37   }
38 
39   std::string sort(StringRef Code, StringRef FileName = "input.cpp") {
40     return sort(Code, GetCodeRange(Code), FileName);
41   }
42 
43   unsigned newCursor(llvm::StringRef Code, unsigned Cursor) {
44     sortIncludes(Style, Code, GetCodeRange(Code), "input.cpp", &Cursor);
45     return Cursor;
46   }
47 
48   FormatStyle Style = getLLVMStyle();
49 
50 };
51 
52 TEST_F(SortIncludesTest, BasicSorting) {
53   EXPECT_EQ("#include \"a.h\"\n"
54             "#include \"b.h\"\n"
55             "#include \"c.h\"\n",
56             sort("#include \"a.h\"\n"
57                  "#include \"c.h\"\n"
58                  "#include \"b.h\"\n"));
59 
60   EXPECT_EQ("// comment\n"
61             "#include <a>\n"
62             "#include <b>\n",
63             sort("// comment\n"
64                  "#include <b>\n"
65                  "#include <a>\n",
66                  {tooling::Range(25, 1)}));
67 }
68 
69 TEST_F(SortIncludesTest, NoReplacementsForValidIncludes) {
70   // Identical #includes have led to a failure with an unstable sort.
71   std::string Code = "#include <a>\n"
72                      "#include <b>\n"
73                      "#include <c>\n"
74                      "#include <d>\n"
75                      "#include <e>\n"
76                      "#include <f>\n";
77   EXPECT_TRUE(sortIncludes(Style, Code, GetCodeRange(Code), "a.cc").empty());
78 }
79 
80 TEST_F(SortIncludesTest, SupportClangFormatOff) {
81   EXPECT_EQ("#include <a>\n"
82             "#include <b>\n"
83             "#include <c>\n"
84             "// clang-format off\n"
85             "#include <b>\n"
86             "#include <a>\n"
87             "#include <c>\n"
88             "// clang-format on\n",
89             sort("#include <b>\n"
90                  "#include <a>\n"
91                  "#include <c>\n"
92                  "// clang-format off\n"
93                  "#include <b>\n"
94                  "#include <a>\n"
95                  "#include <c>\n"
96                  "// clang-format on\n"));
97 }
98 
99 TEST_F(SortIncludesTest, IncludeSortingCanBeDisabled) {
100   Style.SortIncludes = false;
101   EXPECT_EQ("#include \"a.h\"\n"
102             "#include \"c.h\"\n"
103             "#include \"b.h\"\n",
104             sort("#include \"a.h\"\n"
105                  "#include \"c.h\"\n"
106                  "#include \"b.h\"\n"));
107 }
108 
109 TEST_F(SortIncludesTest, MixIncludeAndImport) {
110   EXPECT_EQ("#include \"a.h\"\n"
111             "#import \"b.h\"\n"
112             "#include \"c.h\"\n",
113             sort("#include \"a.h\"\n"
114                  "#include \"c.h\"\n"
115                  "#import \"b.h\"\n"));
116 }
117 
118 TEST_F(SortIncludesTest, FixTrailingComments) {
119   EXPECT_EQ("#include \"a.h\"  // comment\n"
120             "#include \"bb.h\" // comment\n"
121             "#include \"ccc.h\"\n",
122             sort("#include \"a.h\" // comment\n"
123                  "#include \"ccc.h\"\n"
124                  "#include \"bb.h\" // comment\n"));
125 }
126 
127 TEST_F(SortIncludesTest, LeadingWhitespace) {
128   EXPECT_EQ("#include \"a.h\"\n"
129             "#include \"b.h\"\n"
130             "#include \"c.h\"\n",
131             sort(" #include \"a.h\"\n"
132                  "  #include \"c.h\"\n"
133                  "   #include \"b.h\"\n"));
134   EXPECT_EQ("#include \"a.h\"\n"
135             "#include \"b.h\"\n"
136             "#include \"c.h\"\n",
137             sort("# include \"a.h\"\n"
138                  "#  include \"c.h\"\n"
139                  "#   include \"b.h\"\n"));
140 }
141 
142 TEST_F(SortIncludesTest, GreaterInComment) {
143   EXPECT_EQ("#include \"a.h\"\n"
144             "#include \"b.h\" // >\n"
145             "#include \"c.h\"\n",
146             sort("#include \"a.h\"\n"
147                  "#include \"c.h\"\n"
148                  "#include \"b.h\" // >\n"));
149 }
150 
151 TEST_F(SortIncludesTest, SortsLocallyInEachBlock) {
152   EXPECT_EQ("#include \"a.h\"\n"
153             "#include \"c.h\"\n"
154             "\n"
155             "#include \"b.h\"\n",
156             sort("#include \"a.h\"\n"
157                  "#include \"c.h\"\n"
158                  "\n"
159                  "#include \"b.h\"\n"));
160 }
161 
162 TEST_F(SortIncludesTest, HandlesAngledIncludesAsSeparateBlocks) {
163   EXPECT_EQ("#include \"a.h\"\n"
164             "#include \"c.h\"\n"
165             "#include <b.h>\n"
166             "#include <d.h>\n",
167             sort("#include <d.h>\n"
168                  "#include <b.h>\n"
169                  "#include \"c.h\"\n"
170                  "#include \"a.h\"\n"));
171 
172   Style = getGoogleStyle(FormatStyle::LK_Cpp);
173   EXPECT_EQ("#include <b.h>\n"
174             "#include <d.h>\n"
175             "#include \"a.h\"\n"
176             "#include \"c.h\"\n",
177             sort("#include <d.h>\n"
178                  "#include <b.h>\n"
179                  "#include \"c.h\"\n"
180                  "#include \"a.h\"\n"));
181 }
182 
183 TEST_F(SortIncludesTest, HandlesMultilineIncludes) {
184   EXPECT_EQ("#include \"a.h\"\n"
185             "#include \"b.h\"\n"
186             "#include \"c.h\"\n",
187             sort("#include \"a.h\"\n"
188                  "#include \\\n"
189                  "\"c.h\"\n"
190                  "#include \"b.h\"\n"));
191 }
192 
193 TEST_F(SortIncludesTest, LeavesMainHeaderFirst) {
194   Style.IncludeIsMainRegex = "([-_](test|unittest))?$";
195   EXPECT_EQ("#include \"llvm/a.h\"\n"
196             "#include \"b.h\"\n"
197             "#include \"c.h\"\n",
198             sort("#include \"llvm/a.h\"\n"
199                  "#include \"c.h\"\n"
200                  "#include \"b.h\"\n",
201                  "a.cc"));
202   EXPECT_EQ("#include \"llvm/a.h\"\n"
203             "#include \"b.h\"\n"
204             "#include \"c.h\"\n",
205             sort("#include \"llvm/a.h\"\n"
206                  "#include \"c.h\"\n"
207                  "#include \"b.h\"\n",
208                  "a_test.cc"));
209   EXPECT_EQ("#include \"llvm/input.h\"\n"
210             "#include \"b.h\"\n"
211             "#include \"c.h\"\n",
212             sort("#include \"llvm/input.h\"\n"
213                  "#include \"c.h\"\n"
214                  "#include \"b.h\"\n",
215                  "input.mm"));
216 
217   // Don't allow prefixes.
218   EXPECT_EQ("#include \"b.h\"\n"
219             "#include \"c.h\"\n"
220             "#include \"llvm/not_a.h\"\n",
221             sort("#include \"llvm/not_a.h\"\n"
222                  "#include \"c.h\"\n"
223                  "#include \"b.h\"\n",
224                  "a.cc"));
225 
226   // Don't do this for _main and other suffixes.
227   EXPECT_EQ("#include \"b.h\"\n"
228             "#include \"c.h\"\n"
229             "#include \"llvm/a.h\"\n",
230             sort("#include \"llvm/a.h\"\n"
231                  "#include \"c.h\"\n"
232                  "#include \"b.h\"\n",
233                  "a_main.cc"));
234 
235   // Don't do this in headers.
236   EXPECT_EQ("#include \"b.h\"\n"
237             "#include \"c.h\"\n"
238             "#include \"llvm/a.h\"\n",
239             sort("#include \"llvm/a.h\"\n"
240                  "#include \"c.h\"\n"
241                  "#include \"b.h\"\n",
242                  "a.h"));
243 
244   // Only do this in the first #include block.
245   EXPECT_EQ("#include <a>\n"
246             "\n"
247             "#include \"b.h\"\n"
248             "#include \"c.h\"\n"
249             "#include \"llvm/a.h\"\n",
250             sort("#include <a>\n"
251                  "\n"
252                  "#include \"llvm/a.h\"\n"
253                  "#include \"c.h\"\n"
254                  "#include \"b.h\"\n",
255                  "a.cc"));
256 
257   // Only recognize the first #include with a matching basename as main include.
258   EXPECT_EQ("#include \"a.h\"\n"
259             "#include \"b.h\"\n"
260             "#include \"c.h\"\n"
261             "#include \"llvm/a.h\"\n",
262             sort("#include \"b.h\"\n"
263                  "#include \"a.h\"\n"
264                  "#include \"c.h\"\n"
265                  "#include \"llvm/a.h\"\n",
266                  "a.cc"));
267 }
268 
269 TEST_F(SortIncludesTest, SupportCaseInsensitiveMatching) {
270   // Setup an regex for main includes so we can cover those as well.
271   Style.IncludeIsMainRegex = "([-_](test|unittest))?$";
272 
273   // Ensure both main header detection and grouping work in a case insensitive
274   // manner.
275   EXPECT_EQ("#include \"llvm/A.h\"\n"
276             "#include \"b.h\"\n"
277             "#include \"c.h\"\n"
278             "#include \"LLVM/z.h\"\n"
279             "#include \"llvm/X.h\"\n"
280             "#include \"GTest/GTest.h\"\n"
281             "#include \"gmock/gmock.h\"\n",
282             sort("#include \"c.h\"\n"
283                  "#include \"b.h\"\n"
284                  "#include \"GTest/GTest.h\"\n"
285                  "#include \"llvm/A.h\"\n"
286                  "#include \"gmock/gmock.h\"\n"
287                  "#include \"llvm/X.h\"\n"
288                  "#include \"LLVM/z.h\"\n",
289                  "a_TEST.cc"));
290 }
291 
292 TEST_F(SortIncludesTest, NegativePriorities) {
293   Style.IncludeCategories = {{".*important_os_header.*", -1}, {".*", 1}};
294   EXPECT_EQ("#include \"important_os_header.h\"\n"
295             "#include \"c_main.h\"\n"
296             "#include \"a_other.h\"\n",
297             sort("#include \"c_main.h\"\n"
298                  "#include \"a_other.h\"\n"
299                  "#include \"important_os_header.h\"\n",
300                  "c_main.cc"));
301 
302   // check stable when re-run
303   EXPECT_EQ("#include \"important_os_header.h\"\n"
304             "#include \"c_main.h\"\n"
305             "#include \"a_other.h\"\n",
306             sort("#include \"important_os_header.h\"\n"
307                  "#include \"c_main.h\"\n"
308                  "#include \"a_other.h\"\n",
309                  "c_main.cc"));
310 }
311 
312 TEST_F(SortIncludesTest, CalculatesCorrectCursorPosition) {
313   std::string Code = "#include <ccc>\n"    // Start of line: 0
314                      "#include <bbbbbb>\n" // Start of line: 15
315                      "#include <a>\n";     // Start of line: 33
316   EXPECT_EQ(31u, newCursor(Code, 0));
317   EXPECT_EQ(13u, newCursor(Code, 15));
318   EXPECT_EQ(0u, newCursor(Code, 33));
319 
320   EXPECT_EQ(41u, newCursor(Code, 10));
321   EXPECT_EQ(23u, newCursor(Code, 25));
322   EXPECT_EQ(10u, newCursor(Code, 43));
323 }
324 
325 TEST_F(SortIncludesTest, DeduplicateIncludes) {
326   EXPECT_EQ("#include <a>\n"
327             "#include <b>\n"
328             "#include <c>\n",
329             sort("#include <a>\n"
330                  "#include <b>\n"
331                  "#include <b>\n"
332                  "#include <b>\n"
333                  "#include <b>\n"
334                  "#include <c>\n"));
335 }
336 
337 TEST_F(SortIncludesTest, SortAndDeduplicateIncludes) {
338   EXPECT_EQ("#include <a>\n"
339             "#include <b>\n"
340             "#include <c>\n",
341             sort("#include <b>\n"
342                  "#include <a>\n"
343                  "#include <b>\n"
344                  "#include <b>\n"
345                  "#include <c>\n"
346                  "#include <b>\n"));
347 }
348 
349 TEST_F(SortIncludesTest, CalculatesCorrectCursorPositionAfterDeduplicate) {
350   std::string Code = "#include <b>\n"      // Start of line: 0
351                      "#include <a>\n"      // Start of line: 13
352                      "#include <b>\n"      // Start of line: 26
353                      "#include <b>\n"      // Start of line: 39
354                      "#include <c>\n"      // Start of line: 52
355                      "#include <b>\n";     // Start of line: 65
356   std::string Expected = "#include <a>\n"  // Start of line: 0
357                          "#include <b>\n"  // Start of line: 13
358                          "#include <c>\n"; // Start of line: 26
359   EXPECT_EQ(Expected, sort(Code));
360   // Cursor on 'i' in "#include <a>".
361   EXPECT_EQ(1u, newCursor(Code, 14));
362   // Cursor on 'b' in "#include <b>".
363   EXPECT_EQ(23u, newCursor(Code, 10));
364   EXPECT_EQ(23u, newCursor(Code, 36));
365   EXPECT_EQ(23u, newCursor(Code, 49));
366   EXPECT_EQ(23u, newCursor(Code, 36));
367   EXPECT_EQ(23u, newCursor(Code, 75));
368   // Cursor on '#' in "#include <c>".
369   EXPECT_EQ(26u, newCursor(Code, 52));
370 }
371 
372 TEST_F(SortIncludesTest, DeduplicateLocallyInEachBlock) {
373   EXPECT_EQ("#include <a>\n"
374             "#include <b>\n"
375             "\n"
376             "#include <b>\n"
377             "#include <c>\n",
378             sort("#include <a>\n"
379                  "#include <b>\n"
380                  "\n"
381                  "#include <c>\n"
382                  "#include <b>\n"
383                  "#include <b>\n"));
384 }
385 
386 TEST_F(SortIncludesTest, ValidAffactedRangesAfterDeduplicatingIncludes) {
387   std::string Code = "#include <a>\n"
388                      "#include <b>\n"
389                      "#include <a>\n"
390                      "#include <a>\n"
391                      "\n"
392                      "   int     x ;";
393   std::vector<tooling::Range> Ranges = {tooling::Range(0, 52)};
394   auto Replaces = sortIncludes(Style, Code, Ranges, "input.cpp");
395   Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
396   EXPECT_EQ(1u, Ranges.size());
397   EXPECT_EQ(0u, Ranges[0].getOffset());
398   EXPECT_EQ(26u, Ranges[0].getLength());
399 }
400 
401 TEST_F(SortIncludesTest, DoNotSortLikelyXml) {
402   EXPECT_EQ("<!--;\n"
403             "#include <b>\n"
404             "#include <a>\n"
405             "-->",
406             sort("<!--;\n"
407                  "#include <b>\n"
408                  "#include <a>\n"
409                  "-->"));
410 }
411 
412 } // end namespace
413 } // end namespace format
414 } // end namespace clang
415