• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
GetCodeRange(StringRef Code)23   std::vector<tooling::Range> GetCodeRange(StringRef Code) {
24     return std::vector<tooling::Range>(1, tooling::Range(0, Code.size()));
25   }
26 
sort(StringRef Code,StringRef FileName="input.cpp")27   std::string sort(StringRef Code, StringRef FileName = "input.cpp") {
28     auto Ranges = GetCodeRange(Code);
29     auto Sorted =
30         applyAllReplacements(Code, sortIncludes(Style, Code, Ranges, FileName));
31     EXPECT_TRUE(static_cast<bool>(Sorted));
32     auto Result = applyAllReplacements(
33         *Sorted, reformat(Style, *Sorted, Ranges, FileName));
34     EXPECT_TRUE(static_cast<bool>(Result));
35     return *Result;
36   }
37 
newCursor(llvm::StringRef Code,unsigned Cursor)38   unsigned newCursor(llvm::StringRef Code, unsigned Cursor) {
39     sortIncludes(Style, Code, GetCodeRange(Code), "input.cpp", &Cursor);
40     return Cursor;
41   }
42 
43   FormatStyle Style = getLLVMStyle();
44 
45 };
46 
TEST_F(SortIncludesTest,BasicSorting)47 TEST_F(SortIncludesTest, BasicSorting) {
48   EXPECT_EQ("#include \"a.h\"\n"
49             "#include \"b.h\"\n"
50             "#include \"c.h\"\n",
51             sort("#include \"a.h\"\n"
52                  "#include \"c.h\"\n"
53                  "#include \"b.h\"\n"));
54 }
55 
TEST_F(SortIncludesTest,NoReplacementsForValidIncludes)56 TEST_F(SortIncludesTest, NoReplacementsForValidIncludes) {
57   // Identical #includes have led to a failure with an unstable sort.
58   std::string Code = "#include <a>\n"
59                      "#include <b>\n"
60                      "#include <b>\n"
61                      "#include <b>\n"
62                      "#include <b>\n"
63                      "#include <c>\n";
64   EXPECT_TRUE(sortIncludes(Style, Code, GetCodeRange(Code), "a.cc").empty());
65 }
66 
TEST_F(SortIncludesTest,SupportClangFormatOff)67 TEST_F(SortIncludesTest, SupportClangFormatOff) {
68   EXPECT_EQ("#include <a>\n"
69             "#include <b>\n"
70             "#include <c>\n"
71             "// clang-format off\n"
72             "#include <b>\n"
73             "#include <a>\n"
74             "#include <c>\n"
75             "// clang-format on\n",
76             sort("#include <b>\n"
77                  "#include <a>\n"
78                  "#include <c>\n"
79                  "// clang-format off\n"
80                  "#include <b>\n"
81                  "#include <a>\n"
82                  "#include <c>\n"
83                  "// clang-format on\n"));
84 }
85 
TEST_F(SortIncludesTest,IncludeSortingCanBeDisabled)86 TEST_F(SortIncludesTest, IncludeSortingCanBeDisabled) {
87   Style.SortIncludes = false;
88   EXPECT_EQ("#include \"a.h\"\n"
89             "#include \"c.h\"\n"
90             "#include \"b.h\"\n",
91             sort("#include \"a.h\"\n"
92                  "#include \"c.h\"\n"
93                  "#include \"b.h\"\n"));
94 }
95 
TEST_F(SortIncludesTest,MixIncludeAndImport)96 TEST_F(SortIncludesTest, MixIncludeAndImport) {
97   EXPECT_EQ("#include \"a.h\"\n"
98             "#import \"b.h\"\n"
99             "#include \"c.h\"\n",
100             sort("#include \"a.h\"\n"
101                  "#include \"c.h\"\n"
102                  "#import \"b.h\"\n"));
103 }
104 
TEST_F(SortIncludesTest,FixTrailingComments)105 TEST_F(SortIncludesTest, FixTrailingComments) {
106   EXPECT_EQ("#include \"a.h\"  // comment\n"
107             "#include \"bb.h\" // comment\n"
108             "#include \"ccc.h\"\n",
109             sort("#include \"a.h\" // comment\n"
110                  "#include \"ccc.h\"\n"
111                  "#include \"bb.h\" // comment\n"));
112 }
113 
TEST_F(SortIncludesTest,LeadingWhitespace)114 TEST_F(SortIncludesTest, LeadingWhitespace) {
115   EXPECT_EQ("#include \"a.h\"\n"
116             "#include \"b.h\"\n"
117             "#include \"c.h\"\n",
118             sort(" #include \"a.h\"\n"
119                  "  #include \"c.h\"\n"
120                  "   #include \"b.h\"\n"));
121   EXPECT_EQ("#include \"a.h\"\n"
122             "#include \"b.h\"\n"
123             "#include \"c.h\"\n",
124             sort("# include \"a.h\"\n"
125                  "#  include \"c.h\"\n"
126                  "#   include \"b.h\"\n"));
127 }
128 
TEST_F(SortIncludesTest,GreaterInComment)129 TEST_F(SortIncludesTest, GreaterInComment) {
130   EXPECT_EQ("#include \"a.h\"\n"
131             "#include \"b.h\" // >\n"
132             "#include \"c.h\"\n",
133             sort("#include \"a.h\"\n"
134                  "#include \"c.h\"\n"
135                  "#include \"b.h\" // >\n"));
136 }
137 
TEST_F(SortIncludesTest,SortsLocallyInEachBlock)138 TEST_F(SortIncludesTest, SortsLocallyInEachBlock) {
139   EXPECT_EQ("#include \"a.h\"\n"
140             "#include \"c.h\"\n"
141             "\n"
142             "#include \"b.h\"\n",
143             sort("#include \"a.h\"\n"
144                  "#include \"c.h\"\n"
145                  "\n"
146                  "#include \"b.h\"\n"));
147 }
148 
TEST_F(SortIncludesTest,HandlesAngledIncludesAsSeparateBlocks)149 TEST_F(SortIncludesTest, HandlesAngledIncludesAsSeparateBlocks) {
150   EXPECT_EQ("#include \"a.h\"\n"
151             "#include \"c.h\"\n"
152             "#include <b.h>\n"
153             "#include <d.h>\n",
154             sort("#include <d.h>\n"
155                  "#include <b.h>\n"
156                  "#include \"c.h\"\n"
157                  "#include \"a.h\"\n"));
158 
159   Style = getGoogleStyle(FormatStyle::LK_Cpp);
160   EXPECT_EQ("#include <b.h>\n"
161             "#include <d.h>\n"
162             "#include \"a.h\"\n"
163             "#include \"c.h\"\n",
164             sort("#include <d.h>\n"
165                  "#include <b.h>\n"
166                  "#include \"c.h\"\n"
167                  "#include \"a.h\"\n"));
168 }
169 
TEST_F(SortIncludesTest,HandlesMultilineIncludes)170 TEST_F(SortIncludesTest, HandlesMultilineIncludes) {
171   EXPECT_EQ("#include \"a.h\"\n"
172             "#include \"b.h\"\n"
173             "#include \"c.h\"\n",
174             sort("#include \"a.h\"\n"
175                  "#include \\\n"
176                  "\"c.h\"\n"
177                  "#include \"b.h\"\n"));
178 }
179 
TEST_F(SortIncludesTest,LeavesMainHeaderFirst)180 TEST_F(SortIncludesTest, LeavesMainHeaderFirst) {
181   Style.IncludeIsMainRegex = "([-_](test|unittest))?$";
182   EXPECT_EQ("#include \"llvm/a.h\"\n"
183             "#include \"b.h\"\n"
184             "#include \"c.h\"\n",
185             sort("#include \"llvm/a.h\"\n"
186                  "#include \"c.h\"\n"
187                  "#include \"b.h\"\n",
188                  "a.cc"));
189   EXPECT_EQ("#include \"llvm/a.h\"\n"
190             "#include \"b.h\"\n"
191             "#include \"c.h\"\n",
192             sort("#include \"llvm/a.h\"\n"
193                  "#include \"c.h\"\n"
194                  "#include \"b.h\"\n",
195                  "a_test.cc"));
196   EXPECT_EQ("#include \"llvm/input.h\"\n"
197             "#include \"b.h\"\n"
198             "#include \"c.h\"\n",
199             sort("#include \"llvm/input.h\"\n"
200                  "#include \"c.h\"\n"
201                  "#include \"b.h\"\n",
202                  "input.mm"));
203 
204   // Don't allow prefixes.
205   EXPECT_EQ("#include \"b.h\"\n"
206             "#include \"c.h\"\n"
207             "#include \"llvm/not_a.h\"\n",
208             sort("#include \"llvm/not_a.h\"\n"
209                  "#include \"c.h\"\n"
210                  "#include \"b.h\"\n",
211                  "a.cc"));
212 
213   // Don't do this for _main and other suffixes.
214   EXPECT_EQ("#include \"b.h\"\n"
215             "#include \"c.h\"\n"
216             "#include \"llvm/a.h\"\n",
217             sort("#include \"llvm/a.h\"\n"
218                  "#include \"c.h\"\n"
219                  "#include \"b.h\"\n",
220                  "a_main.cc"));
221 
222   // Don't do this in headers.
223   EXPECT_EQ("#include \"b.h\"\n"
224             "#include \"c.h\"\n"
225             "#include \"llvm/a.h\"\n",
226             sort("#include \"llvm/a.h\"\n"
227                  "#include \"c.h\"\n"
228                  "#include \"b.h\"\n",
229                  "a.h"));
230 
231   // Only do this in the first #include block.
232   EXPECT_EQ("#include <a>\n"
233             "\n"
234             "#include \"b.h\"\n"
235             "#include \"c.h\"\n"
236             "#include \"llvm/a.h\"\n",
237             sort("#include <a>\n"
238                  "\n"
239                  "#include \"llvm/a.h\"\n"
240                  "#include \"c.h\"\n"
241                  "#include \"b.h\"\n",
242                  "a.cc"));
243 
244   // Only recognize the first #include with a matching basename as main include.
245   EXPECT_EQ("#include \"a.h\"\n"
246             "#include \"b.h\"\n"
247             "#include \"c.h\"\n"
248             "#include \"llvm/a.h\"\n",
249             sort("#include \"b.h\"\n"
250                  "#include \"a.h\"\n"
251                  "#include \"c.h\"\n"
252                  "#include \"llvm/a.h\"\n",
253                  "a.cc"));
254 }
255 
TEST_F(SortIncludesTest,NegativePriorities)256 TEST_F(SortIncludesTest, NegativePriorities) {
257   Style.IncludeCategories = {{".*important_os_header.*", -1}, {".*", 1}};
258   EXPECT_EQ("#include \"important_os_header.h\"\n"
259             "#include \"c_main.h\"\n"
260             "#include \"a_other.h\"\n",
261             sort("#include \"c_main.h\"\n"
262                  "#include \"a_other.h\"\n"
263                  "#include \"important_os_header.h\"\n",
264                  "c_main.cc"));
265 
266   // check stable when re-run
267   EXPECT_EQ("#include \"important_os_header.h\"\n"
268             "#include \"c_main.h\"\n"
269             "#include \"a_other.h\"\n",
270             sort("#include \"important_os_header.h\"\n"
271                  "#include \"c_main.h\"\n"
272                  "#include \"a_other.h\"\n",
273                  "c_main.cc"));
274 }
275 
TEST_F(SortIncludesTest,CalculatesCorrectCursorPosition)276 TEST_F(SortIncludesTest, CalculatesCorrectCursorPosition) {
277   std::string Code = "#include <ccc>\n"    // Start of line: 0
278                      "#include <bbbbbb>\n" // Start of line: 15
279                      "#include <a>\n";     // Start of line: 33
280   EXPECT_EQ(31u, newCursor(Code, 0));
281   EXPECT_EQ(13u, newCursor(Code, 15));
282   EXPECT_EQ(0u, newCursor(Code, 33));
283 
284   EXPECT_EQ(41u, newCursor(Code, 10));
285   EXPECT_EQ(23u, newCursor(Code, 25));
286   EXPECT_EQ(10u, newCursor(Code, 43));
287 }
288 
289 } // end namespace
290 } // end namespace format
291 } // end namespace clang
292