1c4a0dd49SMartin Probst //===- unittest/Format/SortImportsTestJS.cpp - JS import sort unit tests --===//
2c4a0dd49SMartin Probst //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6c4a0dd49SMartin Probst //
7c4a0dd49SMartin Probst //===----------------------------------------------------------------------===//
8c4a0dd49SMartin Probst
9c4a0dd49SMartin Probst #include "FormatTestUtils.h"
10c4a0dd49SMartin Probst #include "clang/Format/Format.h"
11c4a0dd49SMartin Probst #include "llvm/Support/Debug.h"
12c4a0dd49SMartin Probst #include "gtest/gtest.h"
13c4a0dd49SMartin Probst
14c4a0dd49SMartin Probst #define DEBUG_TYPE "format-test"
15c4a0dd49SMartin Probst
16c4a0dd49SMartin Probst namespace clang {
17c4a0dd49SMartin Probst namespace format {
18c4a0dd49SMartin Probst namespace {
19c4a0dd49SMartin Probst
20*1c58208dSOwen Pan class SortImportsTestJS : public testing::Test {
21c4a0dd49SMartin Probst protected:
sort(StringRef Code,unsigned Offset=0,unsigned Length=0)22c4a0dd49SMartin Probst std::string sort(StringRef Code, unsigned Offset = 0, unsigned Length = 0) {
23c4a0dd49SMartin Probst StringRef FileName = "input.js";
24c4a0dd49SMartin Probst if (Length == 0U)
25c4a0dd49SMartin Probst Length = Code.size() - Offset;
26c4a0dd49SMartin Probst std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));
274f8d9943SEric Liu auto Sorted =
28c4a0dd49SMartin Probst applyAllReplacements(Code, sortIncludes(Style, Code, Ranges, FileName));
294f8d9943SEric Liu EXPECT_TRUE(static_cast<bool>(Sorted));
304f8d9943SEric Liu auto Formatted = applyAllReplacements(
314f8d9943SEric Liu *Sorted, reformat(Style, *Sorted, Ranges, FileName));
324f8d9943SEric Liu EXPECT_TRUE(static_cast<bool>(Formatted));
334f8d9943SEric Liu return *Formatted;
34c4a0dd49SMartin Probst }
35c4a0dd49SMartin Probst
_verifySort(const char * File,int Line,StringRef Expected,StringRef Code,unsigned Offset=0,unsigned Length=0)36*1c58208dSOwen Pan void _verifySort(const char *File, int Line, StringRef Expected,
37*1c58208dSOwen Pan StringRef Code, unsigned Offset = 0, unsigned Length = 0) {
38*1c58208dSOwen Pan testing::ScopedTrace t(File, Line, testing::Message() << Code.str());
39c4a0dd49SMartin Probst std::string Result = sort(Code, Offset, Length);
40c4a0dd49SMartin Probst EXPECT_EQ(Expected.str(), Result) << "Expected:\n"
41c4a0dd49SMartin Probst << Expected << "\nActual:\n"
42c4a0dd49SMartin Probst << Result;
43c4a0dd49SMartin Probst }
44c4a0dd49SMartin Probst
45c4a0dd49SMartin Probst FormatStyle Style = getGoogleStyle(FormatStyle::LK_JavaScript);
46c4a0dd49SMartin Probst };
47c4a0dd49SMartin Probst
4869ecd248SMarek Kurdej #define verifySort(...) _verifySort(__FILE__, __LINE__, __VA_ARGS__)
4969ecd248SMarek Kurdej
TEST_F(SortImportsTestJS,AlreadySorted)50c4a0dd49SMartin Probst TEST_F(SortImportsTestJS, AlreadySorted) {
51c4a0dd49SMartin Probst verifySort("import {sym} from 'a';\n"
52c4a0dd49SMartin Probst "import {sym} from 'b';\n"
53c4a0dd49SMartin Probst "import {sym} from 'c';\n"
54c4a0dd49SMartin Probst "\n"
55c4a0dd49SMartin Probst "let x = 1;",
56c4a0dd49SMartin Probst "import {sym} from 'a';\n"
57c4a0dd49SMartin Probst "import {sym} from 'b';\n"
58c4a0dd49SMartin Probst "import {sym} from 'c';\n"
59c4a0dd49SMartin Probst "\n"
60c4a0dd49SMartin Probst "let x = 1;");
61c4a0dd49SMartin Probst }
62c4a0dd49SMartin Probst
TEST_F(SortImportsTestJS,BasicSorting)63c4a0dd49SMartin Probst TEST_F(SortImportsTestJS, BasicSorting) {
64c4a0dd49SMartin Probst verifySort("import {sym} from 'a';\n"
65c4a0dd49SMartin Probst "import {sym} from 'b';\n"
66c4a0dd49SMartin Probst "import {sym} from 'c';\n"
67c4a0dd49SMartin Probst "\n"
68c4a0dd49SMartin Probst "let x = 1;",
69c4a0dd49SMartin Probst "import {sym} from 'a';\n"
70c4a0dd49SMartin Probst "import {sym} from 'c';\n"
71c4a0dd49SMartin Probst "import {sym} from 'b';\n"
72c4a0dd49SMartin Probst "let x = 1;");
73c4a0dd49SMartin Probst }
74c4a0dd49SMartin Probst
TEST_F(SortImportsTestJS,DefaultBinding)756918dcafSMartin Probst TEST_F(SortImportsTestJS, DefaultBinding) {
766918dcafSMartin Probst verifySort("import A from 'a';\n"
776918dcafSMartin Probst "import B from 'b';\n"
786918dcafSMartin Probst "\n"
796918dcafSMartin Probst "let x = 1;",
806918dcafSMartin Probst "import B from 'b';\n"
816918dcafSMartin Probst "import A from 'a';\n"
826918dcafSMartin Probst "let x = 1;");
836918dcafSMartin Probst }
846918dcafSMartin Probst
TEST_F(SortImportsTestJS,DefaultAndNamedBinding)856918dcafSMartin Probst TEST_F(SortImportsTestJS, DefaultAndNamedBinding) {
866918dcafSMartin Probst verifySort("import A, {a} from 'a';\n"
876918dcafSMartin Probst "import B, {b} from 'b';\n"
886918dcafSMartin Probst "\n"
896918dcafSMartin Probst "let x = 1;",
906918dcafSMartin Probst "import B, {b} from 'b';\n"
916918dcafSMartin Probst "import A, {a} from 'a';\n"
926918dcafSMartin Probst "let x = 1;");
936918dcafSMartin Probst }
946918dcafSMartin Probst
TEST_F(SortImportsTestJS,WrappedImportStatements)95081f176aSMartin Probst TEST_F(SortImportsTestJS, WrappedImportStatements) {
96081f176aSMartin Probst verifySort("import {sym1, sym2} from 'a';\n"
97081f176aSMartin Probst "import {sym} from 'b';\n"
98081f176aSMartin Probst "\n"
99081f176aSMartin Probst "1;",
100081f176aSMartin Probst "import\n"
101081f176aSMartin Probst " {sym}\n"
102081f176aSMartin Probst " from 'b';\n"
103081f176aSMartin Probst "import {\n"
104081f176aSMartin Probst " sym1,\n"
105081f176aSMartin Probst " sym2\n"
106081f176aSMartin Probst "} from 'a';\n"
107081f176aSMartin Probst "1;");
108081f176aSMartin Probst }
109081f176aSMartin Probst
TEST_F(SortImportsTestJS,SeparateMainCodeBody)110c4a0dd49SMartin Probst TEST_F(SortImportsTestJS, SeparateMainCodeBody) {
111c4a0dd49SMartin Probst verifySort("import {sym} from 'a';"
112c4a0dd49SMartin Probst "\n"
113e3ecdf7dSOwen Pan "let x = 1;",
114e3ecdf7dSOwen Pan "import {sym} from 'a'; let x = 1;");
115c4a0dd49SMartin Probst }
116c4a0dd49SMartin Probst
TEST_F(SortImportsTestJS,Comments)117c4a0dd49SMartin Probst TEST_F(SortImportsTestJS, Comments) {
118c4a0dd49SMartin Probst verifySort("/** @fileoverview This is a great file. */\n"
119c4a0dd49SMartin Probst "// A very important import follows.\n"
120c4a0dd49SMartin Probst "import {sym} from 'a'; /* more comments */\n"
121c4a0dd49SMartin Probst "import {sym} from 'b'; // from //foo:bar\n",
122c4a0dd49SMartin Probst "/** @fileoverview This is a great file. */\n"
123c4a0dd49SMartin Probst "import {sym} from 'b'; // from //foo:bar\n"
124c4a0dd49SMartin Probst "// A very important import follows.\n"
125e3ecdf7dSOwen Pan "import {sym} from 'a'; /* more comments */");
12663014581SMartin Probst verifySort("import {sym} from 'a';\n"
12763014581SMartin Probst "import {sym} from 'b';\n"
12863014581SMartin Probst "\n"
12963014581SMartin Probst "/** Comment on variable. */\n"
130e3ecdf7dSOwen Pan "const x = 1;",
13163014581SMartin Probst "import {sym} from 'b';\n"
13263014581SMartin Probst "import {sym} from 'a';\n"
13363014581SMartin Probst "\n"
13463014581SMartin Probst "/** Comment on variable. */\n"
135e3ecdf7dSOwen Pan "const x = 1;");
136c4a0dd49SMartin Probst }
137c4a0dd49SMartin Probst
TEST_F(SortImportsTestJS,SortStar)138c4a0dd49SMartin Probst TEST_F(SortImportsTestJS, SortStar) {
139c4a0dd49SMartin Probst verifySort("import * as foo from 'a';\n"
140c4a0dd49SMartin Probst "import {sym} from 'a';\n"
141c4a0dd49SMartin Probst "import * as bar from 'b';\n",
142c4a0dd49SMartin Probst "import {sym} from 'a';\n"
143c4a0dd49SMartin Probst "import * as foo from 'a';\n"
144e3ecdf7dSOwen Pan "import * as bar from 'b';");
145c4a0dd49SMartin Probst }
146c4a0dd49SMartin Probst
TEST_F(SortImportsTestJS,AliasesSymbols)147c4a0dd49SMartin Probst TEST_F(SortImportsTestJS, AliasesSymbols) {
148c4a0dd49SMartin Probst verifySort("import {sym1 as alias1} from 'b';\n"
149c4a0dd49SMartin Probst "import {sym2 as alias2, sym3 as alias3} from 'c';\n",
150c4a0dd49SMartin Probst "import {sym2 as alias2, sym3 as alias3} from 'c';\n"
151e3ecdf7dSOwen Pan "import {sym1 as alias1} from 'b';");
152c4a0dd49SMartin Probst }
153c4a0dd49SMartin Probst
TEST_F(SortImportsTestJS,SortSymbols)154081f176aSMartin Probst TEST_F(SortImportsTestJS, SortSymbols) {
155081f176aSMartin Probst verifySort("import {sym1, sym2 as a, sym3} from 'b';\n",
156e3ecdf7dSOwen Pan "import {sym2 as a, sym1, sym3} from 'b';");
157081f176aSMartin Probst verifySort("import {sym1 /* important! */, /*!*/ sym2 as a} from 'b';\n",
158e3ecdf7dSOwen Pan "import {/*!*/ sym2 as a, sym1 /* important! */} from 'b';");
159081f176aSMartin Probst verifySort("import {sym1, sym2} from 'b';\n", "import {\n"
160081f176aSMartin Probst " sym2 \n"
161081f176aSMartin Probst ",\n"
162081f176aSMartin Probst " sym1 \n"
163e3ecdf7dSOwen Pan "} from 'b';");
164081f176aSMartin Probst }
165081f176aSMartin Probst
TEST_F(SortImportsTestJS,GroupImports)166c4a0dd49SMartin Probst TEST_F(SortImportsTestJS, GroupImports) {
167c4a0dd49SMartin Probst verifySort("import {a} from 'absolute';\n"
168c4a0dd49SMartin Probst "\n"
169c4a0dd49SMartin Probst "import {b} from '../parent';\n"
170c4a0dd49SMartin Probst "import {b} from '../parent/nested';\n"
171c4a0dd49SMartin Probst "\n"
172c4a0dd49SMartin Probst "import {b} from './relative/path';\n"
173c4a0dd49SMartin Probst "import {b} from './relative/path/nested';\n"
174c4a0dd49SMartin Probst "\n"
175e3ecdf7dSOwen Pan "let x = 1;",
176c4a0dd49SMartin Probst "import {b} from './relative/path/nested';\n"
177c4a0dd49SMartin Probst "import {b} from './relative/path';\n"
178c4a0dd49SMartin Probst "import {b} from '../parent/nested';\n"
179c4a0dd49SMartin Probst "import {b} from '../parent';\n"
180c4a0dd49SMartin Probst "import {a} from 'absolute';\n"
181e3ecdf7dSOwen Pan "let x = 1;");
182c4a0dd49SMartin Probst }
183c4a0dd49SMartin Probst
TEST_F(SortImportsTestJS,Exports)184c4a0dd49SMartin Probst TEST_F(SortImportsTestJS, Exports) {
185c4a0dd49SMartin Probst verifySort("import {S} from 'bpath';\n"
186c4a0dd49SMartin Probst "\n"
187c4a0dd49SMartin Probst "import {T} from './cpath';\n"
188c4a0dd49SMartin Probst "\n"
189c4a0dd49SMartin Probst "export {A, B} from 'apath';\n"
190c4a0dd49SMartin Probst "export {P} from '../parent';\n"
191c4a0dd49SMartin Probst "export {R} from './relative';\n"
192c4a0dd49SMartin Probst "export {S};\n"
193c4a0dd49SMartin Probst "\n"
194c4a0dd49SMartin Probst "let x = 1;\n"
195e3ecdf7dSOwen Pan "export y = 1;",
196c4a0dd49SMartin Probst "export {R} from './relative';\n"
197c4a0dd49SMartin Probst "import {T} from './cpath';\n"
198c4a0dd49SMartin Probst "export {S};\n"
199c4a0dd49SMartin Probst "export {A, B} from 'apath';\n"
200c4a0dd49SMartin Probst "import {S} from 'bpath';\n"
201c4a0dd49SMartin Probst "export {P} from '../parent';\n"
202c4a0dd49SMartin Probst "let x = 1;\n"
203e3ecdf7dSOwen Pan "export y = 1;");
204c4a0dd49SMartin Probst verifySort("import {S} from 'bpath';\n"
205c4a0dd49SMartin Probst "\n"
206c4a0dd49SMartin Probst "export {T} from 'epath';\n",
207c4a0dd49SMartin Probst "export {T} from 'epath';\n"
208e3ecdf7dSOwen Pan "import {S} from 'bpath';");
209c4a0dd49SMartin Probst }
210c4a0dd49SMartin Probst
TEST_F(SortImportsTestJS,SideEffectImports)211c4a0dd49SMartin Probst TEST_F(SortImportsTestJS, SideEffectImports) {
212c4a0dd49SMartin Probst verifySort("import 'ZZside-effect';\n"
213c4a0dd49SMartin Probst "import 'AAside-effect';\n"
214c4a0dd49SMartin Probst "\n"
215c4a0dd49SMartin Probst "import {A} from 'absolute';\n"
216c4a0dd49SMartin Probst "\n"
217c4a0dd49SMartin Probst "import {R} from './relative';\n",
218c4a0dd49SMartin Probst "import {R} from './relative';\n"
219c4a0dd49SMartin Probst "import 'ZZside-effect';\n"
220c4a0dd49SMartin Probst "import {A} from 'absolute';\n"
221e3ecdf7dSOwen Pan "import 'AAside-effect';");
222c4a0dd49SMartin Probst }
223c4a0dd49SMartin Probst
TEST_F(SortImportsTestJS,AffectedRange)224c4a0dd49SMartin Probst TEST_F(SortImportsTestJS, AffectedRange) {
225b480ffbcSMartin Probst // Affected range inside of import statements.
226b480ffbcSMartin Probst verifySort("import {sym} from 'a';\n"
227b480ffbcSMartin Probst "import {sym} from 'b';\n"
228c4a0dd49SMartin Probst "import {sym} from 'c';\n"
229b480ffbcSMartin Probst "\n"
230c4a0dd49SMartin Probst "let x = 1;",
231c4a0dd49SMartin Probst "import {sym} from 'c';\n"
232c4a0dd49SMartin Probst "import {sym} from 'b';\n"
233c4a0dd49SMartin Probst "import {sym} from 'a';\n"
234c4a0dd49SMartin Probst "let x = 1;",
235c4a0dd49SMartin Probst 0, 30);
236b480ffbcSMartin Probst // Affected range outside of import statements.
237c4a0dd49SMartin Probst verifySort("import {sym} from 'c';\n"
238c4a0dd49SMartin Probst "import {sym} from 'b';\n"
239b480ffbcSMartin Probst "import {sym} from 'a';\n"
240c4a0dd49SMartin Probst "\n"
241c4a0dd49SMartin Probst "let x = 1;",
242c4a0dd49SMartin Probst "import {sym} from 'c';\n"
243c4a0dd49SMartin Probst "import {sym} from 'b';\n"
244c4a0dd49SMartin Probst "import {sym} from 'a';\n"
245c4a0dd49SMartin Probst "\n"
246c4a0dd49SMartin Probst "let x = 1;",
247b480ffbcSMartin Probst 70, 1);
248c4a0dd49SMartin Probst }
249c4a0dd49SMartin Probst
TEST_F(SortImportsTestJS,SortingCanShrink)2506f43efbdSMartin Probst TEST_F(SortImportsTestJS, SortingCanShrink) {
2516f43efbdSMartin Probst // Sort excluding a suffix.
2526f43efbdSMartin Probst verifySort("import {B} from 'a';\n"
2536f43efbdSMartin Probst "import {A} from 'b';\n"
2546f43efbdSMartin Probst "\n"
2556f43efbdSMartin Probst "1;",
2566f43efbdSMartin Probst "import {A} from 'b';\n"
2576f43efbdSMartin Probst "\n"
2586f43efbdSMartin Probst "import {B} from 'a';\n"
2596f43efbdSMartin Probst "\n"
2606f43efbdSMartin Probst "1;");
2616f43efbdSMartin Probst }
2626f43efbdSMartin Probst
TEST_F(SortImportsTestJS,TrailingComma)263a8c9d154SMartin Probst TEST_F(SortImportsTestJS, TrailingComma) {
264e3ecdf7dSOwen Pan verifySort("import {A, B,} from 'aa';\n", "import {B, A,} from 'aa';");
265a8c9d154SMartin Probst }
266a8c9d154SMartin Probst
TEST_F(SortImportsTestJS,SortCaseInsensitive)2672a19454aSMartin Probst TEST_F(SortImportsTestJS, SortCaseInsensitive) {
2682a19454aSMartin Probst verifySort("import {A} from 'aa';\n"
2692a19454aSMartin Probst "import {A} from 'Ab';\n"
2702a19454aSMartin Probst "import {A} from 'b';\n"
2712a19454aSMartin Probst "import {A} from 'Bc';\n"
2722a19454aSMartin Probst "\n"
2732a19454aSMartin Probst "1;",
2742a19454aSMartin Probst "import {A} from 'b';\n"
2752a19454aSMartin Probst "import {A} from 'Bc';\n"
2762a19454aSMartin Probst "import {A} from 'Ab';\n"
2772a19454aSMartin Probst "import {A} from 'aa';\n"
2782a19454aSMartin Probst "\n"
2792a19454aSMartin Probst "1;");
2802a19454aSMartin Probst verifySort("import {aa, Ab, b, Bc} from 'x';\n"
2812a19454aSMartin Probst "\n"
2822a19454aSMartin Probst "1;",
2832a19454aSMartin Probst "import {b, Bc, Ab, aa} from 'x';\n"
2842a19454aSMartin Probst "\n"
2852a19454aSMartin Probst "1;");
2862a19454aSMartin Probst }
2872a19454aSMartin Probst
TEST_F(SortImportsTestJS,SortMultiLine)28893008f01SMartin Probst TEST_F(SortImportsTestJS, SortMultiLine) {
28993008f01SMartin Probst // Reproduces issue where multi-line import was not parsed correctly.
29093008f01SMartin Probst verifySort("import {A} from 'a';\n"
29193008f01SMartin Probst "import {A} from 'b';\n"
29293008f01SMartin Probst "\n"
29393008f01SMartin Probst "1;",
29493008f01SMartin Probst "import\n"
29593008f01SMartin Probst "{\n"
29693008f01SMartin Probst "A\n"
29793008f01SMartin Probst "}\n"
29893008f01SMartin Probst "from\n"
29993008f01SMartin Probst "'b';\n"
30093008f01SMartin Probst "import {A} from 'a';\n"
30193008f01SMartin Probst "\n"
30293008f01SMartin Probst "1;");
30393008f01SMartin Probst }
30493008f01SMartin Probst
TEST_F(SortImportsTestJS,SortDefaultImports)3054bf1d7adSMartin Probst TEST_F(SortImportsTestJS, SortDefaultImports) {
3064bf1d7adSMartin Probst // Reproduces issue where multi-line import was not parsed correctly.
3074bf1d7adSMartin Probst verifySort("import {A} from 'a';\n"
3084bf1d7adSMartin Probst "import {default as B} from 'b';\n",
3094bf1d7adSMartin Probst "import {default as B} from 'b';\n"
310e3ecdf7dSOwen Pan "import {A} from 'a';");
3114bf1d7adSMartin Probst }
3124bf1d7adSMartin Probst
TEST_F(SortImportsTestJS,MergeImports)313d45df0d2SMartin Probst TEST_F(SortImportsTestJS, MergeImports) {
314d45df0d2SMartin Probst // basic operation
315d45df0d2SMartin Probst verifySort("import {X, Y} from 'a';\n"
316d45df0d2SMartin Probst "import {Z} from 'z';\n"
317d45df0d2SMartin Probst "\n"
318e3ecdf7dSOwen Pan "X + Y + Z;",
319d45df0d2SMartin Probst "import {X} from 'a';\n"
320d45df0d2SMartin Probst "import {Z} from 'z';\n"
321d45df0d2SMartin Probst "import {Y} from 'a';\n"
322d45df0d2SMartin Probst "\n"
323e3ecdf7dSOwen Pan "X + Y + Z;");
324d45df0d2SMartin Probst
3254d195f1bSMartin Probst // merge only, no resorting.
3264d195f1bSMartin Probst verifySort("import {A, B} from 'foo';\n", "import {A} from 'foo';\n"
3274d195f1bSMartin Probst "import {B} from 'foo';");
3284d195f1bSMartin Probst
329d45df0d2SMartin Probst // empty imports
330d45df0d2SMartin Probst verifySort("import {A} from 'foo';\n", "import {} from 'foo';\n"
331d45df0d2SMartin Probst "import {A} from 'foo';");
332d45df0d2SMartin Probst
333d45df0d2SMartin Probst // ignores import *
334d45df0d2SMartin Probst verifySort("import * as foo from 'foo';\n"
335e3ecdf7dSOwen Pan "import {A} from 'foo';",
336d45df0d2SMartin Probst "import * as foo from 'foo';\n"
337e3ecdf7dSOwen Pan "import {A} from 'foo';");
338d45df0d2SMartin Probst
339d45df0d2SMartin Probst // ignores default import
340d45df0d2SMartin Probst verifySort("import X from 'foo';\n"
341e3ecdf7dSOwen Pan "import {A} from 'foo';",
342d45df0d2SMartin Probst "import X from 'foo';\n"
343e3ecdf7dSOwen Pan "import {A} from 'foo';");
344d45df0d2SMartin Probst
345d45df0d2SMartin Probst // keeps comments
346d45df0d2SMartin Probst // known issue: loses the 'also a' comment.
347d45df0d2SMartin Probst verifySort("// a\n"
348d45df0d2SMartin Probst "import {/* x */ X, /* y */ Y} from 'a';\n"
349d45df0d2SMartin Probst "// z\n"
350d45df0d2SMartin Probst "import {Z} from 'z';\n"
351d45df0d2SMartin Probst "\n"
352e3ecdf7dSOwen Pan "X + Y + Z;",
353d45df0d2SMartin Probst "// a\n"
354d45df0d2SMartin Probst "import {/* y */ Y} from 'a';\n"
355d45df0d2SMartin Probst "// z\n"
356d45df0d2SMartin Probst "import {Z} from 'z';\n"
357d45df0d2SMartin Probst "// also a\n"
358d45df0d2SMartin Probst "import {/* x */ X} from 'a';\n"
359d45df0d2SMartin Probst "\n"
360e3ecdf7dSOwen Pan "X + Y + Z;");
3613d4a6037SMartin Probst
3623d4a6037SMartin Probst // do not merge imports and exports
3633d4a6037SMartin Probst verifySort("import {A} from 'foo';\n"
364b2780cd7SMartin Probst "\n"
365b2780cd7SMartin Probst "export {B} from 'foo';\n",
3663d4a6037SMartin Probst "import {A} from 'foo';\n"
3673d4a6037SMartin Probst "export {B} from 'foo';");
3683d4a6037SMartin Probst // do merge exports
3693d4a6037SMartin Probst verifySort("export {A, B} from 'foo';\n", "export {A} from 'foo';\n"
3703d4a6037SMartin Probst "export {B} from 'foo';");
371fbc6f42dSMartin Probst
372fbc6f42dSMartin Probst // do not merge side effect imports with named ones
373fbc6f42dSMartin Probst verifySort("import './a';\n"
374fbc6f42dSMartin Probst "\n"
375fbc6f42dSMartin Probst "import {bar} from './a';\n",
376fbc6f42dSMartin Probst "import {bar} from './a';\n"
377e3ecdf7dSOwen Pan "import './a';");
378d45df0d2SMartin Probst }
379d45df0d2SMartin Probst
TEST_F(SortImportsTestJS,RespectsClangFormatOff)380b2780cd7SMartin Probst TEST_F(SortImportsTestJS, RespectsClangFormatOff) {
381b2780cd7SMartin Probst verifySort("// clang-format off\n"
382b2780cd7SMartin Probst "import {B} from './b';\n"
383b2780cd7SMartin Probst "import {A} from './a';\n"
384e3ecdf7dSOwen Pan "// clang-format on",
385b2780cd7SMartin Probst "// clang-format off\n"
386b2780cd7SMartin Probst "import {B} from './b';\n"
387b2780cd7SMartin Probst "import {A} from './a';\n"
388e3ecdf7dSOwen Pan "// clang-format on");
389b2780cd7SMartin Probst
390b2780cd7SMartin Probst verifySort("import {A} from './sorted1_a';\n"
391b2780cd7SMartin Probst "import {B} from './sorted1_b';\n"
392b2780cd7SMartin Probst "// clang-format off\n"
393b2780cd7SMartin Probst "import {B} from './unsorted_b';\n"
394b2780cd7SMartin Probst "import {A} from './unsorted_a';\n"
395b2780cd7SMartin Probst "// clang-format on\n"
396b2780cd7SMartin Probst "import {A} from './sorted2_a';\n"
397b2780cd7SMartin Probst "import {B} from './sorted2_b';\n",
398b2780cd7SMartin Probst "import {B} from './sorted1_b';\n"
399b2780cd7SMartin Probst "import {A} from './sorted1_a';\n"
400b2780cd7SMartin Probst "// clang-format off\n"
401b2780cd7SMartin Probst "import {B} from './unsorted_b';\n"
402b2780cd7SMartin Probst "import {A} from './unsorted_a';\n"
403b2780cd7SMartin Probst "// clang-format on\n"
404b2780cd7SMartin Probst "import {B} from './sorted2_b';\n"
405e3ecdf7dSOwen Pan "import {A} from './sorted2_a';");
406b2780cd7SMartin Probst
407b2780cd7SMartin Probst // Boundary cases
408e3ecdf7dSOwen Pan verifySort("// clang-format on", "// clang-format on");
409e3ecdf7dSOwen Pan verifySort("// clang-format off", "// clang-format off");
410b2780cd7SMartin Probst verifySort("// clang-format on\n"
411e3ecdf7dSOwen Pan "// clang-format off",
412b2780cd7SMartin Probst "// clang-format on\n"
413e3ecdf7dSOwen Pan "// clang-format off");
414b2780cd7SMartin Probst verifySort("// clang-format off\n"
415b2780cd7SMartin Probst "// clang-format on\n"
416b2780cd7SMartin Probst "import {A} from './a';\n"
417b2780cd7SMartin Probst "import {B} from './b';\n",
418b2780cd7SMartin Probst "// clang-format off\n"
419b2780cd7SMartin Probst "// clang-format on\n"
420b2780cd7SMartin Probst "import {B} from './b';\n"
421e3ecdf7dSOwen Pan "import {A} from './a';");
422b2780cd7SMartin Probst // section ends with comment
423b2780cd7SMartin Probst verifySort("// clang-format on\n"
424b2780cd7SMartin Probst "import {A} from './a';\n"
425b2780cd7SMartin Probst "import {B} from './b';\n"
426b2780cd7SMartin Probst "import {C} from './c';\n"
427b2780cd7SMartin Probst "\n" // inserted empty line is working as intended: splits imports
428b2780cd7SMartin Probst // section from main code body
429e3ecdf7dSOwen Pan "// clang-format off",
430b2780cd7SMartin Probst "// clang-format on\n"
431b2780cd7SMartin Probst "import {C} from './c';\n"
432b2780cd7SMartin Probst "import {B} from './b';\n"
433b2780cd7SMartin Probst "import {A} from './a';\n"
434e3ecdf7dSOwen Pan "// clang-format off");
435b2780cd7SMartin Probst }
436b2780cd7SMartin Probst
TEST_F(SortImportsTestJS,RespectsClangFormatOffInNamedImports)43763042d46SMartin Probst TEST_F(SortImportsTestJS, RespectsClangFormatOffInNamedImports) {
43863042d46SMartin Probst verifySort("// clang-format off\n"
43963042d46SMartin Probst "import {B, A} from './b';\n"
44063042d46SMartin Probst "// clang-format on\n"
44163042d46SMartin Probst "const x = 1;",
44263042d46SMartin Probst "// clang-format off\n"
44363042d46SMartin Probst "import {B, A} from './b';\n"
44463042d46SMartin Probst "// clang-format on\n"
44563042d46SMartin Probst "const x = 1;");
44663042d46SMartin Probst }
44763042d46SMartin Probst
TEST_F(SortImportsTestJS,ImportEqAliases)44803c59765SMartin Probst TEST_F(SortImportsTestJS, ImportEqAliases) {
44903c59765SMartin Probst verifySort("import {B} from 'bar';\n"
45003c59765SMartin Probst "import {A} from 'foo';\n"
45103c59765SMartin Probst "\n"
45203c59765SMartin Probst "import Z = A.C;\n"
45303c59765SMartin Probst "import Y = B.C.Z;\n"
45403c59765SMartin Probst "\n"
45503c59765SMartin Probst "export {Z};\n"
45603c59765SMartin Probst "\n"
457e3ecdf7dSOwen Pan "console.log(Z);",
45803c59765SMartin Probst "import {A} from 'foo';\n"
45903c59765SMartin Probst "import Z = A.C;\n"
46003c59765SMartin Probst "export {Z};\n"
46103c59765SMartin Probst "import {B} from 'bar';\n"
46203c59765SMartin Probst "import Y = B.C.Z;\n"
46303c59765SMartin Probst "\n"
464e3ecdf7dSOwen Pan "console.log(Z);");
46503c59765SMartin Probst }
46603c59765SMartin Probst
TEST_F(SortImportsTestJS,ImportExportType)46734b422baSJan Kuhle TEST_F(SortImportsTestJS, ImportExportType) {
46834b422baSJan Kuhle verifySort("import type {sym} from 'a';\n"
46934b422baSJan Kuhle "import {type sym} from 'b';\n"
47034b422baSJan Kuhle "import {sym} from 'c';\n"
47134b422baSJan Kuhle "import type sym from 'd';\n"
47234b422baSJan Kuhle "import type * as sym from 'e';\n"
47334b422baSJan Kuhle "\n"
47434b422baSJan Kuhle "let x = 1;",
47534b422baSJan Kuhle "import {sym} from 'c';\n"
47634b422baSJan Kuhle "import type {sym} from 'a';\n"
47734b422baSJan Kuhle "import type * as sym from 'e';\n"
47834b422baSJan Kuhle "import type sym from 'd';\n"
47934b422baSJan Kuhle "import {type sym} from 'b';\n"
48034b422baSJan Kuhle "let x = 1;");
48134b422baSJan Kuhle
48234b422baSJan Kuhle // Symbols within import statement
48334b422baSJan Kuhle verifySort("import {type sym1, type sym2 as a, sym3} from 'b';\n",
484e3ecdf7dSOwen Pan "import {type sym2 as a, type sym1, sym3} from 'b';");
48534b422baSJan Kuhle
48634b422baSJan Kuhle // Merging
48734b422baSJan Kuhle verifySort("import {X, type Z} from 'a';\n"
48834b422baSJan Kuhle "import type {Y} from 'a';\n"
48934b422baSJan Kuhle "\n"
490e3ecdf7dSOwen Pan "X + Y + Z;",
49134b422baSJan Kuhle "import {X} from 'a';\n"
49234b422baSJan Kuhle "import {type Z} from 'a';\n"
49334b422baSJan Kuhle "import type {Y} from 'a';\n"
49434b422baSJan Kuhle "\n"
495e3ecdf7dSOwen Pan "X + Y + Z;");
49634b422baSJan Kuhle
49734b422baSJan Kuhle // Merging: empty imports
49834b422baSJan Kuhle verifySort("import type {A} from 'foo';\n", "import type {} from 'foo';\n"
49934b422baSJan Kuhle "import type {A} from 'foo';");
50034b422baSJan Kuhle
50134b422baSJan Kuhle // Merging: exports
50234b422baSJan Kuhle verifySort("export {A, type B} from 'foo';\n",
50334b422baSJan Kuhle "export {A} from 'foo';\n"
50434b422baSJan Kuhle "export {type B} from 'foo';");
505e1f34b73SJan Kuhle
506e1f34b73SJan Kuhle // `export type X = Y;` should terminate import sorting. The following export
507e1f34b73SJan Kuhle // statements should therefore not merge.
508e1f34b73SJan Kuhle verifySort("export type A = B;\n"
509e1f34b73SJan Kuhle "export {X};\n"
510e3ecdf7dSOwen Pan "export {Y};",
511e1f34b73SJan Kuhle "export type A = B;\n"
512e1f34b73SJan Kuhle "export {X};\n"
513e3ecdf7dSOwen Pan "export {Y};");
51434b422baSJan Kuhle }
51534b422baSJan Kuhle
TEST_F(SortImportsTestJS,TemplateKeyword)516265ed681SOwen Pan TEST_F(SortImportsTestJS, TemplateKeyword) {
517265ed681SOwen Pan // Reproduces issue where importing "template" disables imports sorting.
518265ed681SOwen Pan verifySort("import {template} from './a';\n"
519265ed681SOwen Pan "import {b} from './b';\n",
520265ed681SOwen Pan "import {b} from './b';\n"
521265ed681SOwen Pan "import {template} from './a';");
522265ed681SOwen Pan }
523265ed681SOwen Pan
524c4a0dd49SMartin Probst } // end namespace
525c4a0dd49SMartin Probst } // end namespace format
526c4a0dd49SMartin Probst } // end namespace clang
527