SortImportsTestJS.cpp 8.8 KB

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