Treat NoSubstitutionTemplateLiteral like StringLiteral in more places (#26330)

* Treat NoSubstitutionTemplateLiteral like StringLiteral in more places

* Move isStringOrNumericLiteral closer to its only use
This commit is contained in:
Andy 2018-08-10 16:00:08 -07:00 committed by GitHub
parent 8ef7ceda6d
commit 08f5edbd03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 53 additions and 54 deletions

View File

@ -259,7 +259,7 @@ namespace ts {
if (name.kind === SyntaxKind.ComputedPropertyName) {
const nameExpression = name.expression;
// treat computed property names where expression is string/numeric literal as just string/numeric literal
if (isStringOrNumericLiteral(nameExpression)) {
if (isStringOrNumericLiteralLike(nameExpression)) {
return escapeLeadingUnderscores(nameExpression.text);
}

View File

@ -4447,7 +4447,7 @@ namespace ts {
}
function isComputedNonLiteralName(name: PropertyName): boolean {
return name.kind === SyntaxKind.ComputedPropertyName && !isStringOrNumericLiteral(name.expression);
return name.kind === SyntaxKind.ComputedPropertyName && !isStringOrNumericLiteralLike(name.expression);
}
function getRestType(source: Type, properties: PropertyName[], symbol: Symbol | undefined): Type {
@ -13741,7 +13741,7 @@ namespace ts {
case SyntaxKind.Identifier:
return idText(name);
case SyntaxKind.ComputedPropertyName:
return isStringOrNumericLiteral(name.expression) ? name.expression.text : undefined;
return isStringOrNumericLiteralLike(name.expression) ? name.expression.text : undefined;
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
return name.text;

View File

@ -4709,7 +4709,7 @@ namespace ts {
/**
* Gets the property name of a BindingOrAssignmentElement
*/
export function getPropertyNameOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement) {
export function getPropertyNameOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): PropertyName | undefined {
switch (bindingElement.kind) {
case SyntaxKind.BindingElement:
// `a` in `let { a: b } = ...`
@ -4754,6 +4754,12 @@ namespace ts {
Debug.fail("Invalid property name for binding element.");
}
function isStringOrNumericLiteral(node: Node): node is StringLiteral | NumericLiteral {
const kind = node.kind;
return kind === SyntaxKind.StringLiteral
|| kind === SyntaxKind.NumericLiteral;
}
/**
* Gets the elements of a BindingOrAssignmentPattern
*/

View File

@ -4465,7 +4465,7 @@ namespace ts {
}
else {
const argument = allowInAnd(parseExpression);
if (isStringOrNumericLiteral(argument)) {
if (isStringOrNumericLiteralLike(argument)) {
argument.text = internIdentifier(argument.text);
}
indexedAccess.argumentExpression = argument;

View File

@ -447,7 +447,7 @@ namespace ts {
const argumentExpression = ensureIdentifier(flattenContext, visitNode(propertyName.expression, flattenContext.visitor), /*reuseIdentifierExpressions*/ false, /*location*/ propertyName);
return createElementAccess(value, argumentExpression);
}
else if (isStringOrNumericLiteral(propertyName)) {
else if (isStringOrNumericLiteralLike(propertyName)) {
const argumentExpression = getSynthesizedClone(propertyName);
argumentExpression.text = argumentExpression.text;
return createElementAccess(value, argumentExpression);

View File

@ -771,9 +771,9 @@ namespace ts {
case SyntaxKind.NumericLiteral:
return escapeLeadingUnderscores(name.text);
case SyntaxKind.ComputedPropertyName:
return isStringOrNumericLiteral(name.expression) ? escapeLeadingUnderscores(name.expression.text) : undefined!; // TODO: GH#18217 Almost all uses of this assume the result to be defined!
return isStringOrNumericLiteralLike(name.expression) ? escapeLeadingUnderscores(name.expression.text) : undefined!; // TODO: GH#18217 Almost all uses of this assume the result to be defined!
default:
Debug.assertNever(name);
return Debug.assertNever(name);
}
}
@ -2566,10 +2566,8 @@ namespace ts {
return false;
}
export function isStringOrNumericLiteral(node: Node): node is StringLiteral | NumericLiteral {
const kind = node.kind;
return kind === SyntaxKind.StringLiteral
|| kind === SyntaxKind.NumericLiteral;
export function isStringOrNumericLiteralLike(node: Node): node is StringLiteralLike | NumericLiteral {
return isStringLiteralLike(node) || isNumericLiteral(node);
}
/**
@ -2586,7 +2584,7 @@ namespace ts {
export function isDynamicName(name: DeclarationName): boolean {
return name.kind === SyntaxKind.ComputedPropertyName &&
!isStringOrNumericLiteral(name.expression) &&
!isStringOrNumericLiteralLike(name.expression) &&
!isWellKnownSymbolSyntactically(name.expression);
}
@ -2599,24 +2597,25 @@ namespace ts {
return isPropertyAccessExpression(node) && isESSymbolIdentifier(node.expression);
}
export function getPropertyNameForPropertyNameNode(name: DeclarationName): __String | undefined {
if (name.kind === SyntaxKind.Identifier) {
return name.escapedText;
export function getPropertyNameForPropertyNameNode(name: PropertyName): __String | undefined {
switch (name.kind) {
case SyntaxKind.Identifier:
return name.escapedText;
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
return escapeLeadingUnderscores(name.text);
case SyntaxKind.ComputedPropertyName:
const nameExpression = name.expression;
if (isWellKnownSymbolSyntactically(nameExpression)) {
return getPropertyNameForKnownSymbolName(idText((<PropertyAccessExpression>nameExpression).name));
}
else if (isStringOrNumericLiteralLike(nameExpression)) {
return escapeLeadingUnderscores(nameExpression.text);
}
return undefined;
default:
return Debug.assertNever(name);
}
if (name.kind === SyntaxKind.StringLiteral || name.kind === SyntaxKind.NumericLiteral) {
return escapeLeadingUnderscores(name.text);
}
if (name.kind === SyntaxKind.ComputedPropertyName) {
const nameExpression = name.expression;
if (isWellKnownSymbolSyntactically(nameExpression)) {
return getPropertyNameForKnownSymbolName(idText((<PropertyAccessExpression>nameExpression).name));
}
else if (nameExpression.kind === SyntaxKind.StringLiteral || nameExpression.kind === SyntaxKind.NumericLiteral) {
return escapeLeadingUnderscores((<LiteralExpression>nameExpression).text);
}
}
return undefined;
}
export type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral;
@ -3331,17 +3330,17 @@ namespace ts {
}
}
else {
forEach(declarations, (member: Declaration) => {
if ((member.kind === SyntaxKind.GetAccessor || member.kind === SyntaxKind.SetAccessor)
forEach(declarations, member => {
if (isAccessor(member)
&& hasModifier(member, ModifierFlags.Static) === hasModifier(accessor, ModifierFlags.Static)) {
const memberName = getPropertyNameForPropertyNameNode((member as NamedDeclaration).name!);
const memberName = getPropertyNameForPropertyNameNode(member.name);
const accessorName = getPropertyNameForPropertyNameNode(accessor.name);
if (memberName === accessorName) {
if (!firstAccessor) {
firstAccessor = <AccessorDeclaration>member;
firstAccessor = member;
}
else if (!secondAccessor) {
secondAccessor = <AccessorDeclaration>member;
secondAccessor = member;
}
if (member.kind === SyntaxKind.GetAccessor && !getAccessor) {

View File

@ -416,7 +416,7 @@ namespace ts.NavigationBar {
}
const declName = getNameOfDeclaration(<Declaration>node);
if (declName) {
if (declName && isPropertyName(declName)) {
return unescapeLeadingUnderscores(getPropertyNameForPropertyNameNode(declName)!); // TODO: GH#18217
}
switch (node.kind) {

View File

@ -29,7 +29,7 @@ namespace ts.Rename {
if (isStringLiteralLike(node) && tryGetImportFromModuleSpecifier(node)) return undefined;
const kind = SymbolDisplay.getSymbolKind(typeChecker, symbol, node);
const specifierName = (isImportOrExportSpecifierName(node) || isStringOrNumericLiteral(node) && node.parent.kind === SyntaxKind.ComputedPropertyName)
const specifierName = (isImportOrExportSpecifierName(node) || isStringOrNumericLiteralLike(node) && node.parent.kind === SyntaxKind.ComputedPropertyName)
? stripQuotes(getTextOfIdentifierOrLiteral(node))
: undefined;
const displayName = specifierName || typeChecker.symbolToString(symbol);

View File

@ -2142,7 +2142,7 @@ namespace ts {
function initializeNameTable(sourceFile: SourceFile): void {
const nameTable = sourceFile.nameTable = createUnderscoreEscapedMap<number>();
sourceFile.forEachChild(function walk(node) {
if (isIdentifier(node) && node.escapedText || isStringOrNumericLiteral(node) && literalIsName(node)) {
if (isIdentifier(node) && node.escapedText || isStringOrNumericLiteralLike(node) && literalIsName(node)) {
const text = getEscapedTextOfIdentifierOrLiteral(node);
nameTable.set(text, nameTable.get(text) === undefined ? node.pos : -1);
}
@ -2162,7 +2162,7 @@ namespace ts {
* then we want 'something' to be in the name table. Similarly, if we have
* "a['propname']" then we want to store "propname" in the name table.
*/
function literalIsName(node: StringLiteral | NumericLiteral): boolean {
function literalIsName(node: StringLiteralLike | NumericLiteral): boolean {
return isDeclarationName(node) ||
node.parent.kind === SyntaxKind.ExternalModuleReference ||
isArgumentOfElementAccessExpression(node) ||

View File

@ -1240,7 +1240,7 @@ namespace ts {
export function getNameFromPropertyName(name: PropertyName): string | undefined {
return name.kind === SyntaxKind.ComputedPropertyName
// treat computed property names where expression is string/numeric literal as just string/numeric literal
? isStringOrNumericLiteral(name.expression) ? name.expression.text : undefined
? isStringOrNumericLiteralLike(name.expression) ? name.expression.text : undefined
: getTextOfIdentifierOrLiteral(name);
}

View File

@ -9,8 +9,8 @@ var a: any;
>a : any
var v = {
>v : { [x: string]: any; [x: number]: any; [""]: any; readonly [0]: number; }
>{ get [s]() { return 0; }, set [n](v) { }, get [s + s]() { return 0; }, set [s + n](v) { }, get [+s]() { return 0; }, set [""](v) { }, get [0]() { return 0; }, set [a](v) { }, get [<any>true]() { return 0; }, set [`hello bye`](v) { }, get [`hello ${a} bye`]() { return 0; }} : { [x: string]: any; [x: number]: any; [""]: any; readonly [0]: number; }
>v : { [x: string]: any; [x: number]: any; [""]: any; readonly [0]: number; [`hello bye`]: any; }
>{ get [s]() { return 0; }, set [n](v) { }, get [s + s]() { return 0; }, set [s + n](v) { }, get [+s]() { return 0; }, set [""](v) { }, get [0]() { return 0; }, set [a](v) { }, get [<any>true]() { return 0; }, set [`hello bye`](v) { }, get [`hello ${a} bye`]() { return 0; }} : { [x: string]: any; [x: number]: any; [""]: any; readonly [0]: number; [`hello bye`]: any; }
get [s]() { return 0; },
>[s] : number

View File

@ -9,8 +9,8 @@ var a: any;
>a : any
var v = {
>v : { [x: string]: any; [x: number]: any; [""]: any; readonly [0]: number; }
>{ get [s]() { return 0; }, set [n](v) { }, get [s + s]() { return 0; }, set [s + n](v) { }, get [+s]() { return 0; }, set [""](v) { }, get [0]() { return 0; }, set [a](v) { }, get [<any>true]() { return 0; }, set [`hello bye`](v) { }, get [`hello ${a} bye`]() { return 0; }} : { [x: string]: any; [x: number]: any; [""]: any; readonly [0]: number; }
>v : { [x: string]: any; [x: number]: any; [""]: any; readonly [0]: number; [`hello bye`]: any; }
>{ get [s]() { return 0; }, set [n](v) { }, get [s + s]() { return 0; }, set [s + n](v) { }, get [+s]() { return 0; }, set [""](v) { }, get [0]() { return 0; }, set [a](v) { }, get [<any>true]() { return 0; }, set [`hello bye`](v) { }, get [`hello ${a} bye`]() { return 0; }} : { [x: string]: any; [x: number]: any; [""]: any; readonly [0]: number; [`hello bye`]: any; }
get [s]() { return 0; },
>[s] : number

View File

@ -5,11 +5,10 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames12_ES5.ts(8,
tests/cases/conformance/es6/computedProperties/computedPropertyNames12_ES5.ts(9,5): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type.
tests/cases/conformance/es6/computedProperties/computedPropertyNames12_ES5.ts(12,5): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type.
tests/cases/conformance/es6/computedProperties/computedPropertyNames12_ES5.ts(13,12): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type.
tests/cases/conformance/es6/computedProperties/computedPropertyNames12_ES5.ts(14,5): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type.
tests/cases/conformance/es6/computedProperties/computedPropertyNames12_ES5.ts(15,12): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type.
==== tests/cases/conformance/es6/computedProperties/computedPropertyNames12_ES5.ts (9 errors) ====
==== tests/cases/conformance/es6/computedProperties/computedPropertyNames12_ES5.ts (8 errors) ====
var s: string;
var n: number;
var a: any;
@ -38,8 +37,6 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames12_ES5.ts(15
~~~~~~~~~~~
!!! error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type.
[`hello bye`] = 0;
~~~~~~~~~~~~~
!!! error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type.
static [`hello ${a} bye`] = 0
~~~~~~~~~~~~~~~~~~
!!! error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type.

View File

@ -5,11 +5,10 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames12_ES6.ts(8,
tests/cases/conformance/es6/computedProperties/computedPropertyNames12_ES6.ts(9,5): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type.
tests/cases/conformance/es6/computedProperties/computedPropertyNames12_ES6.ts(12,5): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type.
tests/cases/conformance/es6/computedProperties/computedPropertyNames12_ES6.ts(13,12): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type.
tests/cases/conformance/es6/computedProperties/computedPropertyNames12_ES6.ts(14,5): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type.
tests/cases/conformance/es6/computedProperties/computedPropertyNames12_ES6.ts(15,12): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type.
==== tests/cases/conformance/es6/computedProperties/computedPropertyNames12_ES6.ts (9 errors) ====
==== tests/cases/conformance/es6/computedProperties/computedPropertyNames12_ES6.ts (8 errors) ====
var s: string;
var n: number;
var a: any;
@ -38,8 +37,6 @@ tests/cases/conformance/es6/computedProperties/computedPropertyNames12_ES6.ts(15
~~~~~~~~~~~
!!! error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type.
[`hello bye`] = 0;
~~~~~~~~~~~~~
!!! error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type.
static [`hello ${a} bye`] = 0
~~~~~~~~~~~~~~~~~~
!!! error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type.

View File

@ -1,7 +1,7 @@
=== tests/cases/compiler/computerPropertiesInES5ShouldBeTransformed.ts ===
const b = ({ [`key`]: renamed }) => renamed;
>b : ({ [`key`]: renamed }: {}) => any
>({ [`key`]: renamed }) => renamed : ({ [`key`]: renamed }: {}) => any
>b : ({ [`key`]: renamed }: { key: any; }) => any
>({ [`key`]: renamed }) => renamed : ({ [`key`]: renamed }: { key: any; }) => any
>`key` : "key"
>renamed : any
>renamed : any