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