diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3499cedab45..fc0620db865 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1879,12 +1879,7 @@ namespace ts { } function checkSymbolUsageInExpressionContext(symbol: Symbol, name: __String, useSite: Node) { - if ( - !(useSite.flags & NodeFlags.Ambient) && - !isPartOfTypeQuery(useSite) && - !isPartOfPossiblyValidTypeOrAbstractComputedPropertyName(useSite) && - isExpressionNode(useSite) - ) { + if (!isValidTypeOnlyAliasUseSite(useSite)) { const typeOnlyDeclaration = getTypeOnlyAliasDeclaration(symbol); if (typeOnlyDeclaration) { const message = typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 9d8db0927a1..a0cac0d3753 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -6134,4 +6134,11 @@ namespace ts { export function pseudoBigIntToString({negative, base10Value}: PseudoBigInt): string { return (negative && base10Value !== "0" ? "-" : "") + base10Value; } + + export function isValidTypeOnlyAliasUseSite(useSite: Node): boolean { + return !!(useSite.flags & NodeFlags.Ambient) + || isPartOfTypeQuery(useSite) + || isPartOfPossiblyValidTypeOrAbstractComputedPropertyName(useSite) + || !isExpressionNode(useSite); + } } diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 557362fb4b8..ca3b6744b27 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -30,8 +30,8 @@ namespace ts.codefix { const addToNamespace: FixUseNamespaceImport[] = []; const importType: FixUseImportType[] = []; // Keys are import clause node IDs. - const addToExisting = createMap<{ readonly importClause: ImportClause, defaultImport: string | undefined; readonly namedImports: string[] }>(); - const newImports = createNewImportMap(); + const addToExisting = createMap<{ readonly importClause: ImportClause, defaultImport: string | undefined; readonly namedImports: string[], canUseTypeOnlyImport: boolean }>(); + const newImports = createMap>(); eachDiagnostic(context, errorCodes, diag => { const info = getFixesInfo(context, diag.code, diag.start); @@ -47,11 +47,11 @@ namespace ts.codefix { importType.push(fix); break; case ImportFixKind.AddToExisting: { - const { importClause, importKind } = fix; + const { importClause, importKind, canUseTypeOnlyImport } = fix; const key = String(getNodeId(importClause)); let entry = addToExisting.get(key); if (!entry) { - addToExisting.set(key, entry = { importClause, defaultImport: undefined, namedImports: [] }); + addToExisting.set(key, entry = { importClause, defaultImport: undefined, namedImports: [], canUseTypeOnlyImport }); } if (importKind === ImportKind.Named) { pushIfUnique(entry.namedImports, symbolName); @@ -63,10 +63,10 @@ namespace ts.codefix { break; } case ImportFixKind.AddNew: { - const { moduleSpecifier, importKind, typeOnly } = fix; - let entry = newImports.get(moduleSpecifier, typeOnly); + const { moduleSpecifier, importKind } = fix; + let entry = newImports.get(moduleSpecifier); if (!entry) { - newImports.set(moduleSpecifier, typeOnly, entry = { defaultImport: undefined, namedImports: [], namespaceLikeImport: undefined }); + newImports.set(moduleSpecifier, entry = { defaultImport: undefined, namedImports: [], namespaceLikeImport: undefined }); } switch (importKind) { case ImportKind.Default: @@ -97,41 +97,16 @@ namespace ts.codefix { for (const fix of importType) { addImportType(changes, sourceFile, fix, quotePreference); } - addToExisting.forEach(({ importClause, defaultImport, namedImports }) => { - doAddExistingFix(changes, sourceFile, importClause, defaultImport, namedImports); + addToExisting.forEach(({ importClause, defaultImport, namedImports, canUseTypeOnlyImport }) => { + doAddExistingFix(changes, sourceFile, importClause, defaultImport, namedImports, canUseTypeOnlyImport); }); - newImports.forEach((imports, moduleSpecifier, typeOnly) => { - addNewImports(changes, sourceFile, typeOnly, moduleSpecifier, quotePreference, imports); + newImports.forEach((imports, moduleSpecifier) => { + addNewImports(changes, sourceFile, moduleSpecifier, quotePreference, imports); }); })); }, }); - function createNewImportMap() { - // Keys are module specifiers. - const newImports = createMap>(); - return { - get: (moduleSpecifier: string, typeOnly: boolean) => { - return newImports.get(key(moduleSpecifier, typeOnly)); - }, - set: (moduleSpecifier: string, typeOnly: boolean, value: ImportsCollection) => { - return newImports.set(key(moduleSpecifier, typeOnly), value); - }, - forEach: (action: (value: ImportsCollection, moduleSpecifier: string, typeOnly: boolean) => void) => { - newImports.forEach((value, key) => { - const typeOnly = !!+key[0]; - const moduleSpecifier = key.slice(1); - action(value, moduleSpecifier, typeOnly); - }); - }, - }; - - function key(moduleSpecifier: string, typeOnly: boolean) { - const prefix = typeOnly ? "1" : "0"; - return prefix + moduleSpecifier; - } - } - // Sorted with the preferred fix coming first. const enum ImportFixKind { UseNamespace, ImportType, AddToExisting, AddNew } type ImportFix = FixUseNamespaceImport | FixUseImportType | FixAddToExistingImport | FixAddNewImport; @@ -149,12 +124,12 @@ namespace ts.codefix { readonly kind: ImportFixKind.AddToExisting; readonly importClause: ImportClause; readonly importKind: ImportKind.Default | ImportKind.Named; + readonly canUseTypeOnlyImport: boolean; } interface FixAddNewImport { readonly kind: ImportFixKind.AddNew; readonly moduleSpecifier: string; readonly importKind: ImportKind; - readonly typeOnly: boolean; } const enum ImportKind { @@ -177,7 +152,6 @@ namespace ts.codefix { interface FixAddToExistingImportInfo { readonly declaration: AnyImportSyntax; readonly importKind: ImportKind; - readonly exportedSymbolIsTypeOnly: boolean; } export function getImportCompletionAction( @@ -229,9 +203,14 @@ namespace ts.codefix { return !(skipAlias(s, checker).flags & SymbolFlags.Value); } + function isTypeOnlyPosition(sourceFile: SourceFile, position: number) { + return isValidTypeOnlyAliasUseSite(getTokenAtPosition(sourceFile, position)); + } + function getFixForImport( exportInfos: readonly SymbolExportInfo[], symbolName: string, + /** undefined only for missing JSX namespace */ position: number | undefined, program: Program, sourceFile: SourceFile, @@ -241,7 +220,7 @@ namespace ts.codefix { const checker = program.getTypeChecker(); const existingImports = flatMap(exportInfos, info => getExistingImportDeclarations(info, checker, sourceFile)); const useNamespace = position === undefined ? undefined : tryUseExistingNamespaceImport(existingImports, symbolName, position, checker); - const addToExisting = tryAddToExistingImport(existingImports); + const addToExisting = tryAddToExistingImport(existingImports, position !== undefined && isTypeOnlyPosition(sourceFile, position)); // Don't bother providing an action to add a new import if we can add to an existing one. const addImport = addToExisting ? [addToExisting] : getFixesForAddImport(exportInfos, existingImports, program, sourceFile, position, host, preferences); return [...(useNamespace ? [useNamespace] : emptyArray), ...addImport]; @@ -271,14 +250,14 @@ namespace ts.codefix { }); } - function tryAddToExistingImport(existingImports: readonly FixAddToExistingImportInfo[]): FixAddToExistingImport | undefined { + function tryAddToExistingImport(existingImports: readonly FixAddToExistingImportInfo[], canUseTypeOnlyImport: boolean): FixAddToExistingImport | undefined { return firstDefined(existingImports, ({ declaration, importKind }): FixAddToExistingImport | undefined => { if (declaration.kind !== SyntaxKind.ImportDeclaration) return undefined; const { importClause } = declaration; if (!importClause) return undefined; const { name, namedBindings } = importClause; return importKind === ImportKind.Default && !name || importKind === ImportKind.Named && (!namedBindings || namedBindings.kind === SyntaxKind.NamedImports) - ? { kind: ImportFixKind.AddToExisting, importClause, importKind } + ? { kind: ImportFixKind.AddToExisting, importClause, importKind, canUseTypeOnlyImport } : undefined; }); } @@ -312,13 +291,14 @@ namespace ts.codefix { ): readonly (FixAddNewImport | FixUseImportType)[] { const isJs = isSourceFileJS(sourceFile); const { allowsImportingSpecifier } = createAutoImportFilter(sourceFile, program, host); + const choicesForEachExportingModule = flatMap(moduleSymbols, ({ moduleSymbol, importKind, exportedSymbolIsTypeOnly }) => moduleSpecifiers.getModuleSpecifiers(moduleSymbol, program.getCompilerOptions(), sourceFile, host, program.getSourceFiles(), preferences, program.redirectTargetsMap) .map((moduleSpecifier): FixAddNewImport | FixUseImportType => // `position` should only be undefined at a missing jsx namespace, in which case we shouldn't be looking for pure types. exportedSymbolIsTypeOnly && isJs ? { kind: ImportFixKind.ImportType, moduleSpecifier, position: Debug.assertDefined(position, "position should be defined") } - : { kind: ImportFixKind.AddNew, moduleSpecifier, importKind, typeOnly: exportedSymbolIsTypeOnly })); + : { kind: ImportFixKind.AddNew, moduleSpecifier, importKind })); // Sort by presence in package.json, then shortest paths first return sort(choicesForEachExportingModule, (a, b) => { @@ -347,14 +327,14 @@ namespace ts.codefix { return existingDeclaration ? [existingDeclaration] : getNewImportInfos(program, sourceFile, position, exportInfos, host, preferences); } - function newImportInfoFromExistingSpecifier({ declaration, importKind, exportedSymbolIsTypeOnly }: FixAddToExistingImportInfo): FixAddNewImport | undefined { + function newImportInfoFromExistingSpecifier({ declaration, importKind }: FixAddToExistingImportInfo): FixAddNewImport | undefined { const expression = declaration.kind === SyntaxKind.ImportDeclaration ? declaration.moduleSpecifier : declaration.moduleReference.kind === SyntaxKind.ExternalModuleReference ? declaration.moduleReference.expression : undefined; return expression && isStringLiteral(expression) - ? { kind: ImportFixKind.AddNew, moduleSpecifier: expression.text, importKind, typeOnly: exportedSymbolIsTypeOnly } + ? { kind: ImportFixKind.AddNew, moduleSpecifier: expression.text, importKind } : undefined; } @@ -554,14 +534,14 @@ namespace ts.codefix { addImportType(changes, sourceFile, fix, quotePreference); return [Diagnostics.Change_0_to_1, symbolName, getImportTypePrefix(fix.moduleSpecifier, quotePreference) + symbolName]; case ImportFixKind.AddToExisting: { - const { importClause, importKind } = fix; - doAddExistingFix(changes, sourceFile, importClause, importKind === ImportKind.Default ? symbolName : undefined, importKind === ImportKind.Named ? [symbolName] : emptyArray); + const { importClause, importKind, canUseTypeOnlyImport } = fix; + doAddExistingFix(changes, sourceFile, importClause, importKind === ImportKind.Default ? symbolName : undefined, importKind === ImportKind.Named ? [symbolName] : emptyArray, canUseTypeOnlyImport); const moduleSpecifierWithoutQuotes = stripQuotes(importClause.parent.moduleSpecifier.getText()); return [importKind === ImportKind.Default ? Diagnostics.Add_default_import_0_to_existing_import_declaration_from_1 : Diagnostics.Add_0_to_existing_import_declaration_from_1, symbolName, moduleSpecifierWithoutQuotes]; // you too! } case ImportFixKind.AddNew: { const { importKind, moduleSpecifier } = fix; - addNewImports(changes, sourceFile, fix.typeOnly, moduleSpecifier, quotePreference, importKind === ImportKind.Default ? { defaultImport: symbolName, namedImports: emptyArray, namespaceLikeImport: undefined } + addNewImports(changes, sourceFile, moduleSpecifier, quotePreference, importKind === ImportKind.Default ? { defaultImport: symbolName, namedImports: emptyArray, namespaceLikeImport: undefined } : importKind === ImportKind.Named ? { defaultImport: undefined, namedImports: [symbolName], namespaceLikeImport: undefined } : { defaultImport: undefined, namedImports: emptyArray, namespaceLikeImport: { importKind, name: symbolName } }); return [importKind === ImportKind.Default ? Diagnostics.Import_default_0_from_module_1 : Diagnostics.Import_0_from_module_1, symbolName, moduleSpecifier]; @@ -571,9 +551,10 @@ namespace ts.codefix { } } - function doAddExistingFix(changes: textChanges.ChangeTracker, sourceFile: SourceFile, clause: ImportClause, defaultImport: string | undefined, namedImports: readonly string[]): void { + function doAddExistingFix(changes: textChanges.ChangeTracker, sourceFile: SourceFile, clause: ImportClause, defaultImport: string | undefined, namedImports: readonly string[], canUseTypeOnlyImport: boolean): void { + const convertTypeOnlyToRegular = !canUseTypeOnlyImport && clause.isTypeOnly; if (defaultImport) { - Debug.assert(!clause.name, "Default imports can't have names"); + Debug.assert(!clause.name, "Cannot add a default import to an import clause that already has one"); changes.insertNodeAt(sourceFile, clause.getStart(sourceFile), createIdentifier(defaultImport), { suffix: ", " }); } @@ -591,11 +572,15 @@ namespace ts.codefix { changes.replaceNode(sourceFile, clause.namedBindings, namedImports); } else { - changes.insertNodeAfter(sourceFile, Debug.assertDefined(clause.name, "Named import specifiers must have names"), namedImports); + changes.insertNodeAfter(sourceFile, Debug.assertDefined(clause.name, "Import clause must have either named imports or a default import"), namedImports); } } } } + + if (convertTypeOnlyToRegular) { + changes.delete(sourceFile, getTypeKeywordOfTypeOnlyImport(clause, sourceFile)); + } } function addNamespaceQualifier(changes: textChanges.ChangeTracker, sourceFile: SourceFile, { namespacePrefix, position }: FixUseNamespaceImport): void { @@ -619,13 +604,13 @@ namespace ts.codefix { readonly name: string; } | undefined; } - function addNewImports(changes: textChanges.ChangeTracker, sourceFile: SourceFile, typeOnly: boolean, moduleSpecifier: string, quotePreference: QuotePreference, { defaultImport, namedImports, namespaceLikeImport }: ImportsCollection): void { + function addNewImports(changes: textChanges.ChangeTracker, sourceFile: SourceFile, moduleSpecifier: string, quotePreference: QuotePreference, { defaultImport, namedImports, namespaceLikeImport }: ImportsCollection): void { const quotedModuleSpecifier = makeStringLiteral(moduleSpecifier, quotePreference); if (defaultImport !== undefined || namedImports.length) { insertImport(changes, sourceFile, makeImport( defaultImport === undefined ? undefined : createIdentifier(defaultImport), - namedImports.map(n => createImportSpecifier(/*propertyName*/ undefined, createIdentifier(n))), moduleSpecifier, quotePreference, typeOnly)); + namedImports.map(n => createImportSpecifier(/*propertyName*/ undefined, createIdentifier(n))), moduleSpecifier, quotePreference)); } if (namespaceLikeImport) { insertImport( @@ -633,7 +618,7 @@ namespace ts.codefix { sourceFile, namespaceLikeImport.importKind === ImportKind.Equals ? createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createIdentifier(namespaceLikeImport.name), createExternalModuleReference(quotedModuleSpecifier)) : namespaceLikeImport.importKind === ImportKind.ConstEquals ? createConstEqualsRequireDeclaration(namespaceLikeImport.name, quotedModuleSpecifier) : - createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createImportClause(/*name*/ undefined, createNamespaceImport(createIdentifier(namespaceLikeImport.name)), typeOnly), quotedModuleSpecifier)); + createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createImportClause(/*name*/ undefined, createNamespaceImport(createIdentifier(namespaceLikeImport.name))), quotedModuleSpecifier)); } } diff --git a/src/services/completions.ts b/src/services/completions.ts index 181128fbaf4..8b8f1d1e140 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -525,6 +525,7 @@ namespace ts.Completions { symbolToOriginInfoMap: SymbolOriginInfoMap; previousToken: Node | undefined; readonly isJsxInitializer: IsJsxInitializer; + readonly isTypeOnlyLocation: boolean; } function getSymbolCompletionFromEntryId( program: Program, @@ -543,7 +544,7 @@ namespace ts.Completions { return { type: "request", request: completionData }; } - const { symbols, literals, location, completionKind, symbolToOriginInfoMap, previousToken, isJsxInitializer } = completionData; + const { symbols, literals, location, completionKind, symbolToOriginInfoMap, previousToken, isJsxInitializer, isTypeOnlyLocation } = completionData; const literal = find(literals, l => completionNameForLiteral(l) === entryId.name); if (literal !== undefined) return { type: "literal", literal }; @@ -556,7 +557,7 @@ namespace ts.Completions { const origin = symbolToOriginInfoMap[getSymbolId(symbol)]; const info = getCompletionEntryDisplayNameForSymbol(symbol, compilerOptions.target!, origin, completionKind); return info && info.name === entryId.name && getSourceFromOrigin(origin) === entryId.source - ? { type: "symbol" as const, symbol, location, symbolToOriginInfoMap, previousToken, isJsxInitializer } + ? { type: "symbol" as const, symbol, location, symbolToOriginInfoMap, previousToken, isJsxInitializer, isTypeOnlyLocation } : undefined; }) || { type: "none" }; } @@ -714,6 +715,7 @@ namespace ts.Completions { readonly isJsxInitializer: IsJsxInitializer; readonly insideJsDocTagTypeExpression: boolean; readonly symbolToSortTextMap: SymbolSortTextMap; + readonly isTypeOnlyLocation: boolean; } type Request = { readonly kind: CompletionDataKind.JsDocTagName | CompletionDataKind.JsDocTag } | { readonly kind: CompletionDataKind.JsDocParameterName, tag: JSDocParameterTag }; @@ -1012,6 +1014,7 @@ namespace ts.Completions { const symbolToOriginInfoMap: SymbolOriginInfoMap = []; const symbolToSortTextMap: SymbolSortTextMap = []; const importSuggestionsCache = host.getImportSuggestionsCache && host.getImportSuggestionsCache(); + const isTypeOnly = isTypeOnlyCompletion(); if (isRightOfDot || isRightOfQuestionDot) { getTypeScriptMemberSymbols(); @@ -1061,7 +1064,8 @@ namespace ts.Completions { previousToken, isJsxInitializer, insideJsDocTagTypeExpression, - symbolToSortTextMap + symbolToSortTextMap, + isTypeOnlyLocation: isTypeOnly }; type JSDocTagWithTypeExpression = JSDocParameterTag | JSDocPropertyTag | JSDocReturnTag | JSDocTypeTag | JSDocTypedefTag; @@ -1329,7 +1333,6 @@ namespace ts.Completions { const scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile; isInSnippetScope = isSnippetScope(scopeNode); - const isTypeOnly = isTypeOnlyCompletion(); const symbolMeanings = (isTypeOnly ? SymbolFlags.None : SymbolFlags.Value) | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias; symbols = Debug.assertEachDefined(typeChecker.getSymbolsInScope(scopeNode, symbolMeanings), "getSymbolsInScope() should all be defined"); diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 69010b4611f..3c6fc043096 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -1306,6 +1306,10 @@ namespace ts { return contains(typeKeywords, kind); } + export function isTypeKeywordToken(node: Node): node is Token { + return node.kind === SyntaxKind.TypeKeyword; + } + /** True if the symbol is for an external module, as opposed to a namespace. */ export function isExternalModuleSymbol(moduleSymbol: Symbol): boolean { return !!(moduleSymbol.flags & SymbolFlags.Module) && moduleSymbol.name.charCodeAt(0) === CharacterCodes.doubleQuote; @@ -1494,6 +1498,11 @@ namespace ts { } } + export function getTypeKeywordOfTypeOnlyImport(importClause: ImportClause, sourceFile: SourceFile): Token { + Debug.assert(importClause.isTypeOnly); + return cast(importClause.getChildAt(0, sourceFile), isTypeKeywordToken); + } + export function textSpansEqual(a: TextSpan | undefined, b: TextSpan | undefined): boolean { return !!a && !!b && a.start === b.start && a.length === b.length; } diff --git a/tests/cases/fourslash/codeFixInferFromUsageContextualImport2.ts b/tests/cases/fourslash/codeFixInferFromUsageContextualImport2.ts index 8b88015bcfd..f12f9dc9e80 100644 --- a/tests/cases/fourslash/codeFixInferFromUsageContextualImport2.ts +++ b/tests/cases/fourslash/codeFixInferFromUsageContextualImport2.ts @@ -20,7 +20,7 @@ goTo.file("/b.ts"); verify.codeFix({ description: "Infer parameter types from usage", newFileContent: -`import type { User } from "./a"; +`import { User } from "./a"; export function f(user: User) { getEmail(user); diff --git a/tests/cases/fourslash/completionsImport_exportEquals.ts b/tests/cases/fourslash/completionsImport_exportEquals.ts index 4a5d5fdd16d..7cd2e1cd2f4 100644 --- a/tests/cases/fourslash/completionsImport_exportEquals.ts +++ b/tests/cases/fourslash/completionsImport_exportEquals.ts @@ -43,7 +43,7 @@ verify.applyCodeActionFromCompletion("1", { source: "/a", description: `Import 'b' from module "./a"`, newFileContent: -`import type { b } from "./a"; +`import { b } from "./a"; a; let x: b;`, @@ -54,7 +54,7 @@ verify.applyCodeActionFromCompletion("0", { source: "/a", description: `Import 'a' from module "./a"`, newFileContent: -`import type { b } from "./a"; +`import { b } from "./a"; import a = require("./a"); a; diff --git a/tests/cases/fourslash/completionsImport_typeOnly.ts b/tests/cases/fourslash/completionsImport_typeOnly.ts new file mode 100644 index 00000000000..688afd52966 --- /dev/null +++ b/tests/cases/fourslash/completionsImport_typeOnly.ts @@ -0,0 +1,24 @@ +/// + +// @target: esnext + +// @Filename: /a.ts +//// export class A {} +//// export class B {} + +// @Filename: /b.ts +//// import type { A } from './a'; +//// const b: B/**/ + +goTo.file('/b.ts'); +verify.applyCodeActionFromCompletion('', { + name: 'B', + source: '/a', + description: `Add 'B' to existing import declaration from "./a"`, + preferences: { + includeCompletionsForModuleExports: true, + includeInsertTextCompletions: true + }, + newFileContent: `import type { A, B } from './a'; +const b: B` +}); diff --git a/tests/cases/fourslash/importNameCodeFixConvertTypeOnly1.ts b/tests/cases/fourslash/importNameCodeFixConvertTypeOnly1.ts new file mode 100644 index 00000000000..15f94e55093 --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFixConvertTypeOnly1.ts @@ -0,0 +1,13 @@ +/// + +// @Filename: /a.ts +//// export class A {} +//// export class B {} + +// @Filename: /b.ts +//// import type { A } from './a'; +//// new B + +goTo.file('/b.ts'); +verify.importFixAtPosition([`import { A, B } from './a'; +new B`]); diff --git a/tests/cases/fourslash/importNameCodeFixNewImportFile3.ts b/tests/cases/fourslash/importNameCodeFixNewImportFile3.ts index 30467e76549..af7901e03e6 100644 --- a/tests/cases/fourslash/importNameCodeFixNewImportFile3.ts +++ b/tests/cases/fourslash/importNameCodeFixNewImportFile3.ts @@ -9,7 +9,7 @@ //// } verify.importFixAtPosition([ -`import type { XXX } from "./module"; +`import { XXX } from "./module"; let t: XXX.I;` ]); \ No newline at end of file diff --git a/tests/cases/fourslash/importNameCodeFixNewImportFile4.ts b/tests/cases/fourslash/importNameCodeFixNewImportFile4.ts index 4d59eb28e52..62cf48c4977 100644 --- a/tests/cases/fourslash/importNameCodeFixNewImportFile4.ts +++ b/tests/cases/fourslash/importNameCodeFixNewImportFile4.ts @@ -10,7 +10,7 @@ //// } verify.importFixAtPosition([ -`import type { A } from "./module"; +`import { A } from "./module"; let t: A.B.I;` ]); \ No newline at end of file diff --git a/tests/cases/fourslash/importNameCodeFixNewImportTypeOnly.ts b/tests/cases/fourslash/importNameCodeFixNewImportTypeOnly.ts deleted file mode 100644 index 3b2b61bf7a5..00000000000 --- a/tests/cases/fourslash/importNameCodeFixNewImportTypeOnly.ts +++ /dev/null @@ -1,14 +0,0 @@ -/// - -// @target: esnext - -// @Filename: /a.ts -////export interface Car {} - -// @Filename: /b.ts -////function drive(car: /**/Car) {} - -goTo.file("/b.ts"); -verify.importFixAtPosition([`import type { Car } from "./a"; - -function drive(car: Car) {}`]); diff --git a/tests/cases/fourslash/importNameCodeFix_exportEquals.ts b/tests/cases/fourslash/importNameCodeFix_exportEquals.ts index 5dd9b9f100e..4ab87df7e76 100644 --- a/tests/cases/fourslash/importNameCodeFix_exportEquals.ts +++ b/tests/cases/fourslash/importNameCodeFix_exportEquals.ts @@ -16,9 +16,9 @@ verify.codeFixAll({ fixId: "fixMissingImport", fixAllDescription: "Add all missing imports", newFileContent: -`import a = require("./a"); +`import { b } from "./a"; -import type { b } from "./a"; +import a = require("./a"); a; let x: b;`,