From 124305d00780bd24c40e756a239999eee9644553 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 15 Jul 2016 15:56:22 -0700 Subject: [PATCH] Emit parens around type-asserted binary operators Fixes #9766 --- src/compiler/emitter.ts | 3 +- tests/baselines/reference/asOpEmitParens.js | 19 ++++++++++++ .../reference/asOpEmitParens.symbols | 16 ++++++++++ .../baselines/reference/asOpEmitParens.types | 30 +++++++++++++++++++ .../expressions/asOperator/asOpEmitParens.ts | 9 ++++++ 5 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/asOpEmitParens.js create mode 100644 tests/baselines/reference/asOpEmitParens.symbols create mode 100644 tests/baselines/reference/asOpEmitParens.types create mode 100644 tests/cases/conformance/expressions/asOperator/asOpEmitParens.ts diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 101778e7322..682d9b26fe1 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2553,7 +2553,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge operand = (operand).expression; } - // We have an expression of the form: (SubExpr) + // We have an expression of the form: (SubExpr) or (SubExpr as Type) // Emitting this as (SubExpr) is really not desirable. We would like to emit the subexpr as is. // Omitting the parentheses, however, could cause change in the semantics of the generated // code if the casted expression has a lower precedence than the rest of the expression, e.g.: @@ -2567,6 +2567,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge operand.kind !== SyntaxKind.DeleteExpression && operand.kind !== SyntaxKind.PostfixUnaryExpression && operand.kind !== SyntaxKind.NewExpression && + !(operand.kind === SyntaxKind.BinaryExpression && node.expression.kind === SyntaxKind.AsExpression) && !(operand.kind === SyntaxKind.CallExpression && node.parent.kind === SyntaxKind.NewExpression) && !(operand.kind === SyntaxKind.FunctionExpression && node.parent.kind === SyntaxKind.CallExpression) && !(operand.kind === SyntaxKind.NumericLiteral && node.parent.kind === SyntaxKind.PropertyAccessExpression)) { diff --git a/tests/baselines/reference/asOpEmitParens.js b/tests/baselines/reference/asOpEmitParens.js new file mode 100644 index 00000000000..dee8d263eae --- /dev/null +++ b/tests/baselines/reference/asOpEmitParens.js @@ -0,0 +1,19 @@ +//// [asOpEmitParens.ts] +declare var x; +// Must emit as (x + 1) * 3 +(x + 1 as number) * 3; + +// Should still emit as x.y +(x as any).y; + +// Emit as new (x()) +new (x() as any); + + +//// [asOpEmitParens.js] +// Must emit as (x + 1) * 3 +(x + 1) * 3; +// Should still emit as x.y +x.y; +// Emit as new (x()) +new (x()); diff --git a/tests/baselines/reference/asOpEmitParens.symbols b/tests/baselines/reference/asOpEmitParens.symbols new file mode 100644 index 00000000000..210d9f3ea0d --- /dev/null +++ b/tests/baselines/reference/asOpEmitParens.symbols @@ -0,0 +1,16 @@ +=== tests/cases/conformance/expressions/asOperator/asOpEmitParens.ts === +declare var x; +>x : Symbol(x, Decl(asOpEmitParens.ts, 0, 11)) + +// Must emit as (x + 1) * 3 +(x + 1 as number) * 3; +>x : Symbol(x, Decl(asOpEmitParens.ts, 0, 11)) + +// Should still emit as x.y +(x as any).y; +>x : Symbol(x, Decl(asOpEmitParens.ts, 0, 11)) + +// Emit as new (x()) +new (x() as any); +>x : Symbol(x, Decl(asOpEmitParens.ts, 0, 11)) + diff --git a/tests/baselines/reference/asOpEmitParens.types b/tests/baselines/reference/asOpEmitParens.types new file mode 100644 index 00000000000..b87d7f4d91f --- /dev/null +++ b/tests/baselines/reference/asOpEmitParens.types @@ -0,0 +1,30 @@ +=== tests/cases/conformance/expressions/asOperator/asOpEmitParens.ts === +declare var x; +>x : any + +// Must emit as (x + 1) * 3 +(x + 1 as number) * 3; +>(x + 1 as number) * 3 : number +>(x + 1 as number) : number +>x + 1 as number : number +>x + 1 : any +>x : any +>1 : number +>3 : number + +// Should still emit as x.y +(x as any).y; +>(x as any).y : any +>(x as any) : any +>x as any : any +>x : any +>y : any + +// Emit as new (x()) +new (x() as any); +>new (x() as any) : any +>(x() as any) : any +>x() as any : any +>x() : any +>x : any + diff --git a/tests/cases/conformance/expressions/asOperator/asOpEmitParens.ts b/tests/cases/conformance/expressions/asOperator/asOpEmitParens.ts new file mode 100644 index 00000000000..7a97a74168a --- /dev/null +++ b/tests/cases/conformance/expressions/asOperator/asOpEmitParens.ts @@ -0,0 +1,9 @@ +declare var x; +// Must emit as (x + 1) * 3 +(x + 1 as number) * 3; + +// Should still emit as x.y +(x as any).y; + +// Emit as new (x()) +new (x() as any);