Emit parenthesis around propert/element access expression of casted object literal expression

This commit is contained in:
Kanchalai Tanglertsampan 2017-04-04 11:15:03 -07:00
parent dd48dd1b66
commit 0a194f91a0
9 changed files with 101 additions and 4 deletions

View file

@ -2324,14 +2324,19 @@ namespace ts {
// code if the casted expression has a lower precedence than the rest of the
// expression.
//
// To preserve comments, we return a "PartiallyEmittedExpression" here which will
// preserve the position information of the original expression.
const partialExpression = createPartiallyEmittedExpression(expression, node);
// Due to the auto-parenthesization rules used by the visitor and factory functions
// we can safely elide the parentheses here, as a new synthetic
// ParenthesizedExpression will be inserted if we remove parentheses too
// aggressively.
//
// To preserve comments, we return a "PartiallyEmittedExpression" here which will
// preserve the position information of the original expression.
return createPartiallyEmittedExpression(expression, node);
// However, auto-parenthesization will not preserve parenthesis for the following case: ({ "1": "one", "2": "two" } as { [key: string]: string })[x].
// so we have to manually preserve it here.
const shouldPreserveParen = (isPropertyAccessExpression(node.parent) || isElementAccessExpression(node.parent)) &&
isObjectLiteralExpression((expression as PartiallyEmittedExpression).expression);
return shouldPreserveParen ? createParen(partialExpression) : partialExpression;
}
return visitEachChild(node, visitor, context);

View file

@ -0,0 +1,7 @@
//// [emitAccessExpressionOfCastedObjectLiteralExpressionES5.ts]
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string })[x];
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string }).x;
//// [emitAccessExpressionOfCastedObjectLiteralExpressionES5.js]
(function (x) { return ({ "1": "one", "2": "two" })[x]; });
(function (x) { return ({ "1": "one", "2": "two" }).x; });

View file

@ -0,0 +1,10 @@
=== tests/cases/compiler/emitAccessExpressionOfCastedObjectLiteralExpressionES5.ts ===
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string })[x];
>x : Symbol(x, Decl(emitAccessExpressionOfCastedObjectLiteralExpressionES5.ts, 0, 1))
>key : Symbol(key, Decl(emitAccessExpressionOfCastedObjectLiteralExpressionES5.ts, 0, 41))
>x : Symbol(x, Decl(emitAccessExpressionOfCastedObjectLiteralExpressionES5.ts, 0, 1))
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string }).x;
>x : Symbol(x, Decl(emitAccessExpressionOfCastedObjectLiteralExpressionES5.ts, 1, 1))
>key : Symbol(key, Decl(emitAccessExpressionOfCastedObjectLiteralExpressionES5.ts, 1, 41))

View file

@ -0,0 +1,25 @@
=== tests/cases/compiler/emitAccessExpressionOfCastedObjectLiteralExpressionES5.ts ===
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string })[x];
>(x) => ({ "1": "one", "2": "two" } as { [key: string]: string })[x] : (x: any) => string
>x : any
>({ "1": "one", "2": "two" } as { [key: string]: string })[x] : string
>({ "1": "one", "2": "two" } as { [key: string]: string }) : { [key: string]: string; }
>{ "1": "one", "2": "two" } as { [key: string]: string } : { [key: string]: string; }
>{ "1": "one", "2": "two" } : { "1": string; "2": string; }
>"one" : "one"
>"two" : "two"
>key : string
>x : any
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string }).x;
>(x) => ({ "1": "one", "2": "two" } as { [key: string]: string }).x : (x: any) => string
>x : any
>({ "1": "one", "2": "two" } as { [key: string]: string }).x : string
>({ "1": "one", "2": "two" } as { [key: string]: string }) : { [key: string]: string; }
>{ "1": "one", "2": "two" } as { [key: string]: string } : { [key: string]: string; }
>{ "1": "one", "2": "two" } : { "1": string; "2": string; }
>"one" : "one"
>"two" : "two"
>key : string
>x : string

View file

@ -0,0 +1,7 @@
//// [emitAccessExpressionOfCastedObjectLiteralExpressionES6.ts]
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string })[x];
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string }).x;
//// [emitAccessExpressionOfCastedObjectLiteralExpressionES6.js]
(x) => ({ "1": "one", "2": "two" })[x];
(x) => ({ "1": "one", "2": "two" }).x;

View file

@ -0,0 +1,10 @@
=== tests/cases/compiler/emitAccessExpressionOfCastedObjectLiteralExpressionES6.ts ===
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string })[x];
>x : Symbol(x, Decl(emitAccessExpressionOfCastedObjectLiteralExpressionES6.ts, 0, 1))
>key : Symbol(key, Decl(emitAccessExpressionOfCastedObjectLiteralExpressionES6.ts, 0, 41))
>x : Symbol(x, Decl(emitAccessExpressionOfCastedObjectLiteralExpressionES6.ts, 0, 1))
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string }).x;
>x : Symbol(x, Decl(emitAccessExpressionOfCastedObjectLiteralExpressionES6.ts, 1, 1))
>key : Symbol(key, Decl(emitAccessExpressionOfCastedObjectLiteralExpressionES6.ts, 1, 41))

View file

@ -0,0 +1,25 @@
=== tests/cases/compiler/emitAccessExpressionOfCastedObjectLiteralExpressionES6.ts ===
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string })[x];
>(x) => ({ "1": "one", "2": "two" } as { [key: string]: string })[x] : (x: any) => string
>x : any
>({ "1": "one", "2": "two" } as { [key: string]: string })[x] : string
>({ "1": "one", "2": "two" } as { [key: string]: string }) : { [key: string]: string; }
>{ "1": "one", "2": "two" } as { [key: string]: string } : { [key: string]: string; }
>{ "1": "one", "2": "two" } : { "1": string; "2": string; }
>"one" : "one"
>"two" : "two"
>key : string
>x : any
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string }).x;
>(x) => ({ "1": "one", "2": "two" } as { [key: string]: string }).x : (x: any) => string
>x : any
>({ "1": "one", "2": "two" } as { [key: string]: string }).x : string
>({ "1": "one", "2": "two" } as { [key: string]: string }) : { [key: string]: string; }
>{ "1": "one", "2": "two" } as { [key: string]: string } : { [key: string]: string; }
>{ "1": "one", "2": "two" } : { "1": string; "2": string; }
>"one" : "one"
>"two" : "two"
>key : string
>x : string

View file

@ -0,0 +1,4 @@
// @target: es5
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string })[x];
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string }).x;

View file

@ -0,0 +1,4 @@
// @target: es6
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string })[x];
(x) => ({ "1": "one", "2": "two" } as { [key: string]: string }).x;