diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts
index c3b8babf5f9..dfb366c6e24 100644
--- a/src/compiler/emitter.ts
+++ b/src/compiler/emitter.ts
@@ -2088,7 +2088,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
// SyntaxKind.TemplateMiddle
// SyntaxKind.TemplateTail
function emitLiteral(node: LiteralLikeNode, jsxAttributeEscape: boolean) {
- const text = getLiteralTextOfNode(node, printerOptions.neverAsciiEscape, jsxAttributeEscape);
+ const text = getLiteralTextOfNode(node, /*sourceFile*/ undefined, printerOptions.neverAsciiEscape, jsxAttributeEscape);
if (
(printerOptions.sourceMap || printerOptions.inlineSourceMap)
&& (node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind))
@@ -2641,7 +2641,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
expression = skipPartiallyEmittedExpressions(expression);
if (isNumericLiteral(expression)) {
// check if numeric literal is a decimal literal that was originally written with a dot
- const text = getLiteralTextOfNode(expression as LiteralExpression, /*neverAsciiEscape*/ true, /*jsxAttributeEscape*/ false);
+ const text = getLiteralTextOfNode(expression as LiteralExpression, /*sourceFile*/ undefined, /*neverAsciiEscape*/ true, /*jsxAttributeEscape*/ false);
// If the number will be printed verbatim and it doesn't already contain a dot or an exponent indicator, add one
// if the expression doesn't have any comments that will be emitted.
return !(expression.numericLiteralFlags & TokenFlags.WithSpecifier)
@@ -5169,7 +5169,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
return getSourceTextOfNodeFromSourceFile(sourceFile, node, includeTrivia);
}
- function getLiteralTextOfNode(node: LiteralLikeNode, neverAsciiEscape: boolean | undefined, jsxAttributeEscape: boolean): string {
+ function getLiteralTextOfNode(node: LiteralLikeNode, sourceFile = currentSourceFile, neverAsciiEscape: boolean | undefined, jsxAttributeEscape: boolean): string {
if (node.kind === SyntaxKind.StringLiteral && (node as StringLiteral).textSourceNode) {
const textSourceNode = (node as StringLiteral).textSourceNode!;
if (isIdentifier(textSourceNode) || isPrivateIdentifier(textSourceNode) || isNumericLiteral(textSourceNode) || isJsxNamespacedName(textSourceNode)) {
@@ -5179,7 +5179,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
`"${escapeNonAsciiString(text)}"`;
}
else {
- return getLiteralTextOfNode(textSourceNode, neverAsciiEscape, jsxAttributeEscape);
+ return getLiteralTextOfNode(textSourceNode, getSourceFileOfNode(textSourceNode), neverAsciiEscape, jsxAttributeEscape);
}
}
@@ -5188,7 +5188,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
| (printerOptions.terminateUnterminatedLiterals ? GetLiteralTextFlags.TerminateUnterminatedLiterals : 0)
| (printerOptions.target && printerOptions.target >= ScriptTarget.ES2021 ? GetLiteralTextFlags.AllowNumericSeparator : 0);
- return getLiteralText(node, currentSourceFile, flags);
+ return getLiteralText(node, sourceFile, flags);
}
/**
diff --git a/tests/cases/fourslash/completionClassMemberSnippetCrossFileNodeReuse1.ts b/tests/cases/fourslash/completionClassMemberSnippetCrossFileNodeReuse1.ts
new file mode 100644
index 00000000000..c03e698c86b
--- /dev/null
+++ b/tests/cases/fourslash/completionClassMemberSnippetCrossFileNodeReuse1.ts
@@ -0,0 +1,47 @@
+///
+
+// @strict: true
+
+// @filename: KlassConstructor.ts
+
+//// type GenericConstructor = new (...args: any[]) => T;
+//// export type KlassConstructor> =
+//// GenericConstructor> & { [k in keyof Cls]: Cls[k] };
+
+// @filename: ElementNode.ts
+//// import { KlassConstructor } from "./KlassConstructor";
+////
+//// export type NodeKey = string;
+////
+//// export class ElementNode {
+//// ["constructor"]!: KlassConstructor;
+//// }
+
+// @filename: CollapsibleContainerNode.ts
+//// import { ElementNode, NodeKey } from "./ElementNode";
+////
+//// export class CollapsibleContainerNode extends ElementNode {
+//// __open: boolean;
+////
+//// /*1*/
+//// }
+
+format.setFormatOptions({
+ insertSpaceAfterConstructor: false,
+});
+
+verify.completions({
+ marker: "1",
+ preferences: {
+ includeCompletionsWithClassMemberSnippets: true,
+ includeCompletionsWithInsertText: true,
+ },
+ includes: [{
+ name: `["constructor"]`,
+ insertText: `["constructor"]: KlassConstructor;`,
+ filterText: `["constructor"]`,
+ hasAction: true,
+ source: 'ClassMemberSnippet/'
+ }],
+ isNewIdentifierLocation: true,
+});