brintos

brintos / llvm-project-archived public Read only

0
0
Text · 17.3 KiB · 59ce621 Raw
527 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "FormatTestUtils.h"10#include "clang/Format/Format.h"11#include "llvm/Support/Debug.h"12#include "gtest/gtest.h"13 14#define DEBUG_TYPE "format-test"15 16namespace clang {17namespace format {18namespace {19 20class SortImportsTestJS : public testing::Test {21protected:22  std::string sort(StringRef Code, unsigned Offset = 0, unsigned Length = 0) {23    StringRef FileName = "input.js";24    if (Length == 0U)25      Length = Code.size() - Offset;26    std::vector<tooling::Range> Ranges(1, tooling::Range(Offset, Length));27    auto Sorted =28        applyAllReplacements(Code, sortIncludes(Style, Code, Ranges, FileName));29    EXPECT_TRUE(static_cast<bool>(Sorted));30    auto Formatted = applyAllReplacements(31        *Sorted, reformat(Style, *Sorted, Ranges, FileName));32    EXPECT_TRUE(static_cast<bool>(Formatted));33    return *Formatted;34  }35 36  void _verifySort(const char *File, int Line, StringRef Expected,37                   StringRef Code, unsigned Offset = 0, unsigned Length = 0) {38    testing::ScopedTrace t(File, Line, testing::Message() << Code.str());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 48#define verifySort(...) _verifySort(__FILE__, __LINE__, __VA_ARGS__)49 50TEST_F(SortImportsTestJS, AlreadySorted) {51  verifySort("import {sym} from 'a';\n"52             "import {sym} from 'b';\n"53             "import {sym} from 'c';\n"54             "\n"55             "let x = 1;",56             "import {sym} from 'a';\n"57             "import {sym} from 'b';\n"58             "import {sym} from 'c';\n"59             "\n"60             "let x = 1;");61}62 63TEST_F(SortImportsTestJS, BasicSorting) {64  verifySort("import {sym} from 'a';\n"65             "import {sym} from 'b';\n"66             "import {sym} from 'c';\n"67             "\n"68             "let x = 1;",69             "import {sym} from 'a';\n"70             "import {sym} from 'c';\n"71             "import {sym} from 'b';\n"72             "let x = 1;");73}74 75TEST_F(SortImportsTestJS, DefaultBinding) {76  verifySort("import A from 'a';\n"77             "import B from 'b';\n"78             "\n"79             "let x = 1;",80             "import B from 'b';\n"81             "import A from 'a';\n"82             "let x = 1;");83}84 85TEST_F(SortImportsTestJS, DefaultAndNamedBinding) {86  verifySort("import A, {a} from 'a';\n"87             "import B, {b} from 'b';\n"88             "\n"89             "let x = 1;",90             "import B, {b} from 'b';\n"91             "import A, {a} from 'a';\n"92             "let x = 1;");93}94 95TEST_F(SortImportsTestJS, WrappedImportStatements) {96  verifySort("import {sym1, sym2} from 'a';\n"97             "import {sym} from 'b';\n"98             "\n"99             "1;",100             "import\n"101             "  {sym}\n"102             "  from 'b';\n"103             "import {\n"104             "  sym1,\n"105             "  sym2\n"106             "} from 'a';\n"107             "1;");108}109 110TEST_F(SortImportsTestJS, SeparateMainCodeBody) {111  verifySort("import {sym} from 'a';"112             "\n"113             "let x = 1;",114             "import {sym} from 'a'; let x = 1;");115}116 117TEST_F(SortImportsTestJS, Comments) {118  verifySort("/** @fileoverview This is a great file. */\n"119             "// A very important import follows.\n"120             "import {sym} from 'a';  /* more comments */\n"121             "import {sym} from 'b';  // from //foo:bar\n",122             "/** @fileoverview This is a great file. */\n"123             "import {sym} from 'b';  // from //foo:bar\n"124             "// A very important import follows.\n"125             "import {sym} from 'a';  /* more comments */");126  verifySort("import {sym} from 'a';\n"127             "import {sym} from 'b';\n"128             "\n"129             "/** Comment on variable. */\n"130             "const x = 1;",131             "import {sym} from 'b';\n"132             "import {sym} from 'a';\n"133             "\n"134             "/** Comment on variable. */\n"135             "const x = 1;");136}137 138TEST_F(SortImportsTestJS, SortStar) {139  verifySort("import * as foo from 'a';\n"140             "import {sym} from 'a';\n"141             "import * as bar from 'b';\n",142             "import {sym} from 'a';\n"143             "import * as foo from 'a';\n"144             "import * as bar from 'b';");145}146 147TEST_F(SortImportsTestJS, AliasesSymbols) {148  verifySort("import {sym1 as alias1} from 'b';\n"149             "import {sym2 as alias2, sym3 as alias3} from 'c';\n",150             "import {sym2 as alias2, sym3 as alias3} from 'c';\n"151             "import {sym1 as alias1} from 'b';");152}153 154TEST_F(SortImportsTestJS, SortSymbols) {155  verifySort("import {sym1, sym2 as a, sym3} from 'b';\n",156             "import {sym2 as a, sym1, sym3} from 'b';");157  verifySort("import {sym1 /* important! */, /*!*/ sym2 as a} from 'b';\n",158             "import {/*!*/ sym2 as a, sym1 /* important! */} from 'b';");159  verifySort("import {sym1, sym2} from 'b';\n", "import {\n"160                                                "  sym2 \n"161                                                ",\n"162                                                " sym1 \n"163                                                "} from 'b';");164}165 166TEST_F(SortImportsTestJS, GroupImports) {167  verifySort("import {a} from 'absolute';\n"168             "\n"169             "import {b} from '../parent';\n"170             "import {b} from '../parent/nested';\n"171             "\n"172             "import {b} from './relative/path';\n"173             "import {b} from './relative/path/nested';\n"174             "\n"175             "let x = 1;",176             "import {b} from './relative/path/nested';\n"177             "import {b} from './relative/path';\n"178             "import {b} from '../parent/nested';\n"179             "import {b} from '../parent';\n"180             "import {a} from 'absolute';\n"181             "let x = 1;");182}183 184TEST_F(SortImportsTestJS, Exports) {185  verifySort("import {S} from 'bpath';\n"186             "\n"187             "import {T} from './cpath';\n"188             "\n"189             "export {A, B} from 'apath';\n"190             "export {P} from '../parent';\n"191             "export {R} from './relative';\n"192             "export {S};\n"193             "\n"194             "let x = 1;\n"195             "export y = 1;",196             "export {R} from './relative';\n"197             "import {T} from './cpath';\n"198             "export {S};\n"199             "export {A, B} from 'apath';\n"200             "import {S} from 'bpath';\n"201             "export {P} from '../parent';\n"202             "let x = 1;\n"203             "export y = 1;");204  verifySort("import {S} from 'bpath';\n"205             "\n"206             "export {T} from 'epath';\n",207             "export {T} from 'epath';\n"208             "import {S} from 'bpath';");209}210 211TEST_F(SortImportsTestJS, SideEffectImports) {212  verifySort("import 'ZZside-effect';\n"213             "import 'AAside-effect';\n"214             "\n"215             "import {A} from 'absolute';\n"216             "\n"217             "import {R} from './relative';\n",218             "import {R} from './relative';\n"219             "import 'ZZside-effect';\n"220             "import {A} from 'absolute';\n"221             "import 'AAside-effect';");222}223 224TEST_F(SortImportsTestJS, AffectedRange) {225  // Affected range inside of import statements.226  verifySort("import {sym} from 'a';\n"227             "import {sym} from 'b';\n"228             "import {sym} from 'c';\n"229             "\n"230             "let x = 1;",231             "import {sym} from 'c';\n"232             "import {sym} from 'b';\n"233             "import {sym} from 'a';\n"234             "let x = 1;",235             0, 30);236  // Affected range outside of import statements.237  verifySort("import {sym} from 'c';\n"238             "import {sym} from 'b';\n"239             "import {sym} from 'a';\n"240             "\n"241             "let x = 1;",242             "import {sym} from 'c';\n"243             "import {sym} from 'b';\n"244             "import {sym} from 'a';\n"245             "\n"246             "let x = 1;",247             70, 1);248}249 250TEST_F(SortImportsTestJS, SortingCanShrink) {251  // Sort excluding a suffix.252  verifySort("import {B} from 'a';\n"253             "import {A} from 'b';\n"254             "\n"255             "1;",256             "import {A} from 'b';\n"257             "\n"258             "import {B} from 'a';\n"259             "\n"260             "1;");261}262 263TEST_F(SortImportsTestJS, TrailingComma) {264  verifySort("import {A, B,} from 'aa';\n", "import {B, A,} from 'aa';");265}266 267TEST_F(SortImportsTestJS, SortCaseInsensitive) {268  verifySort("import {A} from 'aa';\n"269             "import {A} from 'Ab';\n"270             "import {A} from 'b';\n"271             "import {A} from 'Bc';\n"272             "\n"273             "1;",274             "import {A} from 'b';\n"275             "import {A} from 'Bc';\n"276             "import {A} from 'Ab';\n"277             "import {A} from 'aa';\n"278             "\n"279             "1;");280  verifySort("import {aa, Ab, b, Bc} from 'x';\n"281             "\n"282             "1;",283             "import {b, Bc, Ab, aa} from 'x';\n"284             "\n"285             "1;");286}287 288TEST_F(SortImportsTestJS, SortMultiLine) {289  // Reproduces issue where multi-line import was not parsed correctly.290  verifySort("import {A} from 'a';\n"291             "import {A} from 'b';\n"292             "\n"293             "1;",294             "import\n"295             "{\n"296             "A\n"297             "}\n"298             "from\n"299             "'b';\n"300             "import {A} from 'a';\n"301             "\n"302             "1;");303}304 305TEST_F(SortImportsTestJS, SortDefaultImports) {306  // Reproduces issue where multi-line import was not parsed correctly.307  verifySort("import {A} from 'a';\n"308             "import {default as B} from 'b';\n",309             "import {default as B} from 'b';\n"310             "import {A} from 'a';");311}312 313TEST_F(SortImportsTestJS, MergeImports) {314  // basic operation315  verifySort("import {X, Y} from 'a';\n"316             "import {Z} from 'z';\n"317             "\n"318             "X + Y + Z;",319             "import {X} from 'a';\n"320             "import {Z} from 'z';\n"321             "import {Y} from 'a';\n"322             "\n"323             "X + Y + Z;");324 325  // merge only, no resorting.326  verifySort("import {A, B} from 'foo';\n", "import {A} from 'foo';\n"327                                            "import {B} from 'foo';");328 329  // empty imports330  verifySort("import {A} from 'foo';\n", "import {} from 'foo';\n"331                                         "import {A} from 'foo';");332 333  // ignores import *334  verifySort("import * as foo from 'foo';\n"335             "import {A} from 'foo';",336             "import   * as foo from 'foo';\n"337             "import {A} from 'foo';");338 339  // ignores default import340  verifySort("import X from 'foo';\n"341             "import {A} from 'foo';",342             "import    X from 'foo';\n"343             "import {A} from 'foo';");344 345  // keeps comments346  // known issue: loses the 'also a' comment.347  verifySort("// a\n"348             "import {/* x */ X, /* y */ Y} from 'a';\n"349             "// z\n"350             "import {Z} from 'z';\n"351             "\n"352             "X + Y + Z;",353             "// a\n"354             "import {/* y */ Y} from 'a';\n"355             "// z\n"356             "import {Z} from 'z';\n"357             "// also a\n"358             "import {/* x */ X} from 'a';\n"359             "\n"360             "X + Y + Z;");361 362  // do not merge imports and exports363  verifySort("import {A} from 'foo';\n"364             "\n"365             "export {B} from 'foo';\n",366             "import {A} from 'foo';\n"367             "export   {B} from 'foo';");368  // do merge exports369  verifySort("export {A, B} from 'foo';\n", "export {A} from 'foo';\n"370                                            "export   {B} from 'foo';");371 372  // do not merge side effect imports with named ones373  verifySort("import './a';\n"374             "\n"375             "import {bar} from './a';\n",376             "import {bar} from './a';\n"377             "import './a';");378}379 380TEST_F(SortImportsTestJS, RespectsClangFormatOff) {381  verifySort("// clang-format off\n"382             "import {B} from './b';\n"383             "import {A} from './a';\n"384             "// clang-format on",385             "// clang-format off\n"386             "import {B} from './b';\n"387             "import {A} from './a';\n"388             "// clang-format on");389 390  verifySort("import {A} from './sorted1_a';\n"391             "import {B} from './sorted1_b';\n"392             "// clang-format off\n"393             "import {B} from './unsorted_b';\n"394             "import {A} from './unsorted_a';\n"395             "// clang-format on\n"396             "import {A} from './sorted2_a';\n"397             "import {B} from './sorted2_b';\n",398             "import {B} from './sorted1_b';\n"399             "import {A} from './sorted1_a';\n"400             "// clang-format off\n"401             "import {B} from './unsorted_b';\n"402             "import {A} from './unsorted_a';\n"403             "// clang-format on\n"404             "import {B} from './sorted2_b';\n"405             "import {A} from './sorted2_a';");406 407  // Boundary cases408  verifySort("// clang-format on", "// clang-format on");409  verifySort("// clang-format off", "// clang-format off");410  verifySort("// clang-format on\n"411             "// clang-format off",412             "// clang-format on\n"413             "// clang-format off");414  verifySort("// clang-format off\n"415             "// clang-format on\n"416             "import {A} from './a';\n"417             "import {B} from './b';\n",418             "// clang-format off\n"419             "// clang-format on\n"420             "import {B} from './b';\n"421             "import {A} from './a';");422  // section ends with comment423  verifySort("// clang-format on\n"424             "import {A} from './a';\n"425             "import {B} from './b';\n"426             "import {C} from './c';\n"427             "\n" // inserted empty line is working as intended: splits imports428                  // section from main code body429             "// clang-format off",430             "// clang-format on\n"431             "import {C} from './c';\n"432             "import {B} from './b';\n"433             "import {A} from './a';\n"434             "// clang-format off");435}436 437TEST_F(SortImportsTestJS, RespectsClangFormatOffInNamedImports) {438  verifySort("// clang-format off\n"439             "import {B, A} from './b';\n"440             "// clang-format on\n"441             "const x = 1;",442             "// clang-format off\n"443             "import {B, A} from './b';\n"444             "// clang-format on\n"445             "const x =   1;");446}447 448TEST_F(SortImportsTestJS, ImportEqAliases) {449  verifySort("import {B} from 'bar';\n"450             "import {A} from 'foo';\n"451             "\n"452             "import Z = A.C;\n"453             "import Y = B.C.Z;\n"454             "\n"455             "export {Z};\n"456             "\n"457             "console.log(Z);",458             "import {A} from 'foo';\n"459             "import Z = A.C;\n"460             "export {Z};\n"461             "import {B} from 'bar';\n"462             "import Y = B.C.Z;\n"463             "\n"464             "console.log(Z);");465}466 467TEST_F(SortImportsTestJS, ImportExportType) {468  verifySort("import type {sym} from 'a';\n"469             "import {type sym} from 'b';\n"470             "import {sym} from 'c';\n"471             "import type sym from 'd';\n"472             "import type * as sym from 'e';\n"473             "\n"474             "let x = 1;",475             "import {sym} from 'c';\n"476             "import type {sym} from 'a';\n"477             "import type * as sym from 'e';\n"478             "import type sym from 'd';\n"479             "import {type sym} from 'b';\n"480             "let x = 1;");481 482  // Symbols within import statement483  verifySort("import {type sym1, type sym2 as a, sym3} from 'b';\n",484             "import {type sym2 as a, type sym1, sym3} from 'b';");485 486  // Merging487  verifySort("import {X, type Z} from 'a';\n"488             "import type {Y} from 'a';\n"489             "\n"490             "X + Y + Z;",491             "import {X} from 'a';\n"492             "import {type Z} from 'a';\n"493             "import type {Y} from 'a';\n"494             "\n"495             "X + Y + Z;");496 497  // Merging: empty imports498  verifySort("import type {A} from 'foo';\n", "import type {} from 'foo';\n"499                                              "import type {A} from 'foo';");500 501  // Merging: exports502  verifySort("export {A, type B} from 'foo';\n",503             "export {A} from 'foo';\n"504             "export   {type B} from 'foo';");505 506  // `export type X = Y;` should terminate import sorting. The following export507  // statements should therefore not merge.508  verifySort("export type A = B;\n"509             "export {X};\n"510             "export {Y};",511             "export type A = B;\n"512             "export {X};\n"513             "export {Y};");514}515 516TEST_F(SortImportsTestJS, TemplateKeyword) {517  // Reproduces issue where importing "template" disables imports sorting.518  verifySort("import {template} from './a';\n"519             "import {b} from './b';\n",520             "import {b} from './b';\n"521             "import {template} from './a';");522}523 524} // end namespace525} // end namespace format526} // end namespace clang527