diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7f18bbc1a1dec..5b7a17333f335 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6207,6 +6207,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const context = syntacticContext as NodeBuilderContext; if (context.bundled || context.enclosingFile !== getSourceFileOfNode(lit)) { let name = lit.text; + const originalName = name; const nodeSymbol = getNodeLinks(parent).resolvedSymbol; const meaning = parent.isTypeOf ? SymbolFlags.Value : SymbolFlags.Type; const parentSymbol = nodeSymbol @@ -6227,7 +6228,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { context.tracker.reportLikelyUnsafeImportRequiredError(name); } } - return name; + if (name !== originalName) { + return name; + } } }, canReuseTypeNode(context, typeNode) { @@ -8831,10 +8834,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return setTextRange(context, setEmitFlags(name, EmitFlags.NoAsciiEscaping), node); } const updated = visitEachChildWorker(node, c => attachSymbolToLeftmostIdentifier(c), /*context*/ undefined); - if (updated !== node) { - setTextRange(context, updated, node); - } - return updated; + return setTextRange(context, updated, node); } } diff --git a/src/compiler/expressionToTypeNode.ts b/src/compiler/expressionToTypeNode.ts index ad4f8321066e9..7ef64ad6375b5 100644 --- a/src/compiler/expressionToTypeNode.ts +++ b/src/compiler/expressionToTypeNode.ts @@ -435,9 +435,11 @@ export function createSyntacticTypeNodeBuilder( if (!resolver.canReuseTypeNode(context, node)) { return resolver.serializeExistingTypeNode(context, node); } + const specifier = rewriteModuleSpecifier(node, node.argument.literal); + const literal = specifier === node.argument.literal ? reuseNode(context, node.argument.literal) : specifier; return factory.updateImportTypeNode( node, - factory.updateLiteralTypeNode(node.argument, rewriteModuleSpecifier(node, node.argument.literal)), + literal === node.argument.literal ? reuseNode(context, node.argument) : factory.createLiteralTypeNode(literal), visitNode(node.attributes, visitExistingNodeTreeSymbols, isImportAttributes), visitNode(node.qualifier, visitExistingNodeTreeSymbols, isEntityName), visitNodes(node.typeArguments, visitExistingNodeTreeSymbols, isTypeNode), @@ -612,10 +614,7 @@ export function createSyntacticTypeNodeBuilder( function rewriteModuleSpecifier(parent: ImportTypeNode, lit: StringLiteral) { const newName = resolver.getModuleSpecifierOverride(context, parent, lit); - if (newName) { - return setOriginalNode(factory.createStringLiteral(newName), lit); - } - return visitNode(lit, visitExistingNodeTreeSymbols, isStringLiteral)!; + return newName ? setOriginalNode(factory.createStringLiteral(newName), lit) : lit; } } } diff --git a/tests/baselines/reference/declarationEmitNoInvalidCommentReuse1.js b/tests/baselines/reference/declarationEmitNoInvalidCommentReuse1.js new file mode 100644 index 0000000000000..44b3fcf5b9cb5 --- /dev/null +++ b/tests/baselines/reference/declarationEmitNoInvalidCommentReuse1.js @@ -0,0 +1,29 @@ +//// [tests/cases/compiler/declarationEmitNoInvalidCommentReuse1.ts] //// + +//// [a.ts] +import { object } from "./obj"; + +export const _ = object; + +/////////// +/** + * huh + */ +//// [obj.d.ts] +export declare const object: import("./id").Id<{ + foo: import("./id" ).Id<{}>; +}>; + +//// [id.d.ts] +export type Id = T; + + + + +//// [a.d.ts] +export declare const _: { + foo: import("./id").Id<{}>; +}; +/** + * huh + */ diff --git a/tests/baselines/reference/declarationEmitNoInvalidCommentReuse1.symbols b/tests/baselines/reference/declarationEmitNoInvalidCommentReuse1.symbols new file mode 100644 index 0000000000000..c2bfa642baaea --- /dev/null +++ b/tests/baselines/reference/declarationEmitNoInvalidCommentReuse1.symbols @@ -0,0 +1,31 @@ +//// [tests/cases/compiler/declarationEmitNoInvalidCommentReuse1.ts] //// + +=== a.ts === +import { object } from "./obj"; +>object : Symbol(object, Decl(a.ts, 0, 8)) + +export const _ = object; +>_ : Symbol(_, Decl(a.ts, 2, 12)) +>object : Symbol(object, Decl(a.ts, 0, 8)) + +/////////// +/** + * huh + */ +=== obj.d.ts === +export declare const object: import("./id").Id<{ +>object : Symbol(object, Decl(obj.d.ts, 0, 20)) +>Id : Symbol(Id, Decl(id.d.ts, 0, 0)) + + foo: import("./id" ).Id<{}>; +>foo : Symbol(foo, Decl(obj.d.ts, 0, 48)) +>Id : Symbol(Id, Decl(id.d.ts, 0, 0)) + +}>; + +=== id.d.ts === +export type Id = T; +>Id : Symbol(Id, Decl(id.d.ts, 0, 0)) +>T : Symbol(T, Decl(id.d.ts, 0, 15)) +>T : Symbol(T, Decl(id.d.ts, 0, 15)) + diff --git a/tests/baselines/reference/declarationEmitNoInvalidCommentReuse1.types b/tests/baselines/reference/declarationEmitNoInvalidCommentReuse1.types new file mode 100644 index 0000000000000..baf3e35b7bdac --- /dev/null +++ b/tests/baselines/reference/declarationEmitNoInvalidCommentReuse1.types @@ -0,0 +1,33 @@ +//// [tests/cases/compiler/declarationEmitNoInvalidCommentReuse1.ts] //// + +=== a.ts === +import { object } from "./obj"; +>object : { foo: import("id").Id<{}>; } +> : ^^^^^^^ ^^^ + +export const _ = object; +>_ : { foo: import("id").Id<{}>; } +> : ^^^^^^^ ^^^ +>object : { foo: import("id").Id<{}>; } +> : ^^^^^^^ ^^^ + +/////////// +/** + * huh + */ +=== obj.d.ts === +export declare const object: import("./id").Id<{ +>object : { foo: import("./id").Id<{}>; } +> : ^^^^^^^ ^^^ + + foo: import("./id" ).Id<{}>; +>foo : {} +> : ^^ + +}>; + +=== id.d.ts === +export type Id = T; +>Id : T +> : ^ + diff --git a/tests/baselines/reference/declarationEmitNoInvalidCommentReuse2.js b/tests/baselines/reference/declarationEmitNoInvalidCommentReuse2.js new file mode 100644 index 0000000000000..d770d4ef4e6ef --- /dev/null +++ b/tests/baselines/reference/declarationEmitNoInvalidCommentReuse2.js @@ -0,0 +1,29 @@ +//// [tests/cases/compiler/declarationEmitNoInvalidCommentReuse2.ts] //// + +//// [a.ts] +import { object } from "./obj.ts"; + +export const _ = object; + +/////////// +/** + * huh + */ +//// [obj.d.ts] +export declare const object: import("./id.ts").Id<{ + foo: import("./id.ts" ).Id<{}>; +}>; + +//// [id.d.ts] +export type Id = T; + + + + +//// [a.d.ts] +export declare const _: { + foo: import("./id").Id<{}>; +}; +/** + * huh + */ diff --git a/tests/baselines/reference/declarationEmitNoInvalidCommentReuse2.symbols b/tests/baselines/reference/declarationEmitNoInvalidCommentReuse2.symbols new file mode 100644 index 0000000000000..c6080fe3b6c3e --- /dev/null +++ b/tests/baselines/reference/declarationEmitNoInvalidCommentReuse2.symbols @@ -0,0 +1,31 @@ +//// [tests/cases/compiler/declarationEmitNoInvalidCommentReuse2.ts] //// + +=== a.ts === +import { object } from "./obj.ts"; +>object : Symbol(object, Decl(a.ts, 0, 8)) + +export const _ = object; +>_ : Symbol(_, Decl(a.ts, 2, 12)) +>object : Symbol(object, Decl(a.ts, 0, 8)) + +/////////// +/** + * huh + */ +=== obj.d.ts === +export declare const object: import("./id.ts").Id<{ +>object : Symbol(object, Decl(obj.d.ts, 0, 20)) +>Id : Symbol(Id, Decl(id.d.ts, 0, 0)) + + foo: import("./id.ts" ).Id<{}>; +>foo : Symbol(foo, Decl(obj.d.ts, 0, 51)) +>Id : Symbol(Id, Decl(id.d.ts, 0, 0)) + +}>; + +=== id.d.ts === +export type Id = T; +>Id : Symbol(Id, Decl(id.d.ts, 0, 0)) +>T : Symbol(T, Decl(id.d.ts, 0, 15)) +>T : Symbol(T, Decl(id.d.ts, 0, 15)) + diff --git a/tests/baselines/reference/declarationEmitNoInvalidCommentReuse2.types b/tests/baselines/reference/declarationEmitNoInvalidCommentReuse2.types new file mode 100644 index 0000000000000..fcda0f29e487a --- /dev/null +++ b/tests/baselines/reference/declarationEmitNoInvalidCommentReuse2.types @@ -0,0 +1,33 @@ +//// [tests/cases/compiler/declarationEmitNoInvalidCommentReuse2.ts] //// + +=== a.ts === +import { object } from "./obj.ts"; +>object : { foo: import("id").Id<{}>; } +> : ^^^^^^^ ^^^ + +export const _ = object; +>_ : { foo: import("id").Id<{}>; } +> : ^^^^^^^ ^^^ +>object : { foo: import("id").Id<{}>; } +> : ^^^^^^^ ^^^ + +/////////// +/** + * huh + */ +=== obj.d.ts === +export declare const object: import("./id.ts").Id<{ +>object : { foo: import("./id.ts").Id<{}>; } +> : ^^^^^^^ ^^^ + + foo: import("./id.ts" ).Id<{}>; +>foo : {} +> : ^^ + +}>; + +=== id.d.ts === +export type Id = T; +>Id : T +> : ^ + diff --git a/tests/baselines/reference/declarationEmitNoInvalidCommentReuse3.js b/tests/baselines/reference/declarationEmitNoInvalidCommentReuse3.js new file mode 100644 index 0000000000000..c23f2cec44a2d --- /dev/null +++ b/tests/baselines/reference/declarationEmitNoInvalidCommentReuse3.js @@ -0,0 +1,29 @@ +//// [tests/cases/compiler/declarationEmitNoInvalidCommentReuse3.ts] //// + +//// [a.ts] +import { object } from "./obj"; +import { id } from "./id"; +export const _ = object; +/** +*/ +//// [obj.d.ts] +import { id } from "./id"; +// ---- +export declare const object: id.A<{ + foo: id.A<1> +}>; + +//// [id.d.ts] +export declare namespace id { + type A = T; +} + + + +//// [a.d.ts] +import { id } from "./id"; +export declare const _: { + foo: id.A<1>; +}; +/** +*/ diff --git a/tests/baselines/reference/declarationEmitNoInvalidCommentReuse3.symbols b/tests/baselines/reference/declarationEmitNoInvalidCommentReuse3.symbols new file mode 100644 index 0000000000000..a60ce81062338 --- /dev/null +++ b/tests/baselines/reference/declarationEmitNoInvalidCommentReuse3.symbols @@ -0,0 +1,41 @@ +//// [tests/cases/compiler/declarationEmitNoInvalidCommentReuse3.ts] //// + +=== a.ts === +import { object } from "./obj"; +>object : Symbol(object, Decl(a.ts, 0, 8)) + +import { id } from "./id"; +>id : Symbol(id, Decl(a.ts, 1, 8)) + +export const _ = object; +>_ : Symbol(_, Decl(a.ts, 2, 12)) +>object : Symbol(object, Decl(a.ts, 0, 8)) + +/** +*/ +=== obj.d.ts === +import { id } from "./id"; +>id : Symbol(id, Decl(obj.d.ts, 0, 8)) + +// ---- +export declare const object: id.A<{ +>object : Symbol(object, Decl(obj.d.ts, 2, 20)) +>id : Symbol(id, Decl(obj.d.ts, 0, 8)) +>A : Symbol(id.A, Decl(id.d.ts, 0, 29)) + + foo: id.A<1> +>foo : Symbol(foo, Decl(obj.d.ts, 2, 35)) +>id : Symbol(id, Decl(obj.d.ts, 0, 8)) +>A : Symbol(id.A, Decl(id.d.ts, 0, 29)) + +}>; + +=== id.d.ts === +export declare namespace id { +>id : Symbol(id, Decl(id.d.ts, 0, 0)) + + type A = T; +>A : Symbol(A, Decl(id.d.ts, 0, 29)) +>T : Symbol(T, Decl(id.d.ts, 1, 11)) +>T : Symbol(T, Decl(id.d.ts, 1, 11)) +} diff --git a/tests/baselines/reference/declarationEmitNoInvalidCommentReuse3.types b/tests/baselines/reference/declarationEmitNoInvalidCommentReuse3.types new file mode 100644 index 0000000000000..610009b9f1df6 --- /dev/null +++ b/tests/baselines/reference/declarationEmitNoInvalidCommentReuse3.types @@ -0,0 +1,45 @@ +//// [tests/cases/compiler/declarationEmitNoInvalidCommentReuse3.ts] //// + +=== a.ts === +import { object } from "./obj"; +>object : { foo: id.A<1>; } +> : ^^^^^^^ ^^^ + +import { id } from "./id"; +>id : any +> : ^^^ + +export const _ = object; +>_ : { foo: id.A<1>; } +> : ^^^^^^^ ^^^ +>object : { foo: id.A<1>; } +> : ^^^^^^^ ^^^ + +/** +*/ +=== obj.d.ts === +import { id } from "./id"; +>id : any +> : ^^^ + +// ---- +export declare const object: id.A<{ +>object : { foo: id.A<1>; } +> : ^^^^^^^ ^^^ +>id : any +> : ^^^ + + foo: id.A<1> +>foo : 1 +> : ^ +>id : any +> : ^^^ + +}>; + +=== id.d.ts === +export declare namespace id { + type A = T; +>A : T +> : ^ +} diff --git a/tests/cases/compiler/declarationEmitNoInvalidCommentReuse1.ts b/tests/cases/compiler/declarationEmitNoInvalidCommentReuse1.ts new file mode 100644 index 0000000000000..264faa6608d2e --- /dev/null +++ b/tests/cases/compiler/declarationEmitNoInvalidCommentReuse1.ts @@ -0,0 +1,22 @@ +// @strict: true +// @declaration: true +// @emitDeclarationOnly: true + +// https://github.com/microsoft/TypeScript/issues/61239 + +// @filename: a.ts +import { object } from "./obj"; + +export const _ = object; + +/////////// +/** + * huh + */ +// @filename: obj.d.ts +export declare const object: import("./id").Id<{ + foo: import("./id" ).Id<{}>; +}>; + +// @filename: id.d.ts +export type Id = T; diff --git a/tests/cases/compiler/declarationEmitNoInvalidCommentReuse2.ts b/tests/cases/compiler/declarationEmitNoInvalidCommentReuse2.ts new file mode 100644 index 0000000000000..af52f4aeef51e --- /dev/null +++ b/tests/cases/compiler/declarationEmitNoInvalidCommentReuse2.ts @@ -0,0 +1,21 @@ +// @strict: true +// @declaration: true +// @emitDeclarationOnly: true +// @rewriteRelativeImportExtensions: true + +// @filename: a.ts +import { object } from "./obj.ts"; + +export const _ = object; + +/////////// +/** + * huh + */ +// @filename: obj.d.ts +export declare const object: import("./id.ts").Id<{ + foo: import("./id.ts" ).Id<{}>; +}>; + +// @filename: id.d.ts +export type Id = T; diff --git a/tests/cases/compiler/declarationEmitNoInvalidCommentReuse3.ts b/tests/cases/compiler/declarationEmitNoInvalidCommentReuse3.ts new file mode 100644 index 0000000000000..e6a502734292f --- /dev/null +++ b/tests/cases/compiler/declarationEmitNoInvalidCommentReuse3.ts @@ -0,0 +1,21 @@ +// @strict: true +// @declaration: true +// @emitDeclarationOnly: true + +// @filename: a.ts +import { object } from "./obj"; +import { id } from "./id"; +export const _ = object; +/** +*/ +// @filename: obj.d.ts +import { id } from "./id"; +// ---- +export declare const object: id.A<{ + foo: id.A<1> +}>; + +// @filename: id.d.ts +export declare namespace id { + type A = T; +} \ No newline at end of file