Skip to content

Commit

Permalink
Group imports before sorting and coalescing
Browse files Browse the repository at this point in the history
  • Loading branch information
amcasey committed Feb 15, 2018
1 parent f459953 commit 7498043
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 189 deletions.
128 changes: 43 additions & 85 deletions src/harness/unittests/organizeImports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,6 @@
namespace ts {
describe("Organize imports", () => {
describe("Sort imports", () => {
it("No imports", () => {
assert.isEmpty(OrganizeImports.sortImports([]));
});

it("One import", () => {
const unsortedImports = parseImports(`import "lib";`);
const actualSortedImports = OrganizeImports.sortImports(unsortedImports);
const expectedSortedImports = unsortedImports;
assertListEqual(expectedSortedImports, actualSortedImports);
});

it("Stable - import kind", () => {
assertUnaffectedBySort(
`import "lib";`,
`import * as x from "lib";`,
`import x from "lib";`,
`import {x} from "lib";`);
});

it("Stable - default property alias", () => {
assertUnaffectedBySort(
`import x from "lib";`,
`import y from "lib";`);
});

it("Stable - module alias", () => {
assertUnaffectedBySort(
`import * as x from "lib";`,
`import * as y from "lib";`);
});

it("Stable - symbol", () => {
assertUnaffectedBySort(
`import {x} from "lib";`,
`import {y} from "lib";`);
});

it("Sort - non-relative vs non-relative", () => {
assertSortsBefore(
`import y from "lib1";`,
Expand All @@ -60,18 +23,10 @@ namespace ts {
`import x from "./lib";`);
});

function assertUnaffectedBySort(...importStrings: string[]) {
const unsortedImports1 = parseImports(...importStrings);
assertListEqual(unsortedImports1, OrganizeImports.sortImports(unsortedImports1));

const unsortedImports2 = reverse(unsortedImports1);
assertListEqual(unsortedImports2, OrganizeImports.sortImports(unsortedImports2));
}

function assertSortsBefore(importString1: string, importString2: string) {
const imports = parseImports(importString1, importString2);
assertListEqual(imports, OrganizeImports.sortImports(imports));
assertListEqual(imports, OrganizeImports.sortImports(reverse(imports)));
const [{moduleSpecifier: moduleSpecifier1}, {moduleSpecifier: moduleSpecifier2}] = parseImports(importString1, importString2);
assert.equal(OrganizeImports.compareModuleSpecifiers(moduleSpecifier1, moduleSpecifier2), Comparison.LessThan);
assert.equal(OrganizeImports.compareModuleSpecifiers(moduleSpecifier2, moduleSpecifier1), Comparison.GreaterThan);
}
});

Expand All @@ -84,7 +39,7 @@ namespace ts {
const sortedImports = parseImports(`import { default as m, a as n, b, y, z as o } from "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = parseImports(`import { a as n, b, default as m, y, z as o } from "lib";`);
assertListEqual(expectedCoalescedImports, actualCoalescedImports);
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});

it("Combine side-effect-only imports", () => {
Expand All @@ -93,7 +48,7 @@ namespace ts {
`import "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = parseImports(`import "lib";`);
assertListEqual(expectedCoalescedImports, actualCoalescedImports);
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});

it("Combine namespace imports", () => {
Expand All @@ -102,7 +57,7 @@ namespace ts {
`import * as y from "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = sortedImports;
assertListEqual(expectedCoalescedImports, actualCoalescedImports);
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});

it("Combine default imports", () => {
Expand All @@ -111,7 +66,7 @@ namespace ts {
`import y from "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = parseImports(`import { default as x, default as y } from "lib";`);
assertListEqual(expectedCoalescedImports, actualCoalescedImports);
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});

it("Combine property imports", () => {
Expand All @@ -120,7 +75,7 @@ namespace ts {
`import { y as z } from "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = parseImports(`import { x, y as z } from "lib";`);
assertListEqual(expectedCoalescedImports, actualCoalescedImports);
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});

it("Combine side-effect-only import with namespace import", () => {
Expand All @@ -129,7 +84,7 @@ namespace ts {
`import * as x from "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = sortedImports;
assertListEqual(expectedCoalescedImports, actualCoalescedImports);
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});

it("Combine side-effect-only import with default import", () => {
Expand All @@ -138,7 +93,7 @@ namespace ts {
`import x from "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = sortedImports;
assertListEqual(expectedCoalescedImports, actualCoalescedImports);
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});

it("Combine side-effect-only import with property import", () => {
Expand All @@ -147,7 +102,7 @@ namespace ts {
`import { x } from "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = sortedImports;
assertListEqual(expectedCoalescedImports, actualCoalescedImports);
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});

it("Combine namespace import with default import", () => {
Expand All @@ -157,7 +112,7 @@ namespace ts {
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = parseImports(
`import y, * as x from "lib";`);
assertListEqual(expectedCoalescedImports, actualCoalescedImports);
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});

it("Combine namespace import with property import", () => {
Expand All @@ -166,7 +121,7 @@ namespace ts {
`import { y } from "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = sortedImports;
assertListEqual(expectedCoalescedImports, actualCoalescedImports);
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});

it("Combine default import with property import", () => {
Expand All @@ -176,7 +131,7 @@ namespace ts {
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = parseImports(
`import x, { y } from "lib";`);
assertListEqual(expectedCoalescedImports, actualCoalescedImports);
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});

it("Combine many imports", () => {
Expand All @@ -195,20 +150,7 @@ namespace ts {
`import * as x from "lib";`,
`import * as y from "lib";`,
`import { a, b, default as w, default as z } from "lib";`);
assertListEqual(expectedCoalescedImports, actualCoalescedImports);
});

it("Combine imports from different modules", () => {
const sortedImports = parseImports(
`import { d } from "lib1";`,
`import { b } from "lib1";`,
`import { c } from "lib2";`,
`import { a } from "lib2";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = parseImports(
`import { b, d } from "lib1";`,
`import { a, c } from "lib2";`);
assertListEqual(expectedCoalescedImports, actualCoalescedImports);
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});

// This is descriptive, rather than normative
Expand All @@ -219,7 +161,7 @@ namespace ts {
`import z from "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = sortedImports;
assertListEqual(expectedCoalescedImports, actualCoalescedImports);
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});
});

Expand All @@ -233,6 +175,17 @@ export default function F2();
`,
};

// Don't bother to actually emit a baseline for this.
it("NoImports", () => {
const testFile = {
path: "/a.ts",
content: "function F() { }",
};
const languageService = makeLanguageService(testFile);
const changes = languageService.organizeImports({ type: "file", fileName: testFile.path }, testFormatOptions);
assert.isEmpty(changes);
});

testOrganizeImports("Simple",
{
path: "/test.ts",
Expand Down Expand Up @@ -283,6 +236,19 @@ D();
libFile);
// tslint:enable no-invalid-template-strings

testOrganizeImports("CoalesceMultipleModules",
{
path: "/test.ts",
content: `
import { d } from "lib1";
import { b } from "lib1";
import { c } from "lib2";
import { a } from "lib2";
`,
},
{ path: "/lib1.ts", content: "" },
{ path: "/lib2.ts", content: "" });

testOrganizeImports("CoalesceTrivia",
{
path: "/test.ts",
Expand Down Expand Up @@ -315,8 +281,8 @@ F2();
const { path: testPath, content: testContent } = testFile;
const languageService = makeLanguageService(testFile, ...otherFiles);
const changes = languageService.organizeImports({ type: "file", fileName: testPath }, testFormatOptions);
assert.equal(1, changes.length);
assert.equal(testPath, changes[0].fileName);
assert.equal(changes.length, 1);
assert.equal(changes[0].fileName, testPath);

Harness.Baseline.runBaseline(baselinePath, () => {
const newText = textChanges.applyChanges(testContent, changes[0].textChanges);
Expand All @@ -340,7 +306,7 @@ F2();
function parseImports(...importStrings: string[]): ReadonlyArray<ImportDeclaration> {
const sourceFile = createSourceFile("a.ts", importStrings.join("\n"), ScriptTarget.ES2015, /*setParentNodes*/ true, ScriptKind.TS);
const imports = filter(sourceFile.statements, isImportDeclaration);
assert.equal(importStrings.length, imports.length);
assert.equal(imports.length, importStrings.length);
return imports;
}

Expand Down Expand Up @@ -414,13 +380,5 @@ F2();
assertEqual(list1[i], list2[i]);
}
}

function reverse<T>(list: ReadonlyArray<T>) {
const result = [];
for (let i = list.length - 1; i >= 0; i--) {
result.push(list[i]);
}
return result;
}
});
}
Loading

0 comments on commit 7498043

Please sign in to comment.