Prefer top-level type-only imports in verbatimModuleSyntax (#52747)

This commit is contained in:
Andrew Branch 2023-02-14 10:23:08 -08:00 committed by GitHub
parent ab40f5e5d0
commit 48e812aa07
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 60 additions and 4 deletions

View File

@ -372,7 +372,8 @@ function createImportAdderWorker(sourceFile: SourceFile, program: Program, useAu
quotePreference,
defaultImport,
namedImports && arrayFrom(namedImports.entries(), ([name, addAsTypeOnly]) => ({ addAsTypeOnly, name })),
namespaceLikeImport);
namespaceLikeImport,
compilerOptions);
newDeclarations = combine(newDeclarations, declarations);
});
if (newDeclarations) {
@ -1249,7 +1250,13 @@ function codeActionForFixWorker(changes: textChanges.ChangeTracker, sourceFile:
const namespaceLikeImport = importKind === ImportKind.Namespace || importKind === ImportKind.CommonJS
? { importKind, name: qualification?.namespacePrefix || symbolName, addAsTypeOnly }
: undefined;
insertImports(changes, sourceFile, getDeclarations(moduleSpecifier, quotePreference, defaultImport, namedImports, namespaceLikeImport), /*blankLineBetween*/ true, preferences);
insertImports(changes, sourceFile, getDeclarations(
moduleSpecifier,
quotePreference,
defaultImport,
namedImports,
namespaceLikeImport,
compilerOptions), /*blankLineBetween*/ true, preferences);
if (qualification) {
addNamespaceQualifier(changes, sourceFile, qualification);
}
@ -1489,12 +1496,18 @@ function getNewImports(
quotePreference: QuotePreference,
defaultImport: Import | undefined,
namedImports: readonly Import[] | undefined,
namespaceLikeImport: Import & { importKind: ImportKind.CommonJS | ImportKind.Namespace } | undefined
namespaceLikeImport: Import & { importKind: ImportKind.CommonJS | ImportKind.Namespace } | undefined,
compilerOptions: CompilerOptions,
): AnyImportSyntax | readonly AnyImportSyntax[] {
const quotedModuleSpecifier = makeStringLiteral(moduleSpecifier, quotePreference);
let statements: AnyImportSyntax | readonly AnyImportSyntax[] | undefined;
if (defaultImport !== undefined || namedImports?.length) {
const topLevelTypeOnly = (!defaultImport || needsTypeOnly(defaultImport)) && every(namedImports, needsTypeOnly);
// `verbatimModuleSyntax` should prefer top-level `import type` -
// even though it's not an error, it would add unnecessary runtime emit.
const topLevelTypeOnly = (!defaultImport || needsTypeOnly(defaultImport)) && every(namedImports, needsTypeOnly) ||
compilerOptions.verbatimModuleSyntax &&
defaultImport?.addAsTypeOnly !== AddAsTypeOnly.NotAllowed &&
!some(namedImports, i => i.addAsTypeOnly === AddAsTypeOnly.NotAllowed);
statements = combine(statements, makeImport(
defaultImport && factory.createIdentifier(defaultImport.name),
namedImports?.map(({ addAsTypeOnly, name }) => factory.createImportSpecifier(

View File

@ -0,0 +1,43 @@
/// <reference path="fourslash.ts" />
// @verbatimModuleSyntax: true
// @module: esnext
// @moduleResolution: bundler
// @Filename: /ts.d.ts
//// declare namespace ts {
//// interface SourceFile {
//// text: string;
//// }
//// function createSourceFile(): SourceFile;
//// }
//// export = ts;
// @Filename: /types.ts
//// export interface VFS {
//// getSourceFile(path: string): ts/**/
//// }
verify.completions({
marker: "",
includes: [{
name: "ts",
source: "./ts",
sourceDisplay: "./ts",
hasAction: true,
sortText: completion.SortText.AutoImportSuggestions,
}],
preferences: {
includeCompletionsForModuleExports: true,
allowIncompleteCompletions: true,
},
}).andApplyCodeAction({
name: "ts",
source: "./ts",
description: `Add import from "./ts"`,
newFileContent: `import type ts from "./ts";
export interface VFS {
getSourceFile(path: string): ts
}`
});