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:
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     std::string Sorted =
29         applyAllReplacements(Code, sortIncludes(Style, Code, Ranges, FileName));
30     return applyAllReplacements(Sorted,
31                                 reformat(Style, Sorted, Ranges, FileName));
32   }
33 
34   void verifySort(llvm::StringRef Expected, llvm::StringRef Code,
35                   unsigned Offset = 0, unsigned Length = 0) {
36     std::string Result = sort(Code, Offset, Length);
37     EXPECT_EQ(Expected.str(), Result) << "Expected:\n"
38                                       << Expected << "\nActual:\n"
39                                       << Result;
40   }
41 
42   FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
43 };
44 
45 TEST_F(SortImportsTestJS, AlreadySorted) {
46   verifySort("import {sym} from 'a';\n"
47              "import {sym} from 'b';\n"
48              "import {sym} from 'c';\n"
49              "\n"
50              "let x = 1;",
51              "import {sym} from 'a';\n"
52              "import {sym} from 'b';\n"
53              "import {sym} from 'c';\n"
54              "\n"
55              "let x = 1;");
56 }
57 
58 TEST_F(SortImportsTestJS, BasicSorting) {
59   verifySort("import {sym} from 'a';\n"
60              "import {sym} from 'b';\n"
61              "import {sym} from 'c';\n"
62              "\n"
63              "let x = 1;",
64              "import {sym} from 'a';\n"
65              "import {sym} from 'c';\n"
66              "import {sym} from 'b';\n"
67              "let x = 1;");
68 }
69 
70 TEST_F(SortImportsTestJS, SeparateMainCodeBody) {
71   verifySort("import {sym} from 'a';"
72              "\n"
73              "let x = 1;\n",
74              "import {sym} from 'a'; let x = 1;\n");
75 }
76 
77 TEST_F(SortImportsTestJS, Comments) {
78   verifySort("/** @fileoverview This is a great file. */\n"
79              "// A very important import follows.\n"
80              "import {sym} from 'a'; /* more comments */\n"
81              "import {sym} from 'b'; // from //foo:bar\n",
82              "/** @fileoverview This is a great file. */\n"
83              "import {sym} from 'b'; // from //foo:bar\n"
84              "// A very important import follows.\n"
85              "import {sym} from 'a'; /* more comments */\n");
86 }
87 
88 TEST_F(SortImportsTestJS, SortStar) {
89   verifySort("import * as foo from 'a';\n"
90              "import {sym} from 'a';\n"
91              "import * as bar from 'b';\n",
92              "import {sym} from 'a';\n"
93              "import * as foo from 'a';\n"
94              "import * as bar from 'b';\n");
95 }
96 
97 TEST_F(SortImportsTestJS, AliasesSymbols) {
98   verifySort("import {sym1 as alias1} from 'b';\n"
99              "import {sym2 as alias2, sym3 as alias3} from 'c';\n",
100              "import {sym2 as alias2, sym3 as alias3} from 'c';\n"
101              "import {sym1 as alias1} from 'b';\n");
102 }
103 
104 TEST_F(SortImportsTestJS, GroupImports) {
105   verifySort("import {a} from 'absolute';\n"
106              "\n"
107              "import {b} from '../parent';\n"
108              "import {b} from '../parent/nested';\n"
109              "\n"
110              "import {b} from './relative/path';\n"
111              "import {b} from './relative/path/nested';\n"
112              "\n"
113              "let x = 1;\n",
114              "import {b} from './relative/path/nested';\n"
115              "import {b} from './relative/path';\n"
116              "import {b} from '../parent/nested';\n"
117              "import {b} from '../parent';\n"
118              "import {a} from 'absolute';\n"
119              "let x = 1;\n");
120 }
121 
122 TEST_F(SortImportsTestJS, Exports) {
123   verifySort("import {S} from 'bpath';\n"
124              "\n"
125              "import {T} from './cpath';\n"
126              "\n"
127              "export {A, B} from 'apath';\n"
128              "export {P} from '../parent';\n"
129              "export {R} from './relative';\n"
130              "export {S};\n"
131              "\n"
132              "let x = 1;\n"
133              "export y = 1;\n",
134              "export {R} from './relative';\n"
135              "import {T} from './cpath';\n"
136              "export {S};\n"
137              "export {A, B} from 'apath';\n"
138              "import {S} from 'bpath';\n"
139              "export {P} from '../parent';\n"
140              "let x = 1;\n"
141              "export y = 1;\n");
142   verifySort("import {S} from 'bpath';\n"
143              "\n"
144              "export {T} from 'epath';\n",
145              "export {T} from 'epath';\n"
146              "import {S} from 'bpath';\n");
147 }
148 
149 TEST_F(SortImportsTestJS, SideEffectImports) {
150   verifySort("import 'ZZside-effect';\n"
151              "import 'AAside-effect';\n"
152              "\n"
153              "import {A} from 'absolute';\n"
154              "\n"
155              "import {R} from './relative';\n",
156              "import {R} from './relative';\n"
157              "import 'ZZside-effect';\n"
158              "import {A} from 'absolute';\n"
159              "import 'AAside-effect';\n");
160 }
161 
162 TEST_F(SortImportsTestJS, AffectedRange) {
163   // Sort excluding a suffix.
164   verifySort("import {sym} from 'b';\n"
165              "import {sym} from 'c';\n"
166              "import {sym} from 'a';\n"
167              "let x = 1;",
168              "import {sym} from 'c';\n"
169              "import {sym} from 'b';\n"
170              "import {sym} from 'a';\n"
171              "let x = 1;",
172              0, 30);
173   // Sort excluding a prefix.
174   verifySort("import {sym} from 'c';\n"
175              "import {sym} from 'a';\n"
176              "import {sym} from 'b';\n"
177              "\n"
178              "let x = 1;",
179              "import {sym} from 'c';\n"
180              "import {sym} from 'b';\n"
181              "import {sym} from 'a';\n"
182              "\n"
183              "let x = 1;",
184              30, 0);
185   // Sort a range within imports.
186   verifySort("import {sym} from 'c';\n"
187              "import {sym} from 'a';\n"
188              "import {sym} from 'b';\n"
189              "import {sym} from 'c';\n"
190              "let x = 1;",
191              "import {sym} from 'c';\n"
192              "import {sym} from 'b';\n"
193              "import {sym} from 'a';\n"
194              "import {sym} from 'c';\n"
195              "let x = 1;",
196              24, 30);
197 }
198 
199 } // end namespace
200 } // end namespace format
201 } // end namespace clang
202