mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Add user preference for preferring type-only auto imports (#56090)
This commit is contained in:
@@ -10014,6 +10014,7 @@ export interface UserPreferences {
|
||||
readonly interactiveInlayHints?: boolean;
|
||||
readonly allowRenameOfImportPath?: boolean;
|
||||
readonly autoImportFileExcludePatterns?: string[];
|
||||
readonly preferTypeOnlyAutoImports?: boolean;
|
||||
readonly organizeImportsIgnoreCase?: "auto" | boolean;
|
||||
readonly organizeImportsCollation?: "ordinal" | "unicode";
|
||||
readonly organizeImportsLocale?: string;
|
||||
|
||||
@@ -3347,12 +3347,16 @@ export class TestState {
|
||||
this.verifyRangeIs(expectedText, includeWhiteSpace);
|
||||
}
|
||||
|
||||
public verifyCodeFixAll({ fixId, fixAllDescription, newFileContent, commands: expectedCommands }: FourSlashInterface.VerifyCodeFixAllOptions): void {
|
||||
const fixWithId = ts.find(this.getCodeFixes(this.activeFile.fileName), a => a.fixId === fixId);
|
||||
public verifyCodeFixAll({ fixId, fixAllDescription, newFileContent, commands: expectedCommands, preferences }: FourSlashInterface.VerifyCodeFixAllOptions): void {
|
||||
if (this.testType === FourSlashTestType.Server && preferences) {
|
||||
this.configure(preferences);
|
||||
}
|
||||
|
||||
const fixWithId = ts.find(this.getCodeFixes(this.activeFile.fileName, /*errorCode*/ undefined, preferences), a => a.fixId === fixId);
|
||||
ts.Debug.assert(fixWithId !== undefined, "No available code fix has the expected id. Fix All is not available if there is only one potentially fixable diagnostic present.", () => `Expected '${fixId}'. Available actions:\n${ts.mapDefined(this.getCodeFixes(this.activeFile.fileName), a => `${a.fixName} (${a.fixId || "no fix id"})`).join("\n")}`);
|
||||
ts.Debug.assertEqual(fixWithId.fixAllDescription, fixAllDescription);
|
||||
|
||||
const { changes, commands } = this.languageService.getCombinedCodeFix({ type: "file", fileName: this.activeFile.fileName }, fixId, this.formatCodeSettings, ts.emptyOptions);
|
||||
const { changes, commands } = this.languageService.getCombinedCodeFix({ type: "file", fileName: this.activeFile.fileName }, fixId, this.formatCodeSettings, preferences || ts.emptyOptions);
|
||||
assert.deepEqual<readonly {}[] | undefined>(commands, expectedCommands);
|
||||
this.verifyNewContent({ newFileContent }, changes);
|
||||
}
|
||||
|
||||
@@ -1869,6 +1869,7 @@ export interface VerifyCodeFixAllOptions {
|
||||
fixAllDescription: string;
|
||||
newFileContent: NewFileContent;
|
||||
commands: readonly {}[];
|
||||
preferences?: ts.UserPreferences;
|
||||
}
|
||||
|
||||
export interface VerifyRefactorOptions {
|
||||
|
||||
@@ -389,6 +389,7 @@ function createImportAdderWorker(sourceFile: SourceFile, program: Program, useAu
|
||||
namedImports && arrayFrom(namedImports.entries(), ([name, addAsTypeOnly]) => ({ addAsTypeOnly, name })),
|
||||
namespaceLikeImport,
|
||||
compilerOptions,
|
||||
preferences,
|
||||
);
|
||||
newDeclarations = combine(newDeclarations, declarations);
|
||||
});
|
||||
@@ -1348,6 +1349,7 @@ function codeActionForFixWorker(
|
||||
namedImports,
|
||||
namespaceLikeImport,
|
||||
program.getCompilerOptions(),
|
||||
preferences,
|
||||
),
|
||||
/*blankLineBetween*/ true,
|
||||
preferences,
|
||||
@@ -1505,7 +1507,7 @@ function doAddExistingFix(
|
||||
const newSpecifiers = stableSort(
|
||||
namedImports.map(namedImport =>
|
||||
factory.createImportSpecifier(
|
||||
(!clause.isTypeOnly || promoteFromTypeOnly) && needsTypeOnly(namedImport),
|
||||
(!clause.isTypeOnly || promoteFromTypeOnly) && shouldUseTypeOnly(namedImport, preferences),
|
||||
/*propertyName*/ undefined,
|
||||
factory.createIdentifier(namedImport.name),
|
||||
)
|
||||
@@ -1604,6 +1606,10 @@ function needsTypeOnly({ addAsTypeOnly }: { addAsTypeOnly: AddAsTypeOnly; }): bo
|
||||
return addAsTypeOnly === AddAsTypeOnly.Required;
|
||||
}
|
||||
|
||||
function shouldUseTypeOnly(info: { addAsTypeOnly: AddAsTypeOnly; }, preferences: UserPreferences): boolean {
|
||||
return needsTypeOnly(info) || !!preferences.preferTypeOnlyAutoImports && info.addAsTypeOnly !== AddAsTypeOnly.NotAllowed;
|
||||
}
|
||||
|
||||
function getNewImports(
|
||||
moduleSpecifier: string,
|
||||
quotePreference: QuotePreference,
|
||||
@@ -1611,6 +1617,7 @@ function getNewImports(
|
||||
namedImports: readonly Import[] | undefined,
|
||||
namespaceLikeImport: Import & { importKind: ImportKind.CommonJS | ImportKind.Namespace; } | undefined,
|
||||
compilerOptions: CompilerOptions,
|
||||
preferences: UserPreferences,
|
||||
): AnyImportSyntax | readonly AnyImportSyntax[] {
|
||||
const quotedModuleSpecifier = makeStringLiteral(moduleSpecifier, quotePreference);
|
||||
let statements: AnyImportSyntax | readonly AnyImportSyntax[] | undefined;
|
||||
@@ -1618,18 +1625,18 @@ function getNewImports(
|
||||
// `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 &&
|
||||
(compilerOptions.verbatimModuleSyntax || preferences.preferTypeOnlyAutoImports) &&
|
||||
defaultImport?.addAsTypeOnly !== AddAsTypeOnly.NotAllowed &&
|
||||
!some(namedImports, i => i.addAsTypeOnly === AddAsTypeOnly.NotAllowed);
|
||||
statements = combine(
|
||||
statements,
|
||||
makeImport(
|
||||
defaultImport && factory.createIdentifier(defaultImport.name),
|
||||
namedImports?.map(({ addAsTypeOnly, name }) =>
|
||||
namedImports?.map(namedImport =>
|
||||
factory.createImportSpecifier(
|
||||
!topLevelTypeOnly && addAsTypeOnly === AddAsTypeOnly.Required,
|
||||
!topLevelTypeOnly && shouldUseTypeOnly(namedImport, preferences),
|
||||
/*propertyName*/ undefined,
|
||||
factory.createIdentifier(name),
|
||||
factory.createIdentifier(namedImport.name),
|
||||
)
|
||||
),
|
||||
moduleSpecifier,
|
||||
@@ -1643,14 +1650,14 @@ function getNewImports(
|
||||
const declaration = namespaceLikeImport.importKind === ImportKind.CommonJS
|
||||
? factory.createImportEqualsDeclaration(
|
||||
/*modifiers*/ undefined,
|
||||
needsTypeOnly(namespaceLikeImport),
|
||||
shouldUseTypeOnly(namespaceLikeImport, preferences),
|
||||
factory.createIdentifier(namespaceLikeImport.name),
|
||||
factory.createExternalModuleReference(quotedModuleSpecifier),
|
||||
)
|
||||
: factory.createImportDeclaration(
|
||||
/*modifiers*/ undefined,
|
||||
factory.createImportClause(
|
||||
needsTypeOnly(namespaceLikeImport),
|
||||
shouldUseTypeOnly(namespaceLikeImport, preferences),
|
||||
/*name*/ undefined,
|
||||
factory.createNamespaceImport(factory.createIdentifier(namespaceLikeImport.name)),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user