Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,7 @@ namespace ts {
return expr.kind === SyntaxKind.Identifier || expr.kind === SyntaxKind.ThisKeyword || expr.kind === SyntaxKind.SuperKeyword ||
(isPropertyAccessExpression(expr) || isNonNullExpression(expr) || isParenthesizedExpression(expr)) && isNarrowableReference(expr.expression) ||
isElementAccessExpression(expr) &&
(isStringLiteral(expr.argumentExpression) || isNumericLiteral(expr.argumentExpression)) &&
isStringOrNumericLiteralLike(expr.argumentExpression) &&
isNarrowableReference(expr.expression);
}

Expand Down
20 changes: 11 additions & 9 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6584,7 +6584,7 @@ namespace ts {
}

function isStringConcatExpression(expr: Node): boolean {
if (expr.kind === SyntaxKind.StringLiteral) {
if (isStringLiteralLike(expr)) {
return true;
}
else if (expr.kind === SyntaxKind.BinaryExpression) {
Expand All @@ -6601,6 +6601,7 @@ namespace ts {
switch (expr.kind) {
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
return true;
case SyntaxKind.PrefixUnaryExpression:
return (<PrefixUnaryExpression>expr).operator === SyntaxKind.MinusToken &&
Expand All @@ -6623,7 +6624,7 @@ namespace ts {
for (const declaration of symbol.declarations) {
if (declaration.kind === SyntaxKind.EnumDeclaration) {
for (const member of (<EnumDeclaration>declaration).members) {
if (member.initializer && member.initializer.kind === SyntaxKind.StringLiteral) {
if (member.initializer && isStringLiteralLike(member.initializer)) {
return links.enumKind = EnumKind.Literal;
}
if (!isLiteralEnumMember(member)) {
Expand Down Expand Up @@ -16514,7 +16515,7 @@ namespace ts {

function getAccessedPropertyName(access: AccessExpression): __String | undefined {
return access.kind === SyntaxKind.PropertyAccessExpression ? access.name.escapedText :
isStringLiteral(access.argumentExpression) || isNumericLiteral(access.argumentExpression) ? escapeLeadingUnderscores(access.argumentExpression.text) :
isStringOrNumericLiteralLike(access.argumentExpression) ? escapeLeadingUnderscores(access.argumentExpression.text) :
undefined;
}

Expand Down Expand Up @@ -16912,8 +16913,8 @@ namespace ts {
const witnesses: (string | undefined)[] = [];
for (const clause of switchStatement.caseBlock.clauses) {
if (clause.kind === SyntaxKind.CaseClause) {
if (clause.expression.kind === SyntaxKind.StringLiteral) {
witnesses.push((clause.expression as StringLiteral).text);
if (isStringLiteralLike(clause.expression)) {
witnesses.push(clause.expression.text);
continue;
}
return emptyArray;
Expand Down Expand Up @@ -21466,7 +21467,7 @@ namespace ts {
return objectType;
}

if (isConstEnumObjectType(objectType) && indexExpression.kind !== SyntaxKind.StringLiteral) {
if (isConstEnumObjectType(objectType) && !isStringLiteralLike(indexExpression)) {
error(indexExpression, Diagnostics.A_const_enum_member_can_only_be_accessed_using_a_string_literal);
return errorType;
}
Expand Down Expand Up @@ -30095,7 +30096,8 @@ namespace ts {
}
break;
case SyntaxKind.StringLiteral:
return (<StringLiteral>expr).text;
case SyntaxKind.NoSubstitutionTemplateLiteral:
return (<StringLiteralLike>expr).text;
case SyntaxKind.NumericLiteral:
checkGrammarNumericLiteral(<NumericLiteral>expr);
return +(<NumericLiteral>expr).text;
Expand Down Expand Up @@ -30148,7 +30150,7 @@ namespace ts {
return node.kind === SyntaxKind.Identifier ||
node.kind === SyntaxKind.PropertyAccessExpression && isConstantMemberAccess((<PropertyAccessExpression>node).expression) ||
node.kind === SyntaxKind.ElementAccessExpression && isConstantMemberAccess((<ElementAccessExpression>node).expression) &&
(<ElementAccessExpression>node).argumentExpression.kind === SyntaxKind.StringLiteral;
isStringLiteralLike((<ElementAccessExpression>node).argumentExpression);
}

function checkEnumDeclaration(node: EnumDeclaration) {
Expand Down Expand Up @@ -33700,7 +33702,7 @@ namespace ts {
}

function isStringOrNumberLiteralExpression(expr: Expression) {
return expr.kind === SyntaxKind.StringLiteral || expr.kind === SyntaxKind.NumericLiteral ||
return isStringOrNumericLiteralLike(expr) ||
expr.kind === SyntaxKind.PrefixUnaryExpression && (<PrefixUnaryExpression>expr).operator === SyntaxKind.MinusToken &&
(<PrefixUnaryExpression>expr).operand.kind === SyntaxKind.NumericLiteral;
}
Expand Down
7 changes: 4 additions & 3 deletions src/compiler/transformers/ts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3249,9 +3249,10 @@ namespace ts {

const substitute = createLiteral(constantValue);
if (!compilerOptions.removeComments) {
const propertyName = isPropertyAccessExpression(node)
? declarationNameToString(node.name)
: getTextOfNode(node.argumentExpression);
const originalNode = getOriginalNode(node, isAccessExpression);
const propertyName = isPropertyAccessExpression(originalNode)
? declarationNameToString(originalNode.name)
: getTextOfNode(originalNode.argumentExpression);

addSyntheticTrailingComment(substitute, SyntaxKind.MultiLineCommentTrivia, ` ${propertyName} `);
}
Expand Down
15 changes: 11 additions & 4 deletions src/compiler/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1692,7 +1692,6 @@ namespace ts {
case SyntaxKind.ConditionalExpression:
case SyntaxKind.SpreadElement:
case SyntaxKind.TemplateExpression:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.OmittedExpression:
case SyntaxKind.JsxElement:
case SyntaxKind.JsxSelfClosingElement:
Expand All @@ -1715,6 +1714,7 @@ namespace ts {
case SyntaxKind.NumericLiteral:
case SyntaxKind.BigIntLiteral:
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.ThisKeyword:
return isInExpressionContext(node);
default:
Expand Down Expand Up @@ -2529,6 +2529,7 @@ namespace ts {
const parent = name.parent;
switch (name.kind) {
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.NumericLiteral:
if (isComputedPropertyName(parent)) return parent.parent;
// falls through
Expand Down Expand Up @@ -2556,7 +2557,7 @@ namespace ts {
}

export function isLiteralComputedPropertyDeclarationName(node: Node) {
return (node.kind === SyntaxKind.StringLiteral || node.kind === SyntaxKind.NumericLiteral) &&
return isStringOrNumericLiteralLike(node) &&
node.parent.kind === SyntaxKind.ComputedPropertyName &&
isDeclaration(node.parent.parent);
}
Expand Down Expand Up @@ -3220,18 +3221,24 @@ namespace ts {
}

/**
* Strip off existed single quotes or double quotes from a given string
* Strip off existed surrounding single quotes, double quotes, or backticks from a given string
*
* @return non-quoted string
*/
export function stripQuotes(name: string) {
const length = name.length;
if (length >= 2 && name.charCodeAt(0) === name.charCodeAt(length - 1) && startsWithQuote(name)) {
if (length >= 2 && name.charCodeAt(0) === name.charCodeAt(length - 1) && isQuoteOrBacktick(name.charCodeAt(0))) {
return name.substring(1, length - 1);
}
return name;
}

function isQuoteOrBacktick(charCode: number) {
return charCode === CharacterCodes.singleQuote ||
charCode === CharacterCodes.doubleQuote ||
charCode === CharacterCodes.backtick;
}

export function startsWithQuote(name: string): boolean {
return isSingleOrDoubleQuote(name.charCodeAt(0));
}
Expand Down
5 changes: 3 additions & 2 deletions src/services/findAllReferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ namespace ts.FindAllReferences {
function getTextSpan(node: Node, sourceFile: SourceFile, endNode?: Node): TextSpan {
let start = node.getStart(sourceFile);
let end = (endNode || node).getEnd();
if (node.kind === SyntaxKind.StringLiteral) {
if (isStringLiteralLike(node)) {
Debug.assert(endNode === undefined);
start += 1;
end -= 1;
Expand Down Expand Up @@ -1234,8 +1234,9 @@ namespace ts.FindAllReferences.Core {
case SyntaxKind.Identifier:
return (node as Identifier).text.length === searchSymbolName.length;

case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.StringLiteral: {
const str = node as StringLiteral;
const str = node as StringLiteralLike;
return (isLiteralNameOfPropertyDeclarationOrIndexAccess(str) || isNameOfModuleDeclaration(node) || isExpressionOfExternalModuleImportEqualsDeclaration(node) || (isCallExpression(node.parent) && isBindableObjectDefinePropertyCall(node.parent) && node.parent.arguments[1] === node)) &&
str.text.length === searchSymbolName.length;
}
Expand Down
3 changes: 2 additions & 1 deletion src/services/rename.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ namespace ts.Rename {
function createTriggerSpanForNode(node: Node, sourceFile: SourceFile) {
let start = node.getStart(sourceFile);
let width = node.getWidth(sourceFile);
if (node.kind === SyntaxKind.StringLiteral) {
if (isStringLiteralLike(node)) {
// Exclude the quotes
start += 1;
width -= 2;
Expand All @@ -93,6 +93,7 @@ namespace ts.Rename {
switch (node.kind) {
case SyntaxKind.Identifier:
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.ThisKeyword:
return true;
case SyntaxKind.NumericLiteral:
Expand Down
1 change: 1 addition & 0 deletions src/services/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2227,6 +2227,7 @@ namespace ts {
function getContainingObjectLiteralElementWorker(node: Node): ObjectLiteralElement | undefined {
switch (node.kind) {
case SyntaxKind.StringLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.NumericLiteral:
if (node.parent.kind === SyntaxKind.ComputedPropertyName) {
return isObjectLiteralElement(node.parent.parent) ? node.parent.parent : undefined;
Expand Down
2 changes: 1 addition & 1 deletion src/services/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ namespace ts {
isFunctionLike(node.parent) && (<FunctionLikeDeclaration>node.parent).name === node;
}

export function isLiteralNameOfPropertyDeclarationOrIndexAccess(node: StringLiteral | NumericLiteral): boolean {
export function isLiteralNameOfPropertyDeclarationOrIndexAccess(node: StringLiteral | NumericLiteral | NoSubstitutionTemplateLiteral): boolean {
switch (node.parent.kind) {
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.PropertySignature:
Expand Down
28 changes: 28 additions & 0 deletions tests/baselines/reference/ambientModuleWithTemplateLiterals.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//// [ambientModuleWithTemplateLiterals.ts]
declare module Foo {
enum Bar {
a = `1`,
b = '2',
c = '3'
}

export const a = 'string';
export const b = `template`;

export const c = Bar.a;
export const d = Bar['b'];
export const e = Bar[`c`];
}

Foo.a;
Foo.b;
Foo.c;
Foo.d;
Foo.e;

//// [ambientModuleWithTemplateLiterals.js]
Foo.a;
Foo.b;
Foo.c;
Foo.d;
Foo.e;
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
=== tests/cases/compiler/ambientModuleWithTemplateLiterals.ts ===
declare module Foo {
>Foo : Symbol(Foo, Decl(ambientModuleWithTemplateLiterals.ts, 0, 0))

enum Bar {
>Bar : Symbol(Bar, Decl(ambientModuleWithTemplateLiterals.ts, 0, 20))

a = `1`,
>a : Symbol(Bar.a, Decl(ambientModuleWithTemplateLiterals.ts, 1, 14))

b = '2',
>b : Symbol(Bar.b, Decl(ambientModuleWithTemplateLiterals.ts, 2, 16))

c = '3'
>c : Symbol(Bar.c, Decl(ambientModuleWithTemplateLiterals.ts, 3, 16))
}

export const a = 'string';
>a : Symbol(a, Decl(ambientModuleWithTemplateLiterals.ts, 7, 16))

export const b = `template`;
>b : Symbol(b, Decl(ambientModuleWithTemplateLiterals.ts, 8, 16))

export const c = Bar.a;
>c : Symbol(c, Decl(ambientModuleWithTemplateLiterals.ts, 10, 16))
>Bar.a : Symbol(Bar.a, Decl(ambientModuleWithTemplateLiterals.ts, 1, 14))
>Bar : Symbol(Bar, Decl(ambientModuleWithTemplateLiterals.ts, 0, 20))
>a : Symbol(Bar.a, Decl(ambientModuleWithTemplateLiterals.ts, 1, 14))

export const d = Bar['b'];
>d : Symbol(d, Decl(ambientModuleWithTemplateLiterals.ts, 11, 16))
>Bar : Symbol(Bar, Decl(ambientModuleWithTemplateLiterals.ts, 0, 20))
>'b' : Symbol(Bar.b, Decl(ambientModuleWithTemplateLiterals.ts, 2, 16))

export const e = Bar[`c`];
>e : Symbol(e, Decl(ambientModuleWithTemplateLiterals.ts, 12, 16))
>Bar : Symbol(Bar, Decl(ambientModuleWithTemplateLiterals.ts, 0, 20))
>`c` : Symbol(Bar.c, Decl(ambientModuleWithTemplateLiterals.ts, 3, 16))
}

Foo.a;
>Foo.a : Symbol(Foo.a, Decl(ambientModuleWithTemplateLiterals.ts, 7, 16))
>Foo : Symbol(Foo, Decl(ambientModuleWithTemplateLiterals.ts, 0, 0))
>a : Symbol(Foo.a, Decl(ambientModuleWithTemplateLiterals.ts, 7, 16))

Foo.b;
>Foo.b : Symbol(Foo.b, Decl(ambientModuleWithTemplateLiterals.ts, 8, 16))
>Foo : Symbol(Foo, Decl(ambientModuleWithTemplateLiterals.ts, 0, 0))
>b : Symbol(Foo.b, Decl(ambientModuleWithTemplateLiterals.ts, 8, 16))

Foo.c;
>Foo.c : Symbol(Foo.c, Decl(ambientModuleWithTemplateLiterals.ts, 10, 16))
>Foo : Symbol(Foo, Decl(ambientModuleWithTemplateLiterals.ts, 0, 0))
>c : Symbol(Foo.c, Decl(ambientModuleWithTemplateLiterals.ts, 10, 16))

Foo.d;
>Foo.d : Symbol(Foo.d, Decl(ambientModuleWithTemplateLiterals.ts, 11, 16))
>Foo : Symbol(Foo, Decl(ambientModuleWithTemplateLiterals.ts, 0, 0))
>d : Symbol(Foo.d, Decl(ambientModuleWithTemplateLiterals.ts, 11, 16))

Foo.e;
>Foo.e : Symbol(Foo.e, Decl(ambientModuleWithTemplateLiterals.ts, 12, 16))
>Foo : Symbol(Foo, Decl(ambientModuleWithTemplateLiterals.ts, 0, 0))
>e : Symbol(Foo.e, Decl(ambientModuleWithTemplateLiterals.ts, 12, 16))

72 changes: 72 additions & 0 deletions tests/baselines/reference/ambientModuleWithTemplateLiterals.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
=== tests/cases/compiler/ambientModuleWithTemplateLiterals.ts ===
declare module Foo {
>Foo : typeof Foo

enum Bar {
>Bar : Bar

a = `1`,
>a : Bar.a
>`1` : "1"

b = '2',
>b : Bar.b
>'2' : "2"

c = '3'
>c : Bar.c
>'3' : "3"
}

export const a = 'string';
>a : "string"
>'string' : "string"

export const b = `template`;
>b : "template"
>`template` : "template"

export const c = Bar.a;
>c : Bar.a
>Bar.a : Bar.a
>Bar : typeof Bar
>a : Bar.a

export const d = Bar['b'];
>d : Bar.b
>Bar['b'] : Bar.b
>Bar : typeof Bar
>'b' : "b"

export const e = Bar[`c`];
>e : Bar.c
>Bar[`c`] : Bar.c
>Bar : typeof Bar
>`c` : "c"
}

Foo.a;
>Foo.a : "string"
>Foo : typeof Foo
>a : "string"

Foo.b;
>Foo.b : "template"
>Foo : typeof Foo
>b : "template"

Foo.c;
>Foo.c : Foo.Bar.a
>Foo : typeof Foo
>c : Foo.Bar.a

Foo.d;
>Foo.d : Foo.Bar.b
>Foo : typeof Foo
>d : Foo.Bar.b

Foo.e;
>Foo.e : Foo.Bar.c
>Foo : typeof Foo
>e : Foo.Bar.c

Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ var v = {

[`hello bye`]() { },
>[`hello bye`] : Symbol([`hello bye`], Decl(computedPropertyNames10_ES5.ts, 12, 22))
>`hello bye` : Symbol([`hello bye`], Decl(computedPropertyNames10_ES5.ts, 12, 22))

[`hello ${a} bye`]() { }
>[`hello ${a} bye`] : Symbol([`hello ${a} bye`], Decl(computedPropertyNames10_ES5.ts, 13, 24))
Expand Down
Loading