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
17namespace clang {
18namespace format {
19namespace {
20
21class SortIncludesTest : public ::testing::Test {
22protected:
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, 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
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
47TEST_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
56TEST_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
67TEST_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
86TEST_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
96TEST_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
105TEST_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
114TEST_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
129TEST_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
138TEST_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
149TEST_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
170TEST_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
180TEST_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
256TEST_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
276TEST_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