From e0515858954a2a14cc2e4f8f6db0ee2db1384c92 Mon Sep 17 00:00:00 2001 From: Dylan Hunn Date: Tue, 5 Dec 2023 21:03:18 -0800 Subject: [PATCH] refactor(compiler): Support unary ops in template pipeline Template Pipeline can now ingest and emit unary ops, such as `+` and `-`. --- .../test_cases/r3_view_compiler/TEST_CASES.json | 17 +++++++++++++++++ .../test_cases/r3_view_compiler/operators.ts | 15 +++++++++++++++ .../r3_view_compiler/operators_template.js | 8 ++++++++ .../src/template/pipeline/ir/src/expression.ts | 2 ++ .../src/template/pipeline/src/ingest.ts | 13 ++++++++++++- 5 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 packages/compiler-cli/test/compliance/test_cases/r3_view_compiler/operators.ts create mode 100644 packages/compiler-cli/test/compliance/test_cases/r3_view_compiler/operators_template.js diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler/TEST_CASES.json b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler/TEST_CASES.json index 9167bba39aa632..aed83968a2bb9f 100644 --- a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler/TEST_CASES.json +++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler/TEST_CASES.json @@ -17,6 +17,23 @@ "failureMessage": "Incorrect template" } ] + }, + { + "description": "should handle binary and unary operators", + "inputFiles": [ + "operators.ts" + ], + "expectations": [ + { + "files": [ + { + "expected": "operators_template.js", + "generated": "operators.js" + } + ], + "failureMessage": "Incorrect template" + } + ] } ] } diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler/operators.ts b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler/operators.ts new file mode 100644 index 00000000000000..6c6b08283c6d7f --- /dev/null +++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler/operators.ts @@ -0,0 +1,15 @@ +import {Component, NgModule} from '@angular/core'; + +@Component({ + template: ` + {{ 1 + 2 }} + {{ (1 % 2) + 3 / 4 * 5 }} + {{ +1 }} +` +}) +export class MyApp { +} + +@NgModule({declarations: [MyApp]}) +export class MyModule { +} diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler/operators_template.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler/operators_template.js new file mode 100644 index 00000000000000..c1a3d7fb87d60d --- /dev/null +++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler/operators_template.js @@ -0,0 +1,8 @@ +template: function MyApp_Template(rf, $ctx$) { + if (rf & 1) { + $i0$.ɵɵtext(0); + } if (rf & 2) { + i0.ɵɵtextInterpolate3(" ", 1 + 2, " ", 1 % 2 + 3 / 4 * 5, " ", +1, "\n"); + } + } + \ No newline at end of file diff --git a/packages/compiler/src/template/pipeline/ir/src/expression.ts b/packages/compiler/src/template/pipeline/ir/src/expression.ts index 53650cb62f2f15..143a21a7bdbd28 100644 --- a/packages/compiler/src/template/pipeline/ir/src/expression.ts +++ b/packages/compiler/src/template/pipeline/ir/src/expression.ts @@ -1043,6 +1043,8 @@ export function transformExpressionsInExpression( } else if (expr instanceof o.BinaryOperatorExpr) { expr.lhs = transformExpressionsInExpression(expr.lhs, transform, flags); expr.rhs = transformExpressionsInExpression(expr.rhs, transform, flags); + } else if (expr instanceof o.UnaryOperatorExpr) { + expr.expr = transformExpressionsInExpression(expr.expr, transform, flags); } else if (expr instanceof o.ReadPropExpr) { expr.receiver = transformExpressionsInExpression(expr.receiver, transform, flags); } else if (expr instanceof o.ReadKeyExpr) { diff --git a/packages/compiler/src/template/pipeline/src/ingest.ts b/packages/compiler/src/template/pipeline/src/ingest.ts index f267424e5067e8..90843c73cc7935 100644 --- a/packages/compiler/src/template/pipeline/src/ingest.ts +++ b/packages/compiler/src/template/pipeline/src/ingest.ts @@ -637,7 +637,18 @@ function convertAst( } else if (ast instanceof e.LiteralPrimitive) { return o.literal(ast.value, undefined, convertSourceSpan(ast.span, baseSourceSpan)); } else if (ast instanceof e.Unary) { - throw new Error('TODO: Support unary operations, which extend binary ops'); + switch (ast.operator) { + case '+': + return new o.UnaryOperatorExpr( + o.UnaryOperator.Plus, convertAst(ast.expr, job, baseSourceSpan), undefined, + convertSourceSpan(ast.span, baseSourceSpan)); + case '-': + return new o.UnaryOperatorExpr( + o.UnaryOperator.Minus, convertAst(ast.expr, job, baseSourceSpan), undefined, + convertSourceSpan(ast.span, baseSourceSpan)); + default: + throw new Error(`AssertionError: unknown unary operator ${ast.operator}`); + } } else if (ast instanceof e.Binary) { const operator = BINARY_OPERATORS.get(ast.operation); if (operator === undefined) {