Type-only import specifiers (#45998)

* Parse type-only import specifiers

* Add type-only export specifiers

* Update transform and emit

* Update checking

* Fix elision when combined with importsNotUsedAsValues=preserve

* Accept baselines

* Add test

* WIP auto imports updates

* First auto-imports test working

* More auto-import tests

* Fix auto imports of type-only exports

* Add test for promoting type-only import

* Sort import/export specifiers by type-onlyness

* Update completions for `import { type |`

* Update other completions tests

* Respect organize imports sorting when promoting type-only to regular while adding a specifier

* Fix comment mistakes

* Update src/services/codefixes/importFixes.ts

Co-authored-by: Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com>

* Rearrange some order of assignments in parser

* Split huge if statement

* Remove redundant check

* Update new transformer

* Fix import statement completions

* Fix type keyword completions good grief

* Fix last tests

Co-authored-by: Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com>
This commit is contained in:
Andrew Branch
2021-09-27 12:38:30 -07:00
committed by GitHub
parent 26aef89a72
commit e160bc8c0d
80 changed files with 1842 additions and 349 deletions

View File

@@ -335,4 +335,4 @@ namespace Harness {
return { unitName: unitName || this.makeUnitName(lastUnit.name, rootDir), content: lastUnit.content, fileOptions: lastUnit.fileOptions };
}
}
}
}

View File

@@ -206,6 +206,13 @@ namespace ts {
assertListEqual(actualCoalescedExports, expectedCoalescedExports);
});
it("Sort specifiers - type-only", () => {
const sortedImports = parseImports(`import { type z, y, type x, c, type b, a } from "lib";`);
const actualCoalescedImports = OrganizeImports.coalesceImports(sortedImports);
const expectedCoalescedImports = parseImports(`import { a, c, y, type b, type x, type z } from "lib";`);
assertListEqual(actualCoalescedImports, expectedCoalescedImports);
});
it("Combine namespace re-exports", () => {
const sortedExports = parseExports(
`export * from "lib";`,

View File

@@ -535,7 +535,7 @@ import {
x
} from "bar"`;
runSingleFileTest("insertNodeInListAfter10", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(factory.createIdentifier("b"), factory.createIdentifier("a")));
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(/*isTypeOnly*/ false, factory.createIdentifier("b"), factory.createIdentifier("a")));
});
}
{
@@ -544,7 +544,7 @@ import {
x // this is x
} from "bar"`;
runSingleFileTest("insertNodeInListAfter11", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(factory.createIdentifier("b"), factory.createIdentifier("a")));
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(/*isTypeOnly*/ false, factory.createIdentifier("b"), factory.createIdentifier("a")));
});
}
{
@@ -554,7 +554,7 @@ import {
} from "bar"`;
runSingleFileTest("insertNodeInListAfter12", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
// eslint-disable-next-line boolean-trivia
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(undefined, factory.createIdentifier("a")));
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(/*isTypeOnly*/ false, undefined, factory.createIdentifier("a")));
});
}
{
@@ -564,7 +564,7 @@ import {
} from "bar"`;
runSingleFileTest("insertNodeInListAfter13", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
// eslint-disable-next-line boolean-trivia
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(undefined, factory.createIdentifier("a")));
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(/*isTypeOnly*/ false, undefined, factory.createIdentifier("a")));
});
}
{
@@ -574,7 +574,7 @@ import {
x
} from "bar"`;
runSingleFileTest("insertNodeInListAfter14", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(factory.createIdentifier("b"), factory.createIdentifier("a")));
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(/*isTypeOnly*/ false, factory.createIdentifier("b"), factory.createIdentifier("a")));
});
}
{
@@ -584,7 +584,7 @@ import {
x // this is x
} from "bar"`;
runSingleFileTest("insertNodeInListAfter15", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(factory.createIdentifier("b"), factory.createIdentifier("a")));
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(/*isTypeOnly*/ false, factory.createIdentifier("b"), factory.createIdentifier("a")));
});
}
{
@@ -595,7 +595,7 @@ import {
} from "bar"`;
runSingleFileTest("insertNodeInListAfter16", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
// eslint-disable-next-line boolean-trivia
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(undefined, factory.createIdentifier("a")));
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(/*isTypeOnly*/ false, undefined, factory.createIdentifier("a")));
});
}
{
@@ -606,7 +606,7 @@ import {
} from "bar"`;
runSingleFileTest("insertNodeInListAfter17", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
// eslint-disable-next-line boolean-trivia
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(undefined, factory.createIdentifier("a")));
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(/*isTypeOnly*/ false, undefined, factory.createIdentifier("a")));
});
}
{
@@ -616,14 +616,14 @@ import {
} from "bar"`;
runSingleFileTest("insertNodeInListAfter18", /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
// eslint-disable-next-line boolean-trivia
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(undefined, factory.createIdentifier("a")));
changeTracker.insertNodeInListAfter(sourceFile, findChild("x", sourceFile), factory.createImportSpecifier(/*isTypeOnly*/ false, undefined, factory.createIdentifier("a")));
});
}
{
const runTest = (name: string, text: string) => runSingleFileTest(name, /*placeOpenBraceOnNewLineForFunctions*/ false, text, /*validateNodes*/ false, (sourceFile, changeTracker) => {
for (const specifier of ["x3", "x4", "x5"]) {
// eslint-disable-next-line boolean-trivia
changeTracker.insertNodeInListAfter(sourceFile, findChild("x2", sourceFile), factory.createImportSpecifier(undefined, factory.createIdentifier(specifier)));
changeTracker.insertNodeInListAfter(sourceFile, findChild("x2", sourceFile), factory.createImportSpecifier(/*isTypeOnly*/ false, undefined, factory.createIdentifier(specifier)));
}
});

View File

@@ -275,7 +275,7 @@ namespace ts {
if (node.kind === SyntaxKind.ExportDeclaration) {
const ed = node as Node as ExportDeclaration;
const exports = [{ name: "x" }];
const exportSpecifiers = exports.map(e => factory.createExportSpecifier(e.name, e.name));
const exportSpecifiers = exports.map(e => factory.createExportSpecifier(/*isTypeOnly*/ false, e.name, e.name));
const exportClause = factory.createNamedExports(exportSpecifiers);
const newEd = factory.updateExportDeclaration(ed, ed.decorators, ed.modifiers, ed.isTypeOnly, exportClause, ed.moduleSpecifier, ed.assertClause);