• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- unittest/Format/SortImportsTestJS.cpp - JS import 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 SortImportsTestJS : public ::testing::Test {
22 protected:
sort(StringRef Code,unsigned Offset=0,unsigned Length=0)23   std::string sort(StringRef Code, unsigned Offset = 0, unsigned Length = 0) {
24     StringRef FileName = "input.js";
25     if (Length == 0U)
26       Length = Code.size() - Offset;
27     std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
28     auto Sorted =
29         applyAllReplacements(Code, sortIncludes(Style, Code, Ranges, FileName));
30     EXPECT_TRUE(static_cast<bool>(Sorted));
31     auto Formatted = applyAllReplacements(
32         *Sorted, reformat(Style, *Sorted, Ranges, FileName));
33     EXPECT_TRUE(static_cast<bool>(Formatted));
34     return *Formatted;
35   }
36 
verifySort(llvm::StringRef Expected,llvm::StringRef Code,unsigned Offset=0,unsigned Length=0)37   void verifySort(llvm::StringRef Expected, llvm::StringRef Code,
38                   unsigned Offset = 0, unsigned Length = 0) {
39     std::string Result = sort(Code, Offset, Length);
40     EXPECT_EQ(Expected.str(), Result) << "Expected:\n"
41                                       << Expected << "\nActual:\n"
42                                       << Result;
43   }
44 
45   FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
46 };
47 
TEST_F(SortImportsTestJS,AlreadySorted)48 TEST_F(SortImportsTestJS, AlreadySorted) {
49   verifySort("import {sym} from 'a';\n"
50              "import {sym} from 'b';\n"
51              "import {sym} from 'c';\n"
52              "\n"
53              "let x = 1;",
54              "import {sym} from 'a';\n"
55              "import {sym} from 'b';\n"
56              "import {sym} from 'c';\n"
57              "\n"
58              "let x = 1;");
59 }
60 
TEST_F(SortImportsTestJS,BasicSorting)61 TEST_F(SortImportsTestJS, BasicSorting) {
62   verifySort("import {sym} from 'a';\n"
63              "import {sym} from 'b';\n"
64              "import {sym} from 'c';\n"
65              "\n"
66              "let x = 1;",
67              "import {sym} from 'a';\n"
68              "import {sym} from 'c';\n"
69              "import {sym} from 'b';\n"
70              "let x = 1;");
71 }
72 
TEST_F(SortImportsTestJS,WrappedImportStatements)73 TEST_F(SortImportsTestJS, WrappedImportStatements) {
74   verifySort("import {sym1, sym2} from 'a';\n"
75              "import {sym} from 'b';\n"
76              "\n"
77              "1;",
78              "import\n"
79              "  {sym}\n"
80              "  from 'b';\n"
81              "import {\n"
82              "  sym1,\n"
83              "  sym2\n"
84              "} from 'a';\n"
85              "1;");
86 }
87 
TEST_F(SortImportsTestJS,SeparateMainCodeBody)88 TEST_F(SortImportsTestJS, SeparateMainCodeBody) {
89   verifySort("import {sym} from 'a';"
90              "\n"
91              "let x = 1;\n",
92              "import {sym} from 'a'; let x = 1;\n");
93 }
94 
TEST_F(SortImportsTestJS,Comments)95 TEST_F(SortImportsTestJS, Comments) {
96   verifySort("/** @fileoverview This is a great file. */\n"
97              "// A very important import follows.\n"
98              "import {sym} from 'a';  /* more comments */\n"
99              "import {sym} from 'b';  // from //foo:bar\n",
100              "/** @fileoverview This is a great file. */\n"
101              "import {sym} from 'b';  // from //foo:bar\n"
102              "// A very important import follows.\n"
103              "import {sym} from 'a';  /* more comments */\n");
104 }
105 
TEST_F(SortImportsTestJS,SortStar)106 TEST_F(SortImportsTestJS, SortStar) {
107   verifySort("import * as foo from 'a';\n"
108              "import {sym} from 'a';\n"
109              "import * as bar from 'b';\n",
110              "import {sym} from 'a';\n"
111              "import * as foo from 'a';\n"
112              "import * as bar from 'b';\n");
113 }
114 
TEST_F(SortImportsTestJS,AliasesSymbols)115 TEST_F(SortImportsTestJS, AliasesSymbols) {
116   verifySort("import {sym1 as alias1} from 'b';\n"
117              "import {sym2 as alias2, sym3 as alias3} from 'c';\n",
118              "import {sym2 as alias2, sym3 as alias3} from 'c';\n"
119              "import {sym1 as alias1} from 'b';\n");
120 }
121 
TEST_F(SortImportsTestJS,SortSymbols)122 TEST_F(SortImportsTestJS, SortSymbols) {
123   verifySort("import {sym1, sym2 as a, sym3} from 'b';\n",
124              "import {sym2 as a, sym1, sym3} from 'b';\n");
125   verifySort("import {sym1 /* important! */, /*!*/ sym2 as a} from 'b';\n",
126              "import {/*!*/ sym2 as a, sym1 /* important! */} from 'b';\n");
127   verifySort("import {sym1, sym2} from 'b';\n", "import {\n"
128                                                 "  sym2 \n"
129                                                 ",\n"
130                                                 " sym1 \n"
131                                                 "} from 'b';\n");
132 }
133 
TEST_F(SortImportsTestJS,GroupImports)134 TEST_F(SortImportsTestJS, GroupImports) {
135   verifySort("import {a} from 'absolute';\n"
136              "\n"
137              "import {b} from '../parent';\n"
138              "import {b} from '../parent/nested';\n"
139              "\n"
140              "import {b} from './relative/path';\n"
141              "import {b} from './relative/path/nested';\n"
142              "\n"
143              "let x = 1;\n",
144              "import {b} from './relative/path/nested';\n"
145              "import {b} from './relative/path';\n"
146              "import {b} from '../parent/nested';\n"
147              "import {b} from '../parent';\n"
148              "import {a} from 'absolute';\n"
149              "let x = 1;\n");
150 }
151 
TEST_F(SortImportsTestJS,Exports)152 TEST_F(SortImportsTestJS, Exports) {
153   verifySort("import {S} from 'bpath';\n"
154              "\n"
155              "import {T} from './cpath';\n"
156              "\n"
157              "export {A, B} from 'apath';\n"
158              "export {P} from '../parent';\n"
159              "export {R} from './relative';\n"
160              "export {S};\n"
161              "\n"
162              "let x = 1;\n"
163              "export y = 1;\n",
164              "export {R} from './relative';\n"
165              "import {T} from './cpath';\n"
166              "export {S};\n"
167              "export {A, B} from 'apath';\n"
168              "import {S} from 'bpath';\n"
169              "export {P} from '../parent';\n"
170              "let x = 1;\n"
171              "export y = 1;\n");
172   verifySort("import {S} from 'bpath';\n"
173              "\n"
174              "export {T} from 'epath';\n",
175              "export {T} from 'epath';\n"
176              "import {S} from 'bpath';\n");
177 }
178 
TEST_F(SortImportsTestJS,SideEffectImports)179 TEST_F(SortImportsTestJS, SideEffectImports) {
180   verifySort("import 'ZZside-effect';\n"
181              "import 'AAside-effect';\n"
182              "\n"
183              "import {A} from 'absolute';\n"
184              "\n"
185              "import {R} from './relative';\n",
186              "import {R} from './relative';\n"
187              "import 'ZZside-effect';\n"
188              "import {A} from 'absolute';\n"
189              "import 'AAside-effect';\n");
190 }
191 
TEST_F(SortImportsTestJS,AffectedRange)192 TEST_F(SortImportsTestJS, AffectedRange) {
193   // Sort excluding a suffix.
194   verifySort("import {sym} from 'b';\n"
195              "import {sym} from 'c';\n"
196              "import {sym} from 'a';\n"
197              "let x = 1;",
198              "import {sym} from 'c';\n"
199              "import {sym} from 'b';\n"
200              "import {sym} from 'a';\n"
201              "let x = 1;",
202              0, 30);
203   // Sort excluding a prefix.
204   verifySort("import {sym} from 'c';\n"
205              "import {sym} from 'a';\n"
206              "import {sym} from 'b';\n"
207              "\n"
208              "let x = 1;",
209              "import {sym} from 'c';\n"
210              "import {sym} from 'b';\n"
211              "import {sym} from 'a';\n"
212              "\n"
213              "let x = 1;",
214              30, 0);
215   // Sort a range within imports.
216   verifySort("import {sym} from 'c';\n"
217              "import {sym} from 'a';\n"
218              "import {sym} from 'b';\n"
219              "import {sym} from 'c';\n"
220              "let x = 1;",
221              "import {sym} from 'c';\n"
222              "import {sym} from 'b';\n"
223              "import {sym} from 'a';\n"
224              "import {sym} from 'c';\n"
225              "let x = 1;",
226              24, 30);
227 }
228 
TEST_F(SortImportsTestJS,SortingCanShrink)229 TEST_F(SortImportsTestJS, SortingCanShrink) {
230   // Sort excluding a suffix.
231   verifySort("import {B} from 'a';\n"
232              "import {A} from 'b';\n"
233              "\n"
234              "1;",
235              "import {A} from 'b';\n"
236              "\n"
237              "import {B} from 'a';\n"
238              "\n"
239              "1;");
240 }
241 
TEST_F(SortImportsTestJS,TrailingComma)242 TEST_F(SortImportsTestJS, TrailingComma) {
243   verifySort("import {A, B,} from 'aa';\n", "import {B, A,} from 'aa';\n");
244 }
245 
TEST_F(SortImportsTestJS,SortCaseInsensitive)246 TEST_F(SortImportsTestJS, SortCaseInsensitive) {
247   verifySort("import {A} from 'aa';\n"
248              "import {A} from 'Ab';\n"
249              "import {A} from 'b';\n"
250              "import {A} from 'Bc';\n"
251              "\n"
252              "1;",
253              "import {A} from 'b';\n"
254              "import {A} from 'Bc';\n"
255              "import {A} from 'Ab';\n"
256              "import {A} from 'aa';\n"
257              "\n"
258              "1;");
259   verifySort("import {aa, Ab, b, Bc} from 'x';\n"
260              "\n"
261              "1;",
262              "import {b, Bc, Ab, aa} from 'x';\n"
263              "\n"
264              "1;");
265 }
266 
267 } // end namespace
268 } // end namespace format
269 } // end namespace clang
270