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 17namespace clang { 18namespace format { 19namespace { 20 21class SortImportsTestJS : public ::testing::Test { 22protected: 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 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 48TEST_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 61TEST_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 73TEST_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 88TEST_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 95TEST_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 106TEST_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 115TEST_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 122TEST_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 134TEST_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 152TEST_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 179TEST_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 192TEST_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 229TEST_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 242TEST_F(SortImportsTestJS, TrailingComma) { 243 verifySort("import {A, B,} from 'aa';\n", "import {B, A,} from 'aa';\n"); 244} 245 246TEST_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