SortImportsTestJS.cpp 10 KB

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