Merge pull request #32117 from andrewbranch/bug/31460

Fix declaration emit for negative number properties, allow negative numbers as computed type property names
This commit is contained in:
Andrew Branch 2019-07-01 10:56:56 -07:00 committed by GitHub
commit 23f1d5ccb7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 204 additions and 4 deletions

View file

@ -274,6 +274,9 @@ namespace ts {
if (isStringOrNumericLiteralLike(nameExpression)) {
return escapeLeadingUnderscores(nameExpression.text);
}
if (isSignedNumericLiteral(nameExpression)) {
return tokenToString(nameExpression.operator) + nameExpression.operand.text as __String;
}
Debug.assert(isWellKnownSymbolSyntactically(nameExpression));
return getPropertyNameForKnownSymbolName(idText((<PropertyAccessExpression>nameExpression).name));

View file

@ -4652,6 +4652,9 @@ namespace ts {
if (!isIdentifierText(name, compilerOptions.target) && !isNumericLiteralName(name)) {
return `"${escapeString(name, CharacterCodes.doubleQuote)}"`;
}
if (isNumericLiteralName(name) && startsWith(name, "-")) {
return `[${name}]`;
}
return name;
}
if (nameType.flags & TypeFlags.UniqueESSymbol) {

View file

@ -2705,11 +2705,19 @@ namespace ts {
return isStringLiteralLike(node) || isNumericLiteral(node);
}
export function isSignedNumericLiteral(node: Node): node is PrefixUnaryExpression & { operand: NumericLiteral } {
return isPrefixUnaryExpression(node) && (node.operator === SyntaxKind.PlusToken || node.operator === SyntaxKind.MinusToken) && isNumericLiteral(node.operand);
}
/**
* A declaration has a dynamic name if both of the following are true:
* 1. The declaration has a computed property name
* 2. The computed name is *not* expressed as Symbol.<name>, where name
* is a property of the Symbol constructor that denotes a built in
* A declaration has a dynamic name if all of the following are true:
* 1. The declaration has a computed property name.
* 2. The computed name is *not* expressed as a StringLiteral.
* 3. The computed name is *not* expressed as a NumericLiteral.
* 4. The computed name is *not* expressed as a PlusToken or MinusToken
* immediately followed by a NumericLiteral.
* 5. The computed name is *not* expressed as `Symbol.<name>`, where `<name>`
* is a property of the Symbol constructor that denotes a built-in
* Symbol.
*/
export function hasDynamicName(declaration: Declaration): declaration is DynamicNamedDeclaration {
@ -2720,6 +2728,7 @@ namespace ts {
export function isDynamicName(name: DeclarationName): boolean {
return name.kind === SyntaxKind.ComputedPropertyName &&
!isStringOrNumericLiteralLike(name.expression) &&
!isSignedNumericLiteral(name.expression) &&
!isWellKnownSymbolSyntactically(name.expression);
}

View file

@ -0,0 +1,13 @@
tests/cases/conformance/es6/computedProperties/computedPropertyNamesDeclarationEmit6_ES5.ts(5,3): error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'.
==== tests/cases/conformance/es6/computedProperties/computedPropertyNamesDeclarationEmit6_ES5.ts (1 errors) ====
var v = {
[-1]: {},
[+1]: {},
[~1]: {},
[!1]: {}
~~~~
!!! error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'.
}

View file

@ -0,0 +1,25 @@
//// [computedPropertyNamesDeclarationEmit6_ES5.ts]
var v = {
[-1]: {},
[+1]: {},
[~1]: {},
[!1]: {}
}
//// [computedPropertyNamesDeclarationEmit6_ES5.js]
var _a;
var v = (_a = {},
_a[-1] = {},
_a[+1] = {},
_a[~1] = {},
_a[!1] = {},
_a);
//// [computedPropertyNamesDeclarationEmit6_ES5.d.ts]
declare var v: {
[x: number]: {};
[-1]: {};
1: {};
};

View file

@ -0,0 +1,17 @@
=== tests/cases/conformance/es6/computedProperties/computedPropertyNamesDeclarationEmit6_ES5.ts ===
var v = {
>v : Symbol(v, Decl(computedPropertyNamesDeclarationEmit6_ES5.ts, 0, 3))
[-1]: {},
>[-1] : Symbol([-1], Decl(computedPropertyNamesDeclarationEmit6_ES5.ts, 0, 9))
[+1]: {},
>[+1] : Symbol([+1], Decl(computedPropertyNamesDeclarationEmit6_ES5.ts, 1, 11))
[~1]: {},
>[~1] : Symbol([~1], Decl(computedPropertyNamesDeclarationEmit6_ES5.ts, 2, 11))
[!1]: {}
>[!1] : Symbol([!1], Decl(computedPropertyNamesDeclarationEmit6_ES5.ts, 3, 11))
}

View file

@ -0,0 +1,30 @@
=== tests/cases/conformance/es6/computedProperties/computedPropertyNamesDeclarationEmit6_ES5.ts ===
var v = {
>v : { [x: number]: {}; [-1]: {}; 1: {}; }
>{ [-1]: {}, [+1]: {}, [~1]: {}, [!1]: {}} : { [x: number]: {}; [-1]: {}; [+1]: {}; }
[-1]: {},
>[-1] : {}
>-1 : -1
>1 : 1
>{} : {}
[+1]: {},
>[+1] : {}
>+1 : 1
>1 : 1
>{} : {}
[~1]: {},
>[~1] : {}
>~1 : number
>1 : 1
>{} : {}
[!1]: {}
>[!1] : {}
>!1 : boolean
>1 : 1
>{} : {}
}

View file

@ -0,0 +1,13 @@
tests/cases/conformance/es6/computedProperties/computedPropertyNamesDeclarationEmit6_ES6.ts(5,3): error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'.
==== tests/cases/conformance/es6/computedProperties/computedPropertyNamesDeclarationEmit6_ES6.ts (1 errors) ====
var v = {
[-1]: {},
[+1]: {},
[~1]: {},
[!1]: {}
~~~~
!!! error TS2464: A computed property name must be of type 'string', 'number', 'symbol', or 'any'.
}

View file

@ -0,0 +1,24 @@
//// [computedPropertyNamesDeclarationEmit6_ES6.ts]
var v = {
[-1]: {},
[+1]: {},
[~1]: {},
[!1]: {}
}
//// [computedPropertyNamesDeclarationEmit6_ES6.js]
var v = {
[-1]: {},
[+1]: {},
[~1]: {},
[!1]: {}
};
//// [computedPropertyNamesDeclarationEmit6_ES6.d.ts]
declare var v: {
[x: number]: {};
[-1]: {};
1: {};
};

View file

@ -0,0 +1,17 @@
=== tests/cases/conformance/es6/computedProperties/computedPropertyNamesDeclarationEmit6_ES6.ts ===
var v = {
>v : Symbol(v, Decl(computedPropertyNamesDeclarationEmit6_ES6.ts, 0, 3))
[-1]: {},
>[-1] : Symbol([-1], Decl(computedPropertyNamesDeclarationEmit6_ES6.ts, 0, 9))
[+1]: {},
>[+1] : Symbol([+1], Decl(computedPropertyNamesDeclarationEmit6_ES6.ts, 1, 11))
[~1]: {},
>[~1] : Symbol([~1], Decl(computedPropertyNamesDeclarationEmit6_ES6.ts, 2, 11))
[!1]: {}
>[!1] : Symbol([!1], Decl(computedPropertyNamesDeclarationEmit6_ES6.ts, 3, 11))
}

View file

@ -0,0 +1,30 @@
=== tests/cases/conformance/es6/computedProperties/computedPropertyNamesDeclarationEmit6_ES6.ts ===
var v = {
>v : { [x: number]: {}; [-1]: {}; 1: {}; }
>{ [-1]: {}, [+1]: {}, [~1]: {}, [!1]: {}} : { [x: number]: {}; [-1]: {}; [+1]: {}; }
[-1]: {},
>[-1] : {}
>-1 : -1
>1 : 1
>{} : {}
[+1]: {},
>[+1] : {}
>+1 : 1
>1 : 1
>{} : {}
[~1]: {},
>[~1] : {}
>~1 : number
>1 : 1
>{} : {}
[!1]: {}
>[!1] : {}
>!1 : boolean
>1 : 1
>{} : {}
}

View file

@ -0,0 +1,8 @@
// @target: es5
// @declaration: true
var v = {
[-1]: {},
[+1]: {},
[~1]: {},
[!1]: {}
}

View file

@ -0,0 +1,8 @@
// @target: es6
// @declaration: true
var v = {
[-1]: {},
[+1]: {},
[~1]: {},
[!1]: {}
}