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, NegativePriorities) {
270   Style.IncludeCategories = {{".*important_os_header.*", -1}, {".*", 1}};
271   EXPECT_EQ("#include \"important_os_header.h\"\n"
272             "#include \"c_main.h\"\n"
273             "#include \"a_other.h\"\n",
274             sort("#include \"c_main.h\"\n"
275                  "#include \"a_other.h\"\n"
276                  "#include \"important_os_header.h\"\n",
277                  "c_main.cc"));
278 
279   // check stable when re-run
280   EXPECT_EQ("#include \"important_os_header.h\"\n"
281             "#include \"c_main.h\"\n"
282             "#include \"a_other.h\"\n",
283             sort("#include \"important_os_header.h\"\n"
284                  "#include \"c_main.h\"\n"
285                  "#include \"a_other.h\"\n",
286                  "c_main.cc"));
287 }
288 
289 TEST_F(SortIncludesTest, CalculatesCorrectCursorPosition) {
290   std::string Code = "#include <ccc>\n"    // Start of line: 0
291                      "#include <bbbbbb>\n" // Start of line: 15
292                      "#include <a>\n";     // Start of line: 33
293   EXPECT_EQ(31u, newCursor(Code, 0));
294   EXPECT_EQ(13u, newCursor(Code, 15));
295   EXPECT_EQ(0u, newCursor(Code, 33));
296 
297   EXPECT_EQ(41u, newCursor(Code, 10));
298   EXPECT_EQ(23u, newCursor(Code, 25));
299   EXPECT_EQ(10u, newCursor(Code, 43));
300 }
301 
302 TEST_F(SortIncludesTest, DeduplicateIncludes) {
303   EXPECT_EQ("#include <a>\n"
304             "#include <b>\n"
305             "#include <c>\n",
306             sort("#include <a>\n"
307                  "#include <b>\n"
308                  "#include <b>\n"
309                  "#include <b>\n"
310                  "#include <b>\n"
311                  "#include <c>\n"));
312 }
313 
314 TEST_F(SortIncludesTest, SortAndDeduplicateIncludes) {
315   EXPECT_EQ("#include <a>\n"
316             "#include <b>\n"
317             "#include <c>\n",
318             sort("#include <b>\n"
319                  "#include <a>\n"
320                  "#include <b>\n"
321                  "#include <b>\n"
322                  "#include <c>\n"
323                  "#include <b>\n"));
324 }
325 
326 TEST_F(SortIncludesTest, CalculatesCorrectCursorPositionAfterDeduplicate) {
327   std::string Code = "#include <b>\n"      // Start of line: 0
328                      "#include <a>\n"      // Start of line: 13
329                      "#include <b>\n"      // Start of line: 26
330                      "#include <b>\n"      // Start of line: 39
331                      "#include <c>\n"      // Start of line: 52
332                      "#include <b>\n";     // Start of line: 65
333   std::string Expected = "#include <a>\n"  // Start of line: 0
334                          "#include <b>\n"  // Start of line: 13
335                          "#include <c>\n"; // Start of line: 26
336   EXPECT_EQ(Expected, sort(Code));
337   // Cursor on 'i' in "#include <a>".
338   EXPECT_EQ(1u, newCursor(Code, 14));
339   // Cursor on 'b' in "#include <b>".
340   EXPECT_EQ(23u, newCursor(Code, 10));
341   EXPECT_EQ(23u, newCursor(Code, 36));
342   EXPECT_EQ(23u, newCursor(Code, 49));
343   EXPECT_EQ(23u, newCursor(Code, 36));
344   EXPECT_EQ(23u, newCursor(Code, 75));
345   // Cursor on '#' in "#include <c>".
346   EXPECT_EQ(26u, newCursor(Code, 52));
347 }
348 
349 TEST_F(SortIncludesTest, DeduplicateLocallyInEachBlock) {
350   EXPECT_EQ("#include <a>\n"
351             "#include <b>\n"
352             "\n"
353             "#include <b>\n"
354             "#include <c>\n",
355             sort("#include <a>\n"
356                  "#include <b>\n"
357                  "\n"
358                  "#include <c>\n"
359                  "#include <b>\n"
360                  "#include <b>\n"));
361 }
362 
363 TEST_F(SortIncludesTest, ValidAffactedRangesAfterDeduplicatingIncludes) {
364   std::string Code = "#include <a>\n"
365                      "#include <b>\n"
366                      "#include <a>\n"
367                      "#include <a>\n"
368                      "\n"
369                      "   int     x ;";
370   std::vector<tooling::Range> Ranges = {tooling::Range(0, 52)};
371   auto Replaces = sortIncludes(Style, Code, Ranges, "input.cpp");
372   Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
373   EXPECT_EQ(1u, Ranges.size());
374   EXPECT_EQ(0u, Ranges[0].getOffset());
375   EXPECT_EQ(26u, Ranges[0].getLength());
376 }
377 
378 } // end namespace
379 } // end namespace format
380 } // end namespace clang
381