[GlobalISel] Add G_ABDS and G_ABDU instructions (#118122)
[llvm-project.git] / clang / unittests / Format / SortImportsTestJS.cpp
blob59ce62117d4a1bdb7dadfaa313bb6351cbb66f94
1 //===- unittest/Format/SortImportsTestJS.cpp - JS import sort unit tests --===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "FormatTestUtils.h"
10 #include "clang/Format/Format.h"
11 #include "llvm/Support/Debug.h"
12 #include "gtest/gtest.h"
14 #define DEBUG_TYPE "format-test"
16 namespace clang {
17 namespace format {
18 namespace {
20 class SortImportsTestJS : public testing::Test {
21 protected:
22 std::string sort(StringRef Code, unsigned Offset = 0, unsigned Length = 0) {
23 StringRef FileName = "input.js";
24 if (Length == 0U)
25 Length = Code.size() - Offset;
26 std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
27 auto Sorted =
28 applyAllReplacements(Code, sortIncludes(Style, Code, Ranges, FileName));
29 EXPECT_TRUE(static_cast<bool>(Sorted));
30 auto Formatted = applyAllReplacements(
31 *Sorted, reformat(Style, *Sorted, Ranges, FileName));
32 EXPECT_TRUE(static_cast<bool>(Formatted));
33 return *Formatted;
36 void _verifySort(const char *File, int Line, StringRef Expected,
37 StringRef Code, unsigned Offset = 0, unsigned Length = 0) {
38 testing::ScopedTrace t(File, Line, testing::Message() << Code.str());
39 std::string Result = sort(Code, Offset, Length);
40 EXPECT_EQ(Expected.str(), Result) << "Expected:\n"
41 << Expected << "\nActual:\n"
42 << Result;
45 FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
48 #define verifySort(...) _verifySort(__FILE__, __LINE__, __VA_ARGS__)
50 TEST_F(SortImportsTestJS, AlreadySorted) {
51 verifySort("import {sym} from 'a';\n"
52 "import {sym} from 'b';\n"
53 "import {sym} from 'c';\n"
54 "\n"
55 "let x = 1;",
56 "import {sym} from 'a';\n"
57 "import {sym} from 'b';\n"
58 "import {sym} from 'c';\n"
59 "\n"
60 "let x = 1;");
63 TEST_F(SortImportsTestJS, BasicSorting) {
64 verifySort("import {sym} from 'a';\n"
65 "import {sym} from 'b';\n"
66 "import {sym} from 'c';\n"
67 "\n"
68 "let x = 1;",
69 "import {sym} from 'a';\n"
70 "import {sym} from 'c';\n"
71 "import {sym} from 'b';\n"
72 "let x = 1;");
75 TEST_F(SortImportsTestJS, DefaultBinding) {
76 verifySort("import A from 'a';\n"
77 "import B from 'b';\n"
78 "\n"
79 "let x = 1;",
80 "import B from 'b';\n"
81 "import A from 'a';\n"
82 "let x = 1;");
85 TEST_F(SortImportsTestJS, DefaultAndNamedBinding) {
86 verifySort("import A, {a} from 'a';\n"
87 "import B, {b} from 'b';\n"
88 "\n"
89 "let x = 1;",
90 "import B, {b} from 'b';\n"
91 "import A, {a} from 'a';\n"
92 "let x = 1;");
95 TEST_F(SortImportsTestJS, WrappedImportStatements) {
96 verifySort("import {sym1, sym2} from 'a';\n"
97 "import {sym} from 'b';\n"
98 "\n"
99 "1;",
100 "import\n"
101 " {sym}\n"
102 " from 'b';\n"
103 "import {\n"
104 " sym1,\n"
105 " sym2\n"
106 "} from 'a';\n"
107 "1;");
110 TEST_F(SortImportsTestJS, SeparateMainCodeBody) {
111 verifySort("import {sym} from 'a';"
112 "\n"
113 "let x = 1;",
114 "import {sym} from 'a'; let x = 1;");
117 TEST_F(SortImportsTestJS, Comments) {
118 verifySort("/** @fileoverview This is a great file. */\n"
119 "// A very important import follows.\n"
120 "import {sym} from 'a'; /* more comments */\n"
121 "import {sym} from 'b'; // from //foo:bar\n",
122 "/** @fileoverview This is a great file. */\n"
123 "import {sym} from 'b'; // from //foo:bar\n"
124 "// A very important import follows.\n"
125 "import {sym} from 'a'; /* more comments */");
126 verifySort("import {sym} from 'a';\n"
127 "import {sym} from 'b';\n"
128 "\n"
129 "/** Comment on variable. */\n"
130 "const x = 1;",
131 "import {sym} from 'b';\n"
132 "import {sym} from 'a';\n"
133 "\n"
134 "/** Comment on variable. */\n"
135 "const x = 1;");
138 TEST_F(SortImportsTestJS, SortStar) {
139 verifySort("import * as foo from 'a';\n"
140 "import {sym} from 'a';\n"
141 "import * as bar from 'b';\n",
142 "import {sym} from 'a';\n"
143 "import * as foo from 'a';\n"
144 "import * as bar from 'b';");
147 TEST_F(SortImportsTestJS, AliasesSymbols) {
148 verifySort("import {sym1 as alias1} from 'b';\n"
149 "import {sym2 as alias2, sym3 as alias3} from 'c';\n",
150 "import {sym2 as alias2, sym3 as alias3} from 'c';\n"
151 "import {sym1 as alias1} from 'b';");
154 TEST_F(SortImportsTestJS, SortSymbols) {
155 verifySort("import {sym1, sym2 as a, sym3} from 'b';\n",
156 "import {sym2 as a, sym1, sym3} from 'b';");
157 verifySort("import {sym1 /* important! */, /*!*/ sym2 as a} from 'b';\n",
158 "import {/*!*/ sym2 as a, sym1 /* important! */} from 'b';");
159 verifySort("import {sym1, sym2} from 'b';\n", "import {\n"
160 " sym2 \n"
161 ",\n"
162 " sym1 \n"
163 "} from 'b';");
166 TEST_F(SortImportsTestJS, GroupImports) {
167 verifySort("import {a} from 'absolute';\n"
168 "\n"
169 "import {b} from '../parent';\n"
170 "import {b} from '../parent/nested';\n"
171 "\n"
172 "import {b} from './relative/path';\n"
173 "import {b} from './relative/path/nested';\n"
174 "\n"
175 "let x = 1;",
176 "import {b} from './relative/path/nested';\n"
177 "import {b} from './relative/path';\n"
178 "import {b} from '../parent/nested';\n"
179 "import {b} from '../parent';\n"
180 "import {a} from 'absolute';\n"
181 "let x = 1;");
184 TEST_F(SortImportsTestJS, Exports) {
185 verifySort("import {S} from 'bpath';\n"
186 "\n"
187 "import {T} from './cpath';\n"
188 "\n"
189 "export {A, B} from 'apath';\n"
190 "export {P} from '../parent';\n"
191 "export {R} from './relative';\n"
192 "export {S};\n"
193 "\n"
194 "let x = 1;\n"
195 "export y = 1;",
196 "export {R} from './relative';\n"
197 "import {T} from './cpath';\n"
198 "export {S};\n"
199 "export {A, B} from 'apath';\n"
200 "import {S} from 'bpath';\n"
201 "export {P} from '../parent';\n"
202 "let x = 1;\n"
203 "export y = 1;");
204 verifySort("import {S} from 'bpath';\n"
205 "\n"
206 "export {T} from 'epath';\n",
207 "export {T} from 'epath';\n"
208 "import {S} from 'bpath';");
211 TEST_F(SortImportsTestJS, SideEffectImports) {
212 verifySort("import 'ZZside-effect';\n"
213 "import 'AAside-effect';\n"
214 "\n"
215 "import {A} from 'absolute';\n"
216 "\n"
217 "import {R} from './relative';\n",
218 "import {R} from './relative';\n"
219 "import 'ZZside-effect';\n"
220 "import {A} from 'absolute';\n"
221 "import 'AAside-effect';");
224 TEST_F(SortImportsTestJS, AffectedRange) {
225 // Affected range inside of import statements.
226 verifySort("import {sym} from 'a';\n"
227 "import {sym} from 'b';\n"
228 "import {sym} from 'c';\n"
229 "\n"
230 "let x = 1;",
231 "import {sym} from 'c';\n"
232 "import {sym} from 'b';\n"
233 "import {sym} from 'a';\n"
234 "let x = 1;",
235 0, 30);
236 // Affected range outside of import statements.
237 verifySort("import {sym} from 'c';\n"
238 "import {sym} from 'b';\n"
239 "import {sym} from 'a';\n"
240 "\n"
241 "let x = 1;",
242 "import {sym} from 'c';\n"
243 "import {sym} from 'b';\n"
244 "import {sym} from 'a';\n"
245 "\n"
246 "let x = 1;",
247 70, 1);
250 TEST_F(SortImportsTestJS, SortingCanShrink) {
251 // Sort excluding a suffix.
252 verifySort("import {B} from 'a';\n"
253 "import {A} from 'b';\n"
254 "\n"
255 "1;",
256 "import {A} from 'b';\n"
257 "\n"
258 "import {B} from 'a';\n"
259 "\n"
260 "1;");
263 TEST_F(SortImportsTestJS, TrailingComma) {
264 verifySort("import {A, B,} from 'aa';\n", "import {B, A,} from 'aa';");
267 TEST_F(SortImportsTestJS, SortCaseInsensitive) {
268 verifySort("import {A} from 'aa';\n"
269 "import {A} from 'Ab';\n"
270 "import {A} from 'b';\n"
271 "import {A} from 'Bc';\n"
272 "\n"
273 "1;",
274 "import {A} from 'b';\n"
275 "import {A} from 'Bc';\n"
276 "import {A} from 'Ab';\n"
277 "import {A} from 'aa';\n"
278 "\n"
279 "1;");
280 verifySort("import {aa, Ab, b, Bc} from 'x';\n"
281 "\n"
282 "1;",
283 "import {b, Bc, Ab, aa} from 'x';\n"
284 "\n"
285 "1;");
288 TEST_F(SortImportsTestJS, SortMultiLine) {
289 // Reproduces issue where multi-line import was not parsed correctly.
290 verifySort("import {A} from 'a';\n"
291 "import {A} from 'b';\n"
292 "\n"
293 "1;",
294 "import\n"
295 "{\n"
296 "A\n"
297 "}\n"
298 "from\n"
299 "'b';\n"
300 "import {A} from 'a';\n"
301 "\n"
302 "1;");
305 TEST_F(SortImportsTestJS, SortDefaultImports) {
306 // Reproduces issue where multi-line import was not parsed correctly.
307 verifySort("import {A} from 'a';\n"
308 "import {default as B} from 'b';\n",
309 "import {default as B} from 'b';\n"
310 "import {A} from 'a';");
313 TEST_F(SortImportsTestJS, MergeImports) {
314 // basic operation
315 verifySort("import {X, Y} from 'a';\n"
316 "import {Z} from 'z';\n"
317 "\n"
318 "X + Y + Z;",
319 "import {X} from 'a';\n"
320 "import {Z} from 'z';\n"
321 "import {Y} from 'a';\n"
322 "\n"
323 "X + Y + Z;");
325 // merge only, no resorting.
326 verifySort("import {A, B} from 'foo';\n", "import {A} from 'foo';\n"
327 "import {B} from 'foo';");
329 // empty imports
330 verifySort("import {A} from 'foo';\n", "import {} from 'foo';\n"
331 "import {A} from 'foo';");
333 // ignores import *
334 verifySort("import * as foo from 'foo';\n"
335 "import {A} from 'foo';",
336 "import * as foo from 'foo';\n"
337 "import {A} from 'foo';");
339 // ignores default import
340 verifySort("import X from 'foo';\n"
341 "import {A} from 'foo';",
342 "import X from 'foo';\n"
343 "import {A} from 'foo';");
345 // keeps comments
346 // known issue: loses the 'also a' comment.
347 verifySort("// a\n"
348 "import {/* x */ X, /* y */ Y} from 'a';\n"
349 "// z\n"
350 "import {Z} from 'z';\n"
351 "\n"
352 "X + Y + Z;",
353 "// a\n"
354 "import {/* y */ Y} from 'a';\n"
355 "// z\n"
356 "import {Z} from 'z';\n"
357 "// also a\n"
358 "import {/* x */ X} from 'a';\n"
359 "\n"
360 "X + Y + Z;");
362 // do not merge imports and exports
363 verifySort("import {A} from 'foo';\n"
364 "\n"
365 "export {B} from 'foo';\n",
366 "import {A} from 'foo';\n"
367 "export {B} from 'foo';");
368 // do merge exports
369 verifySort("export {A, B} from 'foo';\n", "export {A} from 'foo';\n"
370 "export {B} from 'foo';");
372 // do not merge side effect imports with named ones
373 verifySort("import './a';\n"
374 "\n"
375 "import {bar} from './a';\n",
376 "import {bar} from './a';\n"
377 "import './a';");
380 TEST_F(SortImportsTestJS, RespectsClangFormatOff) {
381 verifySort("// clang-format off\n"
382 "import {B} from './b';\n"
383 "import {A} from './a';\n"
384 "// clang-format on",
385 "// clang-format off\n"
386 "import {B} from './b';\n"
387 "import {A} from './a';\n"
388 "// clang-format on");
390 verifySort("import {A} from './sorted1_a';\n"
391 "import {B} from './sorted1_b';\n"
392 "// clang-format off\n"
393 "import {B} from './unsorted_b';\n"
394 "import {A} from './unsorted_a';\n"
395 "// clang-format on\n"
396 "import {A} from './sorted2_a';\n"
397 "import {B} from './sorted2_b';\n",
398 "import {B} from './sorted1_b';\n"
399 "import {A} from './sorted1_a';\n"
400 "// clang-format off\n"
401 "import {B} from './unsorted_b';\n"
402 "import {A} from './unsorted_a';\n"
403 "// clang-format on\n"
404 "import {B} from './sorted2_b';\n"
405 "import {A} from './sorted2_a';");
407 // Boundary cases
408 verifySort("// clang-format on", "// clang-format on");
409 verifySort("// clang-format off", "// clang-format off");
410 verifySort("// clang-format on\n"
411 "// clang-format off",
412 "// clang-format on\n"
413 "// clang-format off");
414 verifySort("// clang-format off\n"
415 "// clang-format on\n"
416 "import {A} from './a';\n"
417 "import {B} from './b';\n",
418 "// clang-format off\n"
419 "// clang-format on\n"
420 "import {B} from './b';\n"
421 "import {A} from './a';");
422 // section ends with comment
423 verifySort("// clang-format on\n"
424 "import {A} from './a';\n"
425 "import {B} from './b';\n"
426 "import {C} from './c';\n"
427 "\n" // inserted empty line is working as intended: splits imports
428 // section from main code body
429 "// clang-format off",
430 "// clang-format on\n"
431 "import {C} from './c';\n"
432 "import {B} from './b';\n"
433 "import {A} from './a';\n"
434 "// clang-format off");
437 TEST_F(SortImportsTestJS, RespectsClangFormatOffInNamedImports) {
438 verifySort("// clang-format off\n"
439 "import {B, A} from './b';\n"
440 "// clang-format on\n"
441 "const x = 1;",
442 "// clang-format off\n"
443 "import {B, A} from './b';\n"
444 "// clang-format on\n"
445 "const x = 1;");
448 TEST_F(SortImportsTestJS, ImportEqAliases) {
449 verifySort("import {B} from 'bar';\n"
450 "import {A} from 'foo';\n"
451 "\n"
452 "import Z = A.C;\n"
453 "import Y = B.C.Z;\n"
454 "\n"
455 "export {Z};\n"
456 "\n"
457 "console.log(Z);",
458 "import {A} from 'foo';\n"
459 "import Z = A.C;\n"
460 "export {Z};\n"
461 "import {B} from 'bar';\n"
462 "import Y = B.C.Z;\n"
463 "\n"
464 "console.log(Z);");
467 TEST_F(SortImportsTestJS, ImportExportType) {
468 verifySort("import type {sym} from 'a';\n"
469 "import {type sym} from 'b';\n"
470 "import {sym} from 'c';\n"
471 "import type sym from 'd';\n"
472 "import type * as sym from 'e';\n"
473 "\n"
474 "let x = 1;",
475 "import {sym} from 'c';\n"
476 "import type {sym} from 'a';\n"
477 "import type * as sym from 'e';\n"
478 "import type sym from 'd';\n"
479 "import {type sym} from 'b';\n"
480 "let x = 1;");
482 // Symbols within import statement
483 verifySort("import {type sym1, type sym2 as a, sym3} from 'b';\n",
484 "import {type sym2 as a, type sym1, sym3} from 'b';");
486 // Merging
487 verifySort("import {X, type Z} from 'a';\n"
488 "import type {Y} from 'a';\n"
489 "\n"
490 "X + Y + Z;",
491 "import {X} from 'a';\n"
492 "import {type Z} from 'a';\n"
493 "import type {Y} from 'a';\n"
494 "\n"
495 "X + Y + Z;");
497 // Merging: empty imports
498 verifySort("import type {A} from 'foo';\n", "import type {} from 'foo';\n"
499 "import type {A} from 'foo';");
501 // Merging: exports
502 verifySort("export {A, type B} from 'foo';\n",
503 "export {A} from 'foo';\n"
504 "export {type B} from 'foo';");
506 // `export type X = Y;` should terminate import sorting. The following export
507 // statements should therefore not merge.
508 verifySort("export type A = B;\n"
509 "export {X};\n"
510 "export {Y};",
511 "export type A = B;\n"
512 "export {X};\n"
513 "export {Y};");
516 TEST_F(SortImportsTestJS, TemplateKeyword) {
517 // Reproduces issue where importing "template" disables imports sorting.
518 verifySort("import {template} from './a';\n"
519 "import {b} from './b';\n",
520 "import {b} from './b';\n"
521 "import {template} from './a';");
524 } // end namespace
525 } // end namespace format
526 } // end namespace clang