1 | #include "clang/Format/Format.h" |
2 | #include "gtest/gtest.h" |
3 | |
4 | #define DEBUG_TYPE "format-test" |
5 | |
6 | namespace clang { |
7 | namespace format { |
8 | namespace { |
9 | |
10 | class SortImportsTestJava : public testing::Test { |
11 | protected: |
12 | std::vector<tooling::Range> GetCodeRange(StringRef Code) { |
13 | return std::vector<tooling::Range>(1, tooling::Range(0, Code.size())); |
14 | } |
15 | |
16 | std::string sort(StringRef Code, std::vector<tooling::Range> Ranges) { |
17 | auto Replaces = sortIncludes(Style: FmtStyle, Code, Ranges, FileName: "input.java" ); |
18 | Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges); |
19 | auto Sorted = applyAllReplacements(Code, Replaces); |
20 | EXPECT_TRUE(static_cast<bool>(Sorted)); |
21 | auto Result = applyAllReplacements( |
22 | Code: *Sorted, Replaces: reformat(Style: FmtStyle, Code: *Sorted, Ranges, FileName: "input.java" )); |
23 | EXPECT_TRUE(static_cast<bool>(Result)); |
24 | return *Result; |
25 | } |
26 | |
27 | std::string sort(StringRef Code) { return sort(Code, Ranges: GetCodeRange(Code)); } |
28 | |
29 | FormatStyle FmtStyle; |
30 | |
31 | public: |
32 | SortImportsTestJava() { |
33 | FmtStyle = getGoogleStyle(Language: FormatStyle::LK_Java); |
34 | EXPECT_TRUE(FmtStyle.SortIncludes.Enabled); |
35 | FmtStyle.JavaImportGroups = {"com.test" , "org" , "com" }; |
36 | FmtStyle.SortIncludes.IgnoreCase = true; |
37 | } |
38 | }; |
39 | |
40 | TEST_F(SortImportsTestJava, StaticSplitFromNormal) { |
41 | EXPECT_EQ("import static org.b;\n" |
42 | "\n" |
43 | "import org.a;" , |
44 | sort("import org.a;\n" |
45 | "import static org.b;" )); |
46 | } |
47 | |
48 | TEST_F(SortImportsTestJava, CapitalBeforeLowercase) { |
49 | EXPECT_EQ("import org.Test;\n" |
50 | "import org.a.Test;\n" |
51 | "import org.b;" , |
52 | sort("import org.a.Test;\n" |
53 | "import org.Test;\n" |
54 | "import org.b;" )); |
55 | } |
56 | |
57 | TEST_F(SortImportsTestJava, KeepSplitGroupsWithOneNewImport) { |
58 | EXPECT_EQ("import static com.test.a;\n" |
59 | "\n" |
60 | "import static org.a;\n" |
61 | "\n" |
62 | "import static com.a;\n" |
63 | "\n" |
64 | "import com.test.b;\n" |
65 | "import com.test.c;\n" |
66 | "\n" |
67 | "import org.b;\n" |
68 | "\n" |
69 | "import com.b;" , |
70 | sort("import static com.test.a;\n" |
71 | "\n" |
72 | "import static org.a;\n" |
73 | "\n" |
74 | "import static com.a;\n" |
75 | "\n" |
76 | "import com.test.b;\n" |
77 | "\n" |
78 | "import org.b;\n" |
79 | "\n" |
80 | "import com.b;\n" |
81 | "import com.test.c;" )); |
82 | } |
83 | |
84 | TEST_F(SortImportsTestJava, SplitGroupsWithNewline) { |
85 | EXPECT_EQ("import static com.test.a;\n" |
86 | "\n" |
87 | "import static org.a;\n" |
88 | "\n" |
89 | "import static com.a;\n" |
90 | "\n" |
91 | "import com.test.b;\n" |
92 | "\n" |
93 | "import org.b;\n" |
94 | "\n" |
95 | "import com.b;" , |
96 | sort("import static com.test.a;\n" |
97 | "import static org.a;\n" |
98 | "import static com.a;\n" |
99 | "import com.test.b;\n" |
100 | "import org.b;\n" |
101 | "import com.b;" )); |
102 | } |
103 | |
104 | TEST_F(SortImportsTestJava, UnspecifiedGroupAfterAllGroups) { |
105 | EXPECT_EQ("import com.test.a;\n" |
106 | "\n" |
107 | "import org.a;\n" |
108 | "\n" |
109 | "import com.a;\n" |
110 | "\n" |
111 | "import abc.a;\n" |
112 | "import xyz.b;" , |
113 | sort("import com.test.a;\n" |
114 | "import com.a;\n" |
115 | "import xyz.b;\n" |
116 | "import abc.a;\n" |
117 | "import org.a;" )); |
118 | } |
119 | |
120 | TEST_F(SortImportsTestJava, NoSortOutsideRange) { |
121 | std::vector<tooling::Range> Ranges = {tooling::Range(27, 15)}; |
122 | EXPECT_EQ("import org.b;\n" |
123 | "import org.a;\n" |
124 | "// comments\n" |
125 | "// that do\n" |
126 | "// nothing" , |
127 | sort("import org.b;\n" |
128 | "import org.a;\n" |
129 | "// comments\n" |
130 | "// that do\n" |
131 | "// nothing" , |
132 | Ranges)); |
133 | } |
134 | |
135 | TEST_F(SortImportsTestJava, SortWhenRangeContainsOneLine) { |
136 | std::vector<tooling::Range> Ranges = {tooling::Range(27, 20)}; |
137 | EXPECT_EQ("import org.a;\n" |
138 | "import org.b;\n" |
139 | "\n" |
140 | "import com.a;\n" |
141 | "// comments\n" |
142 | "// that do\n" |
143 | "// nothing" , |
144 | sort("import org.b;\n" |
145 | "import org.a;\n" |
146 | "import com.a;\n" |
147 | "// comments\n" |
148 | "// that do\n" |
149 | "// nothing" , |
150 | Ranges)); |
151 | } |
152 | |
153 | TEST_F(SortImportsTestJava, SortLexicographically) { |
154 | EXPECT_EQ("import org.a.*;\n" |
155 | "import org.a.a;\n" |
156 | "import org.aA;\n" |
157 | "import org.aa;" , |
158 | sort("import org.aa;\n" |
159 | "import org.a.a;\n" |
160 | "import org.a.*;\n" |
161 | "import org.aA;" )); |
162 | } |
163 | |
164 | TEST_F(SortImportsTestJava, StaticInCommentHasNoEffect) { |
165 | EXPECT_EQ("import org.a; // static\n" |
166 | "import org.b;\n" |
167 | "import org.c; // static" , |
168 | sort("import org.a; // static\n" |
169 | "import org.c; // static\n" |
170 | "import org.b;" )); |
171 | } |
172 | |
173 | TEST_F(SortImportsTestJava, CommentsWithAffectedImports) { |
174 | EXPECT_EQ("import org.a;\n" |
175 | "// commentB\n" |
176 | "/* commentB\n" |
177 | " commentB*/\n" |
178 | "import org.b;\n" |
179 | "// commentC\n" |
180 | "import org.c;" , |
181 | sort("import org.a;\n" |
182 | "// commentC\n" |
183 | "import org.c;\n" |
184 | "// commentB\n" |
185 | "/* commentB\n" |
186 | " commentB*/\n" |
187 | "import org.b;" )); |
188 | } |
189 | |
190 | TEST_F(SortImportsTestJava, CommentWithUnaffectedImports) { |
191 | EXPECT_EQ("import org.a;\n" |
192 | "// comment\n" |
193 | "import org.b;" , |
194 | sort("import org.a;\n" |
195 | "// comment\n" |
196 | "import org.b;" )); |
197 | } |
198 | |
199 | TEST_F(SortImportsTestJava, CommentAfterAffectedImports) { |
200 | EXPECT_EQ("import org.a;\n" |
201 | "import org.b;\n" |
202 | "// comment" , |
203 | sort("import org.b;\n" |
204 | "import org.a;\n" |
205 | "// comment" )); |
206 | } |
207 | |
208 | TEST_F(SortImportsTestJava, CommentBeforeAffectedImports) { |
209 | EXPECT_EQ("// comment\n" |
210 | "import org.a;\n" |
211 | "import org.b;" , |
212 | sort("// comment\n" |
213 | "import org.b;\n" |
214 | "import org.a;" )); |
215 | } |
216 | |
217 | TEST_F(SortImportsTestJava, FormatTotallyOff) { |
218 | EXPECT_EQ("// clang-format off\n" |
219 | "import org.b;\n" |
220 | "import org.a;\n" |
221 | "// clang-format on" , |
222 | sort("// clang-format off\n" |
223 | "import org.b;\n" |
224 | "import org.a;\n" |
225 | "// clang-format on" )); |
226 | } |
227 | |
228 | TEST_F(SortImportsTestJava, FormatTotallyOn) { |
229 | EXPECT_EQ("// clang-format off\n" |
230 | "// clang-format on\n" |
231 | "import org.a;\n" |
232 | "import org.b;" , |
233 | sort("// clang-format off\n" |
234 | "// clang-format on\n" |
235 | "import org.b;\n" |
236 | "import org.a;" )); |
237 | } |
238 | |
239 | TEST_F(SortImportsTestJava, FormatPariallyOnShouldNotReorder) { |
240 | EXPECT_EQ("// clang-format off\n" |
241 | "import org.b;\n" |
242 | "import org.a;\n" |
243 | "// clang-format on\n" |
244 | "import org.d;\n" |
245 | "import org.c;" , |
246 | sort("// clang-format off\n" |
247 | "import org.b;\n" |
248 | "import org.a;\n" |
249 | "// clang-format on\n" |
250 | "import org.d;\n" |
251 | "import org.c;" )); |
252 | } |
253 | |
254 | TEST_F(SortImportsTestJava, SortJavaStaticImport) { |
255 | FmtStyle.SortJavaStaticImport = FormatStyle::SJSIO_Before; |
256 | EXPECT_EQ("import static com.test.a;\n" |
257 | "\n" |
258 | "import static org.a;\n" |
259 | "\n" |
260 | "import static com.a;\n" |
261 | "\n" |
262 | "import com.test.b;\n" |
263 | "\n" |
264 | "import org.b;\n" |
265 | "\n" |
266 | "import com.b;" , |
267 | sort("import static com.test.a;\n" |
268 | "import static org.a;\n" |
269 | "import static com.a;\n" |
270 | "import com.test.b;\n" |
271 | "import org.b;\n" |
272 | "import com.b;" )); |
273 | |
274 | FmtStyle.SortJavaStaticImport = FormatStyle::SJSIO_After; |
275 | EXPECT_EQ("import com.test.b;\n" |
276 | "import com.test.c;\n" |
277 | "\n" |
278 | "import org.b;\n" |
279 | "\n" |
280 | "import com.b;\n" |
281 | "\n" |
282 | "import static com.test.a;\n" |
283 | "\n" |
284 | "import static org.a;\n" |
285 | "\n" |
286 | "import static com.a;" , |
287 | sort("import static com.test.a;\n" |
288 | "import static org.a;\n" |
289 | "import static com.a;\n" |
290 | "import com.test.b;\n" |
291 | "import org.b;\n" |
292 | "import com.b;\n" |
293 | "import com.test.c;" )); |
294 | } |
295 | |
296 | TEST_F(SortImportsTestJava, SortJavaStaticImportAsGroup) { |
297 | FmtStyle.SortJavaStaticImport = FormatStyle::SJSIO_After; |
298 | |
299 | EXPECT_EQ("import com.test.a;\n" |
300 | "import com.test.b;\n" |
301 | "\n" |
302 | "import static org.a;\n" |
303 | "import static org.b;" , |
304 | sort("import com.test.a;\n" |
305 | "import static org.a;\n" |
306 | "import com.test.b;\n" |
307 | "import static org.b;" )); |
308 | } |
309 | |
310 | TEST_F(SortImportsTestJava, DeduplicateImports) { |
311 | EXPECT_EQ("import org.a;" , sort("import org.a;\n" |
312 | "import org.a;" )); |
313 | } |
314 | |
315 | TEST_F(SortImportsTestJava, NoNewlineAtEnd) { |
316 | EXPECT_EQ("import org.a;\n" |
317 | "import org.b;" , |
318 | sort("import org.b;\n" |
319 | "import org.a;" )); |
320 | } |
321 | |
322 | TEST_F(SortImportsTestJava, ImportNamedFunction) { |
323 | EXPECT_EQ("import X;\n" |
324 | "class C {\n" |
325 | " void m() {\n" |
326 | " importFile();\n" |
327 | " }\n" |
328 | "}" , |
329 | sort("import X;\n" |
330 | "class C {\n" |
331 | " void m() {\n" |
332 | " importFile();\n" |
333 | " }\n" |
334 | "}" )); |
335 | } |
336 | |
337 | TEST_F(SortImportsTestJava, NoReplacementsForValidImports) { |
338 | // Identical #includes have led to a failure with an unstable sort. |
339 | std::string Code = "import org.a;\n" |
340 | "import org.b;\n" ; |
341 | EXPECT_TRUE( |
342 | sortIncludes(FmtStyle, Code, GetCodeRange(Code), "input.java" ).empty()); |
343 | } |
344 | |
345 | TEST_F(SortImportsTestJava, NoReplacementsForValidImportsWindows) { |
346 | std::string Code = "import org.a;\r\n" |
347 | "import org.b;\r\n" ; |
348 | EXPECT_TRUE( |
349 | sortIncludes(FmtStyle, Code, GetCodeRange(Code), "input.java" ).empty()); |
350 | } |
351 | |
352 | } // end namespace |
353 | } // end namespace format |
354 | } // end namespace clang |
355 | |