diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index aaa2df431f2d1..f17e73337983e 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -902,6 +902,12 @@ export function tryGetAutoImportableReferenceFromTypeNode(importTypeNode: TypeNo if (isLiteralImportTypeNode(node) && node.qualifier) { // Symbol for the left-most thing after the dot const firstIdentifier = getFirstIdentifier(node.qualifier); + if (!firstIdentifier.symbol) { + // if symbol is missing then this doesn't come from a synthesized import type node + // it has to be an import type node authored by the user and thus it has to be valid + // it can't refer to reserved internal symbol names and such + return visitEachChild(node, visit, /*context*/ undefined); + } const name = getNameForExportedSymbol(firstIdentifier.symbol, scriptTarget); const qualifier = name !== firstIdentifier.text ? replaceFirstIdentifierOfEntityName(node.qualifier, factory.createIdentifier(name)) diff --git a/tests/cases/fourslash/completionsClassMemberImportTypeNodeParameter1.ts b/tests/cases/fourslash/completionsClassMemberImportTypeNodeParameter1.ts new file mode 100644 index 0000000000000..65ee02dcf8dcb --- /dev/null +++ b/tests/cases/fourslash/completionsClassMemberImportTypeNodeParameter1.ts @@ -0,0 +1,34 @@ +/// + +// @module: nodenext + +// @Filename: /generation.d.ts +//// export type GenerationConfigType = { max_length?: number }; + +// @FileName: /index.d.ts +//// export declare class PreTrainedModel { +//// _get_generation_config( +//// param: import("./generation.js").GenerationConfigType, +//// ): import("./generation.js").GenerationConfigType; +//// } +//// +//// export declare class BlenderbotSmallPreTrainedModel extends PreTrainedModel { +//// /*1*/ +//// } + +verify.completions({ + marker: "1", + includes: [ + { + name: "_get_generation_config", + insertText: `_get_generation_config(param: import("./generation.js").GenerationConfigType): import("./generation.js").GenerationConfigType;`, + filterText: "_get_generation_config", + hasAction: undefined, + }, + ], + preferences: { + includeCompletionsWithClassMemberSnippets: true, + includeCompletionsWithInsertText: true, + }, + isNewIdentifierLocation: true, +}); diff --git a/tests/cases/fourslash/completionsClassMemberImportTypeNodeParameter2.ts b/tests/cases/fourslash/completionsClassMemberImportTypeNodeParameter2.ts new file mode 100644 index 0000000000000..764075a757be3 --- /dev/null +++ b/tests/cases/fourslash/completionsClassMemberImportTypeNodeParameter2.ts @@ -0,0 +1,31 @@ +/// + +// @module: nodenext + +// @FileName: /index.d.ts +//// export declare class Cls { +//// method( +//// param: import("./doesntexist.js").Foo, +//// ): import("./doesntexist.js").Foo; +//// } +//// +//// export declare class Derived extends Cls { +//// /*1*/ +//// } + +verify.completions({ + marker: "1", + includes: [ + { + name: "method", + insertText: `method(param: import("./doesntexist.js").Foo);`, + filterText: "method", + hasAction: undefined, + }, + ], + preferences: { + includeCompletionsWithClassMemberSnippets: true, + includeCompletionsWithInsertText: true, + }, + isNewIdentifierLocation: true, +}); diff --git a/tests/cases/fourslash/completionsClassMemberImportTypeNodeParameter3.ts b/tests/cases/fourslash/completionsClassMemberImportTypeNodeParameter3.ts new file mode 100644 index 0000000000000..5edb4d7478e8b --- /dev/null +++ b/tests/cases/fourslash/completionsClassMemberImportTypeNodeParameter3.ts @@ -0,0 +1,37 @@ +/// + +// @module: nodenext + +// @FileName: /other/foo.d.ts +//// export declare type Bar = { baz: string }; + +// @FileName: /other/cls.d.ts +//// export declare class Cls { +//// method( +//// param: import("./foo.js").Bar, +//// ): import("./foo.js").Bar; +//// } + +// @FileName: /index.d.ts +//// import { Cls } from "./other/cls.js"; +//// +//// export declare class Derived extends Cls { +//// /*1*/ +//// } + +verify.completions({ + marker: "1", + includes: [ + { + name: "method", + insertText: `method(param: import("./other/foo.js").Bar): import("./other/foo.js").Bar;`, + filterText: "method", + hasAction: undefined, + }, + ], + preferences: { + includeCompletionsWithClassMemberSnippets: true, + includeCompletionsWithInsertText: true, + }, + isNewIdentifierLocation: true, +}); diff --git a/tests/cases/fourslash/completionsClassMemberImportTypeNodeParameter4.ts b/tests/cases/fourslash/completionsClassMemberImportTypeNodeParameter4.ts new file mode 100644 index 0000000000000..072725ac2f745 --- /dev/null +++ b/tests/cases/fourslash/completionsClassMemberImportTypeNodeParameter4.ts @@ -0,0 +1,34 @@ +/// + +// @module: nodenext + +// @FileName: /other/cls.d.ts +//// export declare class Cls { +//// method( +//// param: import("./doesntexist.js").Foo, +//// ): import("./doesntexist.js").Foo; +//// } + +// @FileName: /index.d.ts +//// import { Cls } from "./other/cls.js"; +//// +//// export declare class Derived extends Cls { +//// /*1*/ +//// } + +verify.completions({ + marker: "1", + includes: [ + { + name: "method", + insertText: `method(param: import("./doesntexist.js").Foo);`, + filterText: "method", + hasAction: undefined, + }, + ], + preferences: { + includeCompletionsWithClassMemberSnippets: true, + includeCompletionsWithInsertText: true, + }, + isNewIdentifierLocation: true, +});