Skip to content

Commit c1e0db7

Browse files
authored
Escape apparent substitution in synthesized NoSubstitutionTemplateLiterals (microsoft#32580)
* Add failing test * Escape apparent substitution in synthesized NoSubstitutionTemplateLiterals
1 parent 012bacc commit c1e0db7

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

src/compiler/utilities.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,8 @@ namespace ts {
566566
return emitNode && emitNode.flags || 0;
567567
}
568568

569+
const escapeNoSubstitutionTemplateLiteralText = compose(escapeString, escapeTemplateSubstitution);
570+
const escapeNonAsciiNoSubstitutionTemplateLiteralText = compose(escapeNonAsciiString, escapeTemplateSubstitution);
569571
export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile, neverAsciiEscape: boolean | undefined) {
570572
// If we don't need to downlevel and we can reach the original source text using
571573
// the node's parent reference, then simply get the text as it was originally written.
@@ -576,7 +578,11 @@ namespace ts {
576578
return getSourceTextOfNodeFromSourceFile(sourceFile, node);
577579
}
578580

579-
const escapeText = neverAsciiEscape || (getEmitFlags(node) & EmitFlags.NoAsciiEscaping) ? escapeString : escapeNonAsciiString;
581+
// If a NoSubstitutionTemplateLiteral appears to have a substitution in it, the original text
582+
// had to include a backslash: `not \${a} substitution`.
583+
const escapeText = neverAsciiEscape || (getEmitFlags(node) & EmitFlags.NoAsciiEscaping) ?
584+
node.kind === SyntaxKind.NoSubstitutionTemplateLiteral ? escapeNoSubstitutionTemplateLiteralText : escapeString :
585+
node.kind === SyntaxKind.NoSubstitutionTemplateLiteral ? escapeNonAsciiNoSubstitutionTemplateLiteralText : escapeNonAsciiString;
580586

581587
// If we can't reach the original source text, use the canonical form if it's a number,
582588
// or a (possibly escaped) quoted form of the original text if it's string-like.
@@ -3113,6 +3119,11 @@ namespace ts {
31133119
}
31143120
}
31153121

3122+
const templateSubstitutionRegExp = /\$\{/g;
3123+
function escapeTemplateSubstitution(str: string): string {
3124+
return str.replace(templateSubstitutionRegExp, "\\${");
3125+
}
3126+
31163127
// This consists of the first 19 unprintable ASCII characters, canonical escapes, lineSeparator,
31173128
// paragraphSeparator, and nextLine. The latter three are just desirable to suppress new lines in
31183129
// the language service. These characters should be escaped when printing, and if any characters are added,
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
////function /*a*/insert/*b*/(template: string, overwriteBefore = 0) {}
4+
////insert(`this is \${not} a substitution`);
5+
6+
7+
goTo.select("a", "b");
8+
edit.applyRefactor({
9+
refactorName: "Convert parameters to destructured object",
10+
actionName: "Convert parameters to destructured object",
11+
actionDescription: "Convert parameters to destructured object",
12+
newContent: [
13+
'function insert({ template, overwriteBefore = 0 }: { template: string; overwriteBefore?: number; }) {}',
14+
'insert({ template: `this is \\${not} a substitution` });'
15+
].join('\n')
16+
});

0 commit comments

Comments
 (0)