From 8c8e375f53c512d837663e236863fcbe81493bae Mon Sep 17 00:00:00 2001 From: fisker Date: Tue, 11 Mar 2025 17:52:06 +0800 Subject: [PATCH 01/14] Upgrade --- package.json | 2 +- yarn.lock | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 08acecd8..ef217ff4 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "release": "yarn build && standard-version" }, "devDependencies": { - "@angular/compiler": "19.2.1", + "@angular/compiler": "20.0.0-next.1", "@babel/code-frame": "7.26.2", "@babel/parser": "7.26.9", "@babel/types": "7.26.9", diff --git a/yarn.lock b/yarn.lock index b457a970..e8a0011a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15,17 +15,17 @@ __metadata: languageName: node linkType: hard -"@angular/compiler@npm:19.2.1": - version: 19.2.1 - resolution: "@angular/compiler@npm:19.2.1" +"@angular/compiler@npm:20.0.0-next.1": + version: 20.0.0-next.1 + resolution: "@angular/compiler@npm:20.0.0-next.1" dependencies: tslib: "npm:^2.3.0" peerDependencies: - "@angular/core": 19.2.1 + "@angular/core": 20.0.0-next.1 peerDependenciesMeta: "@angular/core": optional: true - checksum: 10/24d094e6f6653e20bd554a1b38488b6e6f752ec65491dd77135fc8b7ac03020f64ed967e21fd9ea38a5e644e7e90e84cf8da24d31ef905944cbafa34c05a31bb + checksum: 10/b391d6eeda17b6a9277dcc20bed551e270fe3a5d190446fdf3325f25c80f00f2fff2d464879ce8ffeafe596f93b4c4c51fd317a58403d647367b727b2e523ec1 languageName: node linkType: hard @@ -989,7 +989,7 @@ __metadata: version: 0.0.0-use.local resolution: "angular-estree-parser@workspace:." dependencies: - "@angular/compiler": "npm:19.2.1" + "@angular/compiler": "npm:20.0.0-next.1" "@babel/code-frame": "npm:7.26.2" "@babel/parser": "npm:7.26.9" "@babel/types": "npm:7.26.9" From 5252c54eec8c23ab2759a120bf7b28f94f414ba3 Mon Sep 17 00:00:00 2001 From: fisker Date: Tue, 11 Mar 2025 17:52:36 +0800 Subject: [PATCH 02/14] Support `VoidExpression` --- src/transform-node.ts | 22 +++++-- tests/transform.test.ts | 141 ++++++++++++++++++++-------------------- 2 files changed, 88 insertions(+), 75 deletions(-) diff --git a/src/transform-node.ts b/src/transform-node.ts index 7847db0c..c3d410e6 100644 --- a/src/transform-node.ts +++ b/src/transform-node.ts @@ -427,20 +427,31 @@ class Transformer extends Source { ); } - const isPrefixNot = node instanceof angular.PrefixNot; - if (isPrefixNot || node instanceof angular.TypeofExpression) { + if ( + node instanceof angular.PrefixNot || + node instanceof angular.TypeofExpression || + node instanceof angular.VoidExpression + ) { const expression = this.#transform(node.expression); - const operator = isPrefixNot ? '!' : 'typeof'; + const operator = + node instanceof angular.PrefixNot + ? '!' + : node instanceof angular.TypeofExpression + ? 'typeof' + : node instanceof angular.VoidExpression + ? 'void' + : undefined; + let { start } = node.sourceSpan; - if (!isPrefixNot) { + if (operator === 'typeof' || operator === 'void') { const index = this.text.lastIndexOf(operator, start); // istanbul ignore next 7 if (index === -1) { throw new Error( - `Cannot find operator ${operator} from index ${start} in ${JSON.stringify( + `Cannot find operator '${operator}' from index ${start} in ${JSON.stringify( this.text, )}`, ); @@ -619,6 +630,7 @@ type SupportedNodes = | angular.EmptyExpr | angular.PrefixNot | angular.TypeofExpression + | angular.VoidExpression | angular.TemplateLiteral; // Including `TemplateLiteralElement` function transform(node: SupportedNodes, text: string): NGNode { return new Transformer(node, text).node; diff --git a/tests/transform.test.ts b/tests/transform.test.ts index 70401353..4a0c4d1d 100644 --- a/tests/transform.test.ts +++ b/tests/transform.test.ts @@ -26,76 +26,77 @@ const PARSE_METHODS = [ ] as const; describe.each` - expectedAngularType | expectedEstreeType | text | parseAction | parseBinding | parseSimpleBinding | parseInterpolationExpression - ${'Binary'} | ${'BinaryExpression'} | ${' 0 - 1 '} | ${true} | ${true} | ${true} | ${true} - ${'Binary'} | ${'LogicalExpression'} | ${' a && b '} | ${true} | ${true} | ${true} | ${true} - ${'Binary'} | ${'LogicalExpression'} | ${' a ?? b '} | ${true} | ${true} | ${true} | ${true} - ${'Unary'} | ${'UnaryExpression'} | ${' - 1 '} | ${true} | ${true} | ${true} | ${true} - ${'Unary'} | ${'UnaryExpression'} | ${' + 1 '} | ${true} | ${true} | ${true} | ${true} - ${'BindingPipe'} | ${'NGPipeExpression'} | ${' a | b '} | ${false} | ${true} | ${false} | ${true} - ${'BindingPipe'} | ${'NGPipeExpression'} | ${' a | b : c '} | ${false} | ${true} | ${false} | ${true} - ${'Chain'} | ${'NGChainedExpression'} | ${' a ; b '} | ${true} | ${false} | ${false} | ${false} - ${'Conditional'} | ${'ConditionalExpression'} | ${' a ? 1 : 2 '} | ${true} | ${true} | ${true} | ${true} - ${'EmptyExpr'} | ${'NGEmptyExpression'} | ${''} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' ( a . b ) ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' ( a . b )?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' ( a ) ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' ( a )?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' a ( 1 ) ( 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ( 1 )?.( 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'KeyedRead'} | ${'MemberExpression'} | ${' a [ b ] '} | ${true} | ${true} | ${true} | ${true} - ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. [ b ] '} | ${true} | ${true} | ${true} | ${true} - ${'KeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b [ c ] '} | ${true} | ${true} | ${true} | ${true} - ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b ?. [ c ] '} | ${true} | ${true} | ${true} | ${true} - ${'KeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b () [ c ] '} | ${true} | ${true} | ${true} | ${true} - ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b () ?. [ c ] '} | ${true} | ${true} | ${true} | ${true} - ${'KeyedWrite'} | ${'AssignmentExpression'} | ${' a [ b ] = 1 '} | ${true} | ${true} | ${true} | ${true} - ${'ImplicitReceiver'} | ${'ThisExpression'} | ${' this '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralArray'} | ${'ArrayExpression'} | ${' [ 1 ] '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { "a" : 1 } )'} | ${true} | ${true} | ${true} | ${true} - ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { a : 1 } ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' f ( { a : 1 } ) '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( {a, b: 2} ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' f ( {a, b: 2} ) '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( {a, b} ) '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { a, b} ) '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'BooleanLiteral'} | ${' true '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'Identifier'} | ${' undefined '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'NullLiteral'} | ${' null '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'NumericLiteral'} | ${' ( 1 ) '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'NumericLiteral'} | ${' 1 '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'StringLiteral'} | ${' ( "hello" ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' a ( this ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?.( this ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' a ( b) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?.( b) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' a . b ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a . b ?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' a ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b . c ( ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b . c ?. ( ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) . c ( ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) . c ?.( ) '} | ${true} | ${true} | ${true} | ${true} - ${'NonNullAssert'} | ${'TSNonNullExpression'} | ${' x ! '} | ${true} | ${true} | ${true} | ${true} - ${'PrefixNot'} | ${'UnaryExpression'} | ${' ! x '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'Identifier'} | ${' ( ( a ) ) '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'Identifier'} | ${' a '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'Identifier'} | ${' a // hello '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'MemberExpression'} | ${' a . b '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'MemberExpression'} | ${' this . a '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b . c '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b ( ) . c '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyWrite'} | ${'AssignmentExpression'} | ${' a . b = 1 '} | ${true} | ${false} | ${false} | ${false} - ${'PropertyWrite'} | ${'AssignmentExpression'} | ${' a = 1 '} | ${true} | ${false} | ${false} | ${false} - ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b ?. ( ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafePropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b '} | ${true} | ${true} | ${true} | ${true} - ${'TypeofExpression'} | ${'UnaryExpression'} | ${' typeof {} '} | ${true} | ${true} | ${true} | ${true} - ${'Binary'} | ${'BinaryExpression'} | ${' typeof {} === "object" '} | ${true} | ${true} | ${true} | ${true} - ${'PrefixNot'} | ${'UnaryExpression'} | ${' ! ( typeof {} === "number" ) '} | ${true} | ${true} | ${true} | ${true} - ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ` a ${ b } \u0063 ` '} | ${true} | ${true} | ${true} | ${true} - ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ( ` a ${ b } \u0063 ` ) '} | ${true} | ${true} | ${true} | ${true} + expectedAngularType | expectedEstreeType | text | parseAction | parseBinding | parseSimpleBinding | parseInterpolationExpression + ${'Binary'} | ${'BinaryExpression'} | ${' 0 - 1 '} | ${true} | ${true} | ${true} | ${true} + ${'Binary'} | ${'LogicalExpression'} | ${' a && b '} | ${true} | ${true} | ${true} | ${true} + ${'Binary'} | ${'LogicalExpression'} | ${' a ?? b '} | ${true} | ${true} | ${true} | ${true} + ${'Unary'} | ${'UnaryExpression'} | ${' - 1 '} | ${true} | ${true} | ${true} | ${true} + ${'Unary'} | ${'UnaryExpression'} | ${' + 1 '} | ${true} | ${true} | ${true} | ${true} + ${'BindingPipe'} | ${'NGPipeExpression'} | ${' a | b '} | ${false} | ${true} | ${false} | ${true} + ${'BindingPipe'} | ${'NGPipeExpression'} | ${' a | b : c '} | ${false} | ${true} | ${false} | ${true} + ${'Chain'} | ${'NGChainedExpression'} | ${' a ; b '} | ${true} | ${false} | ${false} | ${false} + ${'Conditional'} | ${'ConditionalExpression'} | ${' a ? 1 : 2 '} | ${true} | ${true} | ${true} | ${true} + ${'EmptyExpr'} | ${'NGEmptyExpression'} | ${''} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' ( a . b ) ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' ( a . b )?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' ( a ) ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' ( a )?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' a ( 1 ) ( 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ( 1 )?.( 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'KeyedRead'} | ${'MemberExpression'} | ${' a [ b ] '} | ${true} | ${true} | ${true} | ${true} + ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. [ b ] '} | ${true} | ${true} | ${true} | ${true} + ${'KeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b [ c ] '} | ${true} | ${true} | ${true} | ${true} + ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b ?. [ c ] '} | ${true} | ${true} | ${true} | ${true} + ${'KeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b () [ c ] '} | ${true} | ${true} | ${true} | ${true} + ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b () ?. [ c ] '} | ${true} | ${true} | ${true} | ${true} + ${'KeyedWrite'} | ${'AssignmentExpression'} | ${' a [ b ] = 1 '} | ${true} | ${true} | ${true} | ${true} + ${'ImplicitReceiver'} | ${'ThisExpression'} | ${' this '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralArray'} | ${'ArrayExpression'} | ${' [ 1 ] '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { "a" : 1 } )'} | ${true} | ${true} | ${true} | ${true} + ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { a : 1 } ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' f ( { a : 1 } ) '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( {a, b: 2} ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' f ( {a, b: 2} ) '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( {a, b} ) '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { a, b} ) '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'BooleanLiteral'} | ${' true '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'Identifier'} | ${' undefined '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'NullLiteral'} | ${' null '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'NumericLiteral'} | ${' ( 1 ) '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'NumericLiteral'} | ${' 1 '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'StringLiteral'} | ${' ( "hello" ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' a ( this ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?.( this ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' a ( b) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?.( b) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' a . b ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a . b ?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' a ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b . c ( ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b . c ?. ( ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) . c ( ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) . c ?.( ) '} | ${true} | ${true} | ${true} | ${true} + ${'NonNullAssert'} | ${'TSNonNullExpression'} | ${' x ! '} | ${true} | ${true} | ${true} | ${true} + ${'PrefixNot'} | ${'UnaryExpression'} | ${' ! x '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'Identifier'} | ${' ( ( a ) ) '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'Identifier'} | ${' a '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'Identifier'} | ${' a // hello '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'MemberExpression'} | ${' a . b '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'MemberExpression'} | ${' this . a '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b . c '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b ( ) . c '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyWrite'} | ${'AssignmentExpression'} | ${' a . b = 1 '} | ${true} | ${false} | ${false} | ${false} + ${'PropertyWrite'} | ${'AssignmentExpression'} | ${' a = 1 '} | ${true} | ${false} | ${false} | ${false} + ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b ?. ( ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafePropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b '} | ${true} | ${true} | ${true} | ${true} + ${'TypeofExpression'} | ${'UnaryExpression'} | ${' ( ( typeof {} ) ) '} | ${true} | ${true} | ${true} | ${true} + ${'Binary'} | ${'BinaryExpression'} | ${' typeof {} === "object" '} | ${true} | ${true} | ${true} | ${true} + ${'PrefixNot'} | ${'UnaryExpression'} | ${' ! ( typeof {} === "number" ) '} | ${true} | ${true} | ${true} | ${true} + ${'VoidExpression'} | ${'UnaryExpression'} | ${' ( ( void ( handleMousedown() ) ) ) '} | ${true} | ${true} | ${true} | ${true} + ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ` a ${ b } \u0063 ` '} | ${true} | ${true} | ${true} | ${true} + ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ( ( ` a ${ b } \u0063 ` ) ) '} | ${true} | ${true} | ${true} | ${true} `('($expectedAngularType -> $expectedEstreeType)', (fields) => { for (const method of PARSE_METHODS) { testSection(method, fields); From a4e7666f82832418940a26fc2dfd0399717e08b3 Mon Sep 17 00:00:00 2001 From: fisker Date: Tue, 11 Mar 2025 17:59:33 +0800 Subject: [PATCH 03/14] Support `TaggedTemplateLiteral` --- src/transform-node.ts | 12 +++- tests/transform.test.ts | 144 ++++++++++++++++++++-------------------- 2 files changed, 84 insertions(+), 72 deletions(-) diff --git a/src/transform-node.ts b/src/transform-node.ts index c3d410e6..2b1c3fd0 100644 --- a/src/transform-node.ts +++ b/src/transform-node.ts @@ -550,6 +550,15 @@ class Transformer extends Source { ); } + if (node instanceof angular.TaggedTemplateLiteral) { + return this.#create({ + type: 'TaggedTemplateExpression', + tag: this.#transform(node.tag), + quasi: this.#transform(node.template), + ...node.sourceSpan, + }); + } + if (node instanceof angular.TemplateLiteral) { const { elements, expressions } = node; @@ -631,7 +640,8 @@ type SupportedNodes = | angular.PrefixNot | angular.TypeofExpression | angular.VoidExpression - | angular.TemplateLiteral; // Including `TemplateLiteralElement` + | angular.TemplateLiteral // Including `TemplateLiteralElement` + | angular.TaggedTemplateLiteral; function transform(node: SupportedNodes, text: string): NGNode { return new Transformer(node, text).node; } diff --git a/tests/transform.test.ts b/tests/transform.test.ts index 4a0c4d1d..66fe869d 100644 --- a/tests/transform.test.ts +++ b/tests/transform.test.ts @@ -26,77 +26,79 @@ const PARSE_METHODS = [ ] as const; describe.each` - expectedAngularType | expectedEstreeType | text | parseAction | parseBinding | parseSimpleBinding | parseInterpolationExpression - ${'Binary'} | ${'BinaryExpression'} | ${' 0 - 1 '} | ${true} | ${true} | ${true} | ${true} - ${'Binary'} | ${'LogicalExpression'} | ${' a && b '} | ${true} | ${true} | ${true} | ${true} - ${'Binary'} | ${'LogicalExpression'} | ${' a ?? b '} | ${true} | ${true} | ${true} | ${true} - ${'Unary'} | ${'UnaryExpression'} | ${' - 1 '} | ${true} | ${true} | ${true} | ${true} - ${'Unary'} | ${'UnaryExpression'} | ${' + 1 '} | ${true} | ${true} | ${true} | ${true} - ${'BindingPipe'} | ${'NGPipeExpression'} | ${' a | b '} | ${false} | ${true} | ${false} | ${true} - ${'BindingPipe'} | ${'NGPipeExpression'} | ${' a | b : c '} | ${false} | ${true} | ${false} | ${true} - ${'Chain'} | ${'NGChainedExpression'} | ${' a ; b '} | ${true} | ${false} | ${false} | ${false} - ${'Conditional'} | ${'ConditionalExpression'} | ${' a ? 1 : 2 '} | ${true} | ${true} | ${true} | ${true} - ${'EmptyExpr'} | ${'NGEmptyExpression'} | ${''} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' ( a . b ) ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' ( a . b )?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' ( a ) ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' ( a )?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' a ( 1 ) ( 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ( 1 )?.( 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'KeyedRead'} | ${'MemberExpression'} | ${' a [ b ] '} | ${true} | ${true} | ${true} | ${true} - ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. [ b ] '} | ${true} | ${true} | ${true} | ${true} - ${'KeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b [ c ] '} | ${true} | ${true} | ${true} | ${true} - ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b ?. [ c ] '} | ${true} | ${true} | ${true} | ${true} - ${'KeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b () [ c ] '} | ${true} | ${true} | ${true} | ${true} - ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b () ?. [ c ] '} | ${true} | ${true} | ${true} | ${true} - ${'KeyedWrite'} | ${'AssignmentExpression'} | ${' a [ b ] = 1 '} | ${true} | ${true} | ${true} | ${true} - ${'ImplicitReceiver'} | ${'ThisExpression'} | ${' this '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralArray'} | ${'ArrayExpression'} | ${' [ 1 ] '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { "a" : 1 } )'} | ${true} | ${true} | ${true} | ${true} - ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { a : 1 } ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' f ( { a : 1 } ) '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( {a, b: 2} ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' f ( {a, b: 2} ) '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( {a, b} ) '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { a, b} ) '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'BooleanLiteral'} | ${' true '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'Identifier'} | ${' undefined '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'NullLiteral'} | ${' null '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'NumericLiteral'} | ${' ( 1 ) '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'NumericLiteral'} | ${' 1 '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'StringLiteral'} | ${' ( "hello" ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' a ( this ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?.( this ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' a ( b) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?.( b) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' a . b ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a . b ?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' a ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b . c ( ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b . c ?. ( ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) . c ( ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) . c ?.( ) '} | ${true} | ${true} | ${true} | ${true} - ${'NonNullAssert'} | ${'TSNonNullExpression'} | ${' x ! '} | ${true} | ${true} | ${true} | ${true} - ${'PrefixNot'} | ${'UnaryExpression'} | ${' ! x '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'Identifier'} | ${' ( ( a ) ) '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'Identifier'} | ${' a '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'Identifier'} | ${' a // hello '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'MemberExpression'} | ${' a . b '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'MemberExpression'} | ${' this . a '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b . c '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b ( ) . c '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyWrite'} | ${'AssignmentExpression'} | ${' a . b = 1 '} | ${true} | ${false} | ${false} | ${false} - ${'PropertyWrite'} | ${'AssignmentExpression'} | ${' a = 1 '} | ${true} | ${false} | ${false} | ${false} - ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b ?. ( ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafePropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b '} | ${true} | ${true} | ${true} | ${true} - ${'TypeofExpression'} | ${'UnaryExpression'} | ${' ( ( typeof {} ) ) '} | ${true} | ${true} | ${true} | ${true} - ${'Binary'} | ${'BinaryExpression'} | ${' typeof {} === "object" '} | ${true} | ${true} | ${true} | ${true} - ${'PrefixNot'} | ${'UnaryExpression'} | ${' ! ( typeof {} === "number" ) '} | ${true} | ${true} | ${true} | ${true} - ${'VoidExpression'} | ${'UnaryExpression'} | ${' ( ( void ( handleMousedown() ) ) ) '} | ${true} | ${true} | ${true} | ${true} - ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ` a ${ b } \u0063 ` '} | ${true} | ${true} | ${true} | ${true} - ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ( ( ` a ${ b } \u0063 ` ) ) '} | ${true} | ${true} | ${true} | ${true} + expectedAngularType | expectedEstreeType | text | parseAction | parseBinding | parseSimpleBinding | parseInterpolationExpression + ${'Binary'} | ${'BinaryExpression'} | ${' 0 - 1 '} | ${true} | ${true} | ${true} | ${true} + ${'Binary'} | ${'LogicalExpression'} | ${' a && b '} | ${true} | ${true} | ${true} | ${true} + ${'Binary'} | ${'LogicalExpression'} | ${' a ?? b '} | ${true} | ${true} | ${true} | ${true} + ${'Unary'} | ${'UnaryExpression'} | ${' - 1 '} | ${true} | ${true} | ${true} | ${true} + ${'Unary'} | ${'UnaryExpression'} | ${' + 1 '} | ${true} | ${true} | ${true} | ${true} + ${'BindingPipe'} | ${'NGPipeExpression'} | ${' a | b '} | ${false} | ${true} | ${false} | ${true} + ${'BindingPipe'} | ${'NGPipeExpression'} | ${' a | b : c '} | ${false} | ${true} | ${false} | ${true} + ${'Chain'} | ${'NGChainedExpression'} | ${' a ; b '} | ${true} | ${false} | ${false} | ${false} + ${'Conditional'} | ${'ConditionalExpression'} | ${' a ? 1 : 2 '} | ${true} | ${true} | ${true} | ${true} + ${'EmptyExpr'} | ${'NGEmptyExpression'} | ${''} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' ( a . b ) ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' ( a . b )?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' ( a ) ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' ( a )?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' a ( 1 ) ( 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ( 1 )?.( 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'KeyedRead'} | ${'MemberExpression'} | ${' a [ b ] '} | ${true} | ${true} | ${true} | ${true} + ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. [ b ] '} | ${true} | ${true} | ${true} | ${true} + ${'KeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b [ c ] '} | ${true} | ${true} | ${true} | ${true} + ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b ?. [ c ] '} | ${true} | ${true} | ${true} | ${true} + ${'KeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b () [ c ] '} | ${true} | ${true} | ${true} | ${true} + ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b () ?. [ c ] '} | ${true} | ${true} | ${true} | ${true} + ${'KeyedWrite'} | ${'AssignmentExpression'} | ${' a [ b ] = 1 '} | ${true} | ${true} | ${true} | ${true} + ${'ImplicitReceiver'} | ${'ThisExpression'} | ${' this '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralArray'} | ${'ArrayExpression'} | ${' [ 1 ] '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { "a" : 1 } )'} | ${true} | ${true} | ${true} | ${true} + ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { a : 1 } ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' f ( { a : 1 } ) '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( {a, b: 2} ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' f ( {a, b: 2} ) '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( {a, b} ) '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { a, b} ) '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'BooleanLiteral'} | ${' true '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'Identifier'} | ${' undefined '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'NullLiteral'} | ${' null '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'NumericLiteral'} | ${' ( 1 ) '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'NumericLiteral'} | ${' 1 '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'StringLiteral'} | ${' ( "hello" ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' a ( this ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?.( this ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' a ( b) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?.( b) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' a . b ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a . b ?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' a ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b . c ( ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b . c ?. ( ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) . c ( ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) . c ?.( ) '} | ${true} | ${true} | ${true} | ${true} + ${'NonNullAssert'} | ${'TSNonNullExpression'} | ${' x ! '} | ${true} | ${true} | ${true} | ${true} + ${'PrefixNot'} | ${'UnaryExpression'} | ${' ! x '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'Identifier'} | ${' ( ( a ) ) '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'Identifier'} | ${' a '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'Identifier'} | ${' a // hello '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'MemberExpression'} | ${' a . b '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'MemberExpression'} | ${' this . a '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b . c '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b ( ) . c '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyWrite'} | ${'AssignmentExpression'} | ${' a . b = 1 '} | ${true} | ${false} | ${false} | ${false} + ${'PropertyWrite'} | ${'AssignmentExpression'} | ${' a = 1 '} | ${true} | ${false} | ${false} | ${false} + ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b ?. ( ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafePropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b '} | ${true} | ${true} | ${true} | ${true} + ${'TypeofExpression'} | ${'UnaryExpression'} | ${' ( ( typeof {} ) ) '} | ${true} | ${true} | ${true} | ${true} + ${'Binary'} | ${'BinaryExpression'} | ${' typeof {} === "object" '} | ${true} | ${true} | ${true} | ${true} + ${'PrefixNot'} | ${'UnaryExpression'} | ${' ! ( typeof {} === "number" ) '} | ${true} | ${true} | ${true} | ${true} + ${'VoidExpression'} | ${'UnaryExpression'} | ${' ( ( void ( handleMousedown() ) ) ) '} | ${true} | ${true} | ${true} | ${true} + ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ` a ${ b } \u0063 ` '} | ${true} | ${true} | ${true} | ${true} + ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ( ( ` a ${ b } \u0063 ` ) ) '} | ${true} | ${true} | ${true} | ${true} + ${'TaggedTemplateLiteral'} | ${'TaggedTemplateExpression'} | ${' tag ` a ${ b } \u0063 ` '} | ${true} | ${true} | ${true} | ${true} + ${'TaggedTemplateLiteral'} | ${'TaggedTemplateExpression'} | ${' ( ( ( ( tag ) ) ` a ${ b } \u0063 ` ) ) '} | ${true} | ${true} | ${true} | ${true} `('($expectedAngularType -> $expectedEstreeType)', (fields) => { for (const method of PARSE_METHODS) { testSection(method, fields); From c473f069bd96a0691491d53fa491aa7f56d8bb53 Mon Sep 17 00:00:00 2001 From: fisker Date: Tue, 11 Mar 2025 18:00:32 +0800 Subject: [PATCH 04/14] Bump range --- package.json | 2 +- yarn.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index ef217ff4..4051ef43 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "vitest": "3.0.8" }, "peerDependencies": { - "@angular/compiler": "^19.0.0" + "@angular/compiler": "^19.0.0 || ^20.0.0" }, "engines": { "node": ">= 20" diff --git a/yarn.lock b/yarn.lock index e8a0011a..5d4096b0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1011,7 +1011,7 @@ __metadata: typescript-eslint: "npm:8.26.1" vitest: "npm:3.0.8" peerDependencies: - "@angular/compiler": ^19.0.0 + "@angular/compiler": ^19.0.0 || ^20.0.0 languageName: unknown linkType: soft From b5a7c097492dbd0f36ddc0ee0b4328c33d2b2909 Mon Sep 17 00:00:00 2001 From: fisker Date: Tue, 11 Mar 2025 18:03:15 +0800 Subject: [PATCH 05/14] Shorter tests --- tests/transform.test.ts | 146 ++++++++++++++++++++-------------------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/tests/transform.test.ts b/tests/transform.test.ts index 66fe869d..21be4ab3 100644 --- a/tests/transform.test.ts +++ b/tests/transform.test.ts @@ -26,79 +26,79 @@ const PARSE_METHODS = [ ] as const; describe.each` - expectedAngularType | expectedEstreeType | text | parseAction | parseBinding | parseSimpleBinding | parseInterpolationExpression - ${'Binary'} | ${'BinaryExpression'} | ${' 0 - 1 '} | ${true} | ${true} | ${true} | ${true} - ${'Binary'} | ${'LogicalExpression'} | ${' a && b '} | ${true} | ${true} | ${true} | ${true} - ${'Binary'} | ${'LogicalExpression'} | ${' a ?? b '} | ${true} | ${true} | ${true} | ${true} - ${'Unary'} | ${'UnaryExpression'} | ${' - 1 '} | ${true} | ${true} | ${true} | ${true} - ${'Unary'} | ${'UnaryExpression'} | ${' + 1 '} | ${true} | ${true} | ${true} | ${true} - ${'BindingPipe'} | ${'NGPipeExpression'} | ${' a | b '} | ${false} | ${true} | ${false} | ${true} - ${'BindingPipe'} | ${'NGPipeExpression'} | ${' a | b : c '} | ${false} | ${true} | ${false} | ${true} - ${'Chain'} | ${'NGChainedExpression'} | ${' a ; b '} | ${true} | ${false} | ${false} | ${false} - ${'Conditional'} | ${'ConditionalExpression'} | ${' a ? 1 : 2 '} | ${true} | ${true} | ${true} | ${true} - ${'EmptyExpr'} | ${'NGEmptyExpression'} | ${''} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' ( a . b ) ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' ( a . b )?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' ( a ) ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' ( a )?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' a ( 1 ) ( 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ( 1 )?.( 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'KeyedRead'} | ${'MemberExpression'} | ${' a [ b ] '} | ${true} | ${true} | ${true} | ${true} - ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. [ b ] '} | ${true} | ${true} | ${true} | ${true} - ${'KeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b [ c ] '} | ${true} | ${true} | ${true} | ${true} - ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b ?. [ c ] '} | ${true} | ${true} | ${true} | ${true} - ${'KeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b () [ c ] '} | ${true} | ${true} | ${true} | ${true} - ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b () ?. [ c ] '} | ${true} | ${true} | ${true} | ${true} - ${'KeyedWrite'} | ${'AssignmentExpression'} | ${' a [ b ] = 1 '} | ${true} | ${true} | ${true} | ${true} - ${'ImplicitReceiver'} | ${'ThisExpression'} | ${' this '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralArray'} | ${'ArrayExpression'} | ${' [ 1 ] '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { "a" : 1 } )'} | ${true} | ${true} | ${true} | ${true} - ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { a : 1 } ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' f ( { a : 1 } ) '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( {a, b: 2} ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' f ( {a, b: 2} ) '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( {a, b} ) '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { a, b} ) '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'BooleanLiteral'} | ${' true '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'Identifier'} | ${' undefined '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'NullLiteral'} | ${' null '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'NumericLiteral'} | ${' ( 1 ) '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'NumericLiteral'} | ${' 1 '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'StringLiteral'} | ${' ( "hello" ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' a ( this ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?.( this ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' a ( b) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?.( b) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' a . b ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a . b ?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' a ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b . c ( ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b . c ?. ( ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) . c ( ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) . c ?.( ) '} | ${true} | ${true} | ${true} | ${true} - ${'NonNullAssert'} | ${'TSNonNullExpression'} | ${' x ! '} | ${true} | ${true} | ${true} | ${true} - ${'PrefixNot'} | ${'UnaryExpression'} | ${' ! x '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'Identifier'} | ${' ( ( a ) ) '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'Identifier'} | ${' a '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'Identifier'} | ${' a // hello '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'MemberExpression'} | ${' a . b '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'MemberExpression'} | ${' this . a '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b . c '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b ( ) . c '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyWrite'} | ${'AssignmentExpression'} | ${' a . b = 1 '} | ${true} | ${false} | ${false} | ${false} - ${'PropertyWrite'} | ${'AssignmentExpression'} | ${' a = 1 '} | ${true} | ${false} | ${false} | ${false} - ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b ?. ( ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafePropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b '} | ${true} | ${true} | ${true} | ${true} - ${'TypeofExpression'} | ${'UnaryExpression'} | ${' ( ( typeof {} ) ) '} | ${true} | ${true} | ${true} | ${true} - ${'Binary'} | ${'BinaryExpression'} | ${' typeof {} === "object" '} | ${true} | ${true} | ${true} | ${true} - ${'PrefixNot'} | ${'UnaryExpression'} | ${' ! ( typeof {} === "number" ) '} | ${true} | ${true} | ${true} | ${true} - ${'VoidExpression'} | ${'UnaryExpression'} | ${' ( ( void ( handleMousedown() ) ) ) '} | ${true} | ${true} | ${true} | ${true} - ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ` a ${ b } \u0063 ` '} | ${true} | ${true} | ${true} | ${true} - ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ( ( ` a ${ b } \u0063 ` ) ) '} | ${true} | ${true} | ${true} | ${true} - ${'TaggedTemplateLiteral'} | ${'TaggedTemplateExpression'} | ${' tag ` a ${ b } \u0063 ` '} | ${true} | ${true} | ${true} | ${true} - ${'TaggedTemplateLiteral'} | ${'TaggedTemplateExpression'} | ${' ( ( ( ( tag ) ) ` a ${ b } \u0063 ` ) ) '} | ${true} | ${true} | ${true} | ${true} + expectedAngularType | expectedEstreeType | text | parseAction | parseBinding | parseSimpleBinding | parseInterpolationExpression + ${'Binary'} | ${'BinaryExpression'} | ${' 0 - 1 '} | ${true} | ${true} | ${true} | ${true} + ${'Binary'} | ${'LogicalExpression'} | ${' a && b '} | ${true} | ${true} | ${true} | ${true} + ${'Binary'} | ${'LogicalExpression'} | ${' a ?? b '} | ${true} | ${true} | ${true} | ${true} + ${'Unary'} | ${'UnaryExpression'} | ${' - 1 '} | ${true} | ${true} | ${true} | ${true} + ${'Unary'} | ${'UnaryExpression'} | ${' + 1 '} | ${true} | ${true} | ${true} | ${true} + ${'BindingPipe'} | ${'NGPipeExpression'} | ${' a | b '} | ${false} | ${true} | ${false} | ${true} + ${'BindingPipe'} | ${'NGPipeExpression'} | ${' a | b : c '} | ${false} | ${true} | ${false} | ${true} + ${'Chain'} | ${'NGChainedExpression'} | ${' a ; b '} | ${true} | ${false} | ${false} | ${false} + ${'Conditional'} | ${'ConditionalExpression'} | ${' a ? 1 : 2 '} | ${true} | ${true} | ${true} | ${true} + ${'EmptyExpr'} | ${'NGEmptyExpression'} | ${''} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' ( a . b ) ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' ( a . b )?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' ( a ) ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' ( a )?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' a ( 1 ) ( 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ( 1 )?.( 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'KeyedRead'} | ${'MemberExpression'} | ${' a [ b ] '} | ${true} | ${true} | ${true} | ${true} + ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. [ b ] '} | ${true} | ${true} | ${true} | ${true} + ${'KeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b [ c ] '} | ${true} | ${true} | ${true} | ${true} + ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b ?. [ c ] '} | ${true} | ${true} | ${true} | ${true} + ${'KeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b () [ c ] '} | ${true} | ${true} | ${true} | ${true} + ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b () ?. [ c ] '} | ${true} | ${true} | ${true} | ${true} + ${'KeyedWrite'} | ${'AssignmentExpression'} | ${' a [ b ] = 1 '} | ${true} | ${true} | ${true} | ${true} + ${'ImplicitReceiver'} | ${'ThisExpression'} | ${' this '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralArray'} | ${'ArrayExpression'} | ${' [ 1 ] '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { "a" : 1 } )'} | ${true} | ${true} | ${true} | ${true} + ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { a : 1 } ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' f ( { a : 1 } ) '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( {a, b: 2} ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' f ( {a, b: 2} ) '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( {a, b} ) '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { a, b} ) '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'BooleanLiteral'} | ${' true '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'Identifier'} | ${' undefined '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'NullLiteral'} | ${' null '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'NumericLiteral'} | ${' ( 1 ) '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'NumericLiteral'} | ${' 1 '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'StringLiteral'} | ${' ( "hello" ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' a ( this ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?.( this ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' a ( b) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?.( b) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' a . b ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a . b ?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' a ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b . c ( ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b . c ?. ( ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) . c ( ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) . c ?.( ) '} | ${true} | ${true} | ${true} | ${true} + ${'NonNullAssert'} | ${'TSNonNullExpression'} | ${' x ! '} | ${true} | ${true} | ${true} | ${true} + ${'PrefixNot'} | ${'UnaryExpression'} | ${' ! x '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'Identifier'} | ${' ( ( a ) ) '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'Identifier'} | ${' a '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'Identifier'} | ${' a // hello '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'MemberExpression'} | ${' a . b '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'MemberExpression'} | ${' this . a '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b . c '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b ( ) . c '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyWrite'} | ${'AssignmentExpression'} | ${' a . b = 1 '} | ${true} | ${false} | ${false} | ${false} + ${'PropertyWrite'} | ${'AssignmentExpression'} | ${' a = 1 '} | ${true} | ${false} | ${false} | ${false} + ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b ?. ( ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafePropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b '} | ${true} | ${true} | ${true} | ${true} + ${'TypeofExpression'} | ${'UnaryExpression'} | ${' ( ( typeof {} ) ) '} | ${true} | ${true} | ${true} | ${true} + ${'Binary'} | ${'BinaryExpression'} | ${' typeof {} === "object" '} | ${true} | ${true} | ${true} | ${true} + ${'PrefixNot'} | ${'UnaryExpression'} | ${' ! ( typeof {} === "" ) '} | ${true} | ${true} | ${true} | ${true} + ${'VoidExpression'} | ${'UnaryExpression'} | ${' ( ( void ( ( a() ) ) ) ) '} | ${true} | ${true} | ${true} | ${true} + ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ` a ${ b } \u0063 ` '} | ${true} | ${true} | ${true} | ${true} + ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ( ` a ${ b } \u0063 ` ) '} | ${true} | ${true} | ${true} | ${true} + ${'TaggedTemplateLiteral'} | ${'TaggedTemplateExpression'} | ${' tag ` a ${ b } \u0063 ` '} | ${true} | ${true} | ${true} | ${true} + ${'TaggedTemplateLiteral'} | ${'TaggedTemplateExpression'} | ${' ( ( ( ( tag ) ) `` ) ) '} | ${true} | ${true} | ${true} | ${true} `('($expectedAngularType -> $expectedEstreeType)', (fields) => { for (const method of PARSE_METHODS) { testSection(method, fields); From f48b6448a319b29ccbefbfbac12d5ec0d0a301d6 Mon Sep 17 00:00:00 2001 From: fisker Date: Tue, 11 Mar 2025 18:11:10 +0800 Subject: [PATCH 06/14] Minor tweak --- tests/transform.test.ts | 146 ++++++++++++++++++++-------------------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/tests/transform.test.ts b/tests/transform.test.ts index 21be4ab3..a44835bc 100644 --- a/tests/transform.test.ts +++ b/tests/transform.test.ts @@ -26,79 +26,79 @@ const PARSE_METHODS = [ ] as const; describe.each` - expectedAngularType | expectedEstreeType | text | parseAction | parseBinding | parseSimpleBinding | parseInterpolationExpression - ${'Binary'} | ${'BinaryExpression'} | ${' 0 - 1 '} | ${true} | ${true} | ${true} | ${true} - ${'Binary'} | ${'LogicalExpression'} | ${' a && b '} | ${true} | ${true} | ${true} | ${true} - ${'Binary'} | ${'LogicalExpression'} | ${' a ?? b '} | ${true} | ${true} | ${true} | ${true} - ${'Unary'} | ${'UnaryExpression'} | ${' - 1 '} | ${true} | ${true} | ${true} | ${true} - ${'Unary'} | ${'UnaryExpression'} | ${' + 1 '} | ${true} | ${true} | ${true} | ${true} - ${'BindingPipe'} | ${'NGPipeExpression'} | ${' a | b '} | ${false} | ${true} | ${false} | ${true} - ${'BindingPipe'} | ${'NGPipeExpression'} | ${' a | b : c '} | ${false} | ${true} | ${false} | ${true} - ${'Chain'} | ${'NGChainedExpression'} | ${' a ; b '} | ${true} | ${false} | ${false} | ${false} - ${'Conditional'} | ${'ConditionalExpression'} | ${' a ? 1 : 2 '} | ${true} | ${true} | ${true} | ${true} - ${'EmptyExpr'} | ${'NGEmptyExpression'} | ${''} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' ( a . b ) ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' ( a . b )?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' ( a ) ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' ( a )?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' a ( 1 ) ( 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ( 1 )?.( 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'KeyedRead'} | ${'MemberExpression'} | ${' a [ b ] '} | ${true} | ${true} | ${true} | ${true} - ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. [ b ] '} | ${true} | ${true} | ${true} | ${true} - ${'KeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b [ c ] '} | ${true} | ${true} | ${true} | ${true} - ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b ?. [ c ] '} | ${true} | ${true} | ${true} | ${true} - ${'KeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b () [ c ] '} | ${true} | ${true} | ${true} | ${true} - ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b () ?. [ c ] '} | ${true} | ${true} | ${true} | ${true} - ${'KeyedWrite'} | ${'AssignmentExpression'} | ${' a [ b ] = 1 '} | ${true} | ${true} | ${true} | ${true} - ${'ImplicitReceiver'} | ${'ThisExpression'} | ${' this '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralArray'} | ${'ArrayExpression'} | ${' [ 1 ] '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { "a" : 1 } )'} | ${true} | ${true} | ${true} | ${true} - ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { a : 1 } ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' f ( { a : 1 } ) '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( {a, b: 2} ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' f ( {a, b: 2} ) '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( {a, b} ) '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { a, b} ) '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'BooleanLiteral'} | ${' true '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'Identifier'} | ${' undefined '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'NullLiteral'} | ${' null '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'NumericLiteral'} | ${' ( 1 ) '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'NumericLiteral'} | ${' 1 '} | ${true} | ${true} | ${true} | ${true} - ${'LiteralPrimitive'} | ${'StringLiteral'} | ${' ( "hello" ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' a ( this ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?.( this ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' a ( b) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?.( b) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' a . b ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a . b ?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'CallExpression'} | ${' a ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b . c ( ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b . c ?. ( ) '} | ${true} | ${true} | ${true} | ${true} - ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) . c ( ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) . c ?.( ) '} | ${true} | ${true} | ${true} | ${true} - ${'NonNullAssert'} | ${'TSNonNullExpression'} | ${' x ! '} | ${true} | ${true} | ${true} | ${true} - ${'PrefixNot'} | ${'UnaryExpression'} | ${' ! x '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'Identifier'} | ${' ( ( a ) ) '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'Identifier'} | ${' a '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'Identifier'} | ${' a // hello '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'MemberExpression'} | ${' a . b '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'MemberExpression'} | ${' this . a '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b . c '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b ( ) . c '} | ${true} | ${true} | ${true} | ${true} - ${'PropertyWrite'} | ${'AssignmentExpression'} | ${' a . b = 1 '} | ${true} | ${false} | ${false} | ${false} - ${'PropertyWrite'} | ${'AssignmentExpression'} | ${' a = 1 '} | ${true} | ${false} | ${false} | ${false} - ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b ?. ( ) '} | ${true} | ${true} | ${true} | ${true} - ${'SafePropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b '} | ${true} | ${true} | ${true} | ${true} - ${'TypeofExpression'} | ${'UnaryExpression'} | ${' ( ( typeof {} ) ) '} | ${true} | ${true} | ${true} | ${true} - ${'Binary'} | ${'BinaryExpression'} | ${' typeof {} === "object" '} | ${true} | ${true} | ${true} | ${true} - ${'PrefixNot'} | ${'UnaryExpression'} | ${' ! ( typeof {} === "" ) '} | ${true} | ${true} | ${true} | ${true} - ${'VoidExpression'} | ${'UnaryExpression'} | ${' ( ( void ( ( a() ) ) ) ) '} | ${true} | ${true} | ${true} | ${true} - ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ` a ${ b } \u0063 ` '} | ${true} | ${true} | ${true} | ${true} - ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ( ` a ${ b } \u0063 ` ) '} | ${true} | ${true} | ${true} | ${true} - ${'TaggedTemplateLiteral'} | ${'TaggedTemplateExpression'} | ${' tag ` a ${ b } \u0063 ` '} | ${true} | ${true} | ${true} | ${true} - ${'TaggedTemplateLiteral'} | ${'TaggedTemplateExpression'} | ${' ( ( ( ( tag ) ) `` ) ) '} | ${true} | ${true} | ${true} | ${true} + expectedAngularType | expectedEstreeType | text | parseAction | parseBinding | parseSimpleBinding | parseInterpolationExpression + ${'Binary'} | ${'BinaryExpression'} | ${' 0 - 1 '} | ${true} | ${true} | ${true} | ${true} + ${'Binary'} | ${'LogicalExpression'} | ${' a && b '} | ${true} | ${true} | ${true} | ${true} + ${'Binary'} | ${'LogicalExpression'} | ${' a ?? b '} | ${true} | ${true} | ${true} | ${true} + ${'Unary'} | ${'UnaryExpression'} | ${' - 1 '} | ${true} | ${true} | ${true} | ${true} + ${'Unary'} | ${'UnaryExpression'} | ${' + 1 '} | ${true} | ${true} | ${true} | ${true} + ${'BindingPipe'} | ${'NGPipeExpression'} | ${' a | b '} | ${false} | ${true} | ${false} | ${true} + ${'BindingPipe'} | ${'NGPipeExpression'} | ${' a | b : c '} | ${false} | ${true} | ${false} | ${true} + ${'Chain'} | ${'NGChainedExpression'} | ${' a ; b '} | ${true} | ${false} | ${false} | ${false} + ${'Conditional'} | ${'ConditionalExpression'} | ${' a ? 1 : 2 '} | ${true} | ${true} | ${true} | ${true} + ${'EmptyExpr'} | ${'NGEmptyExpression'} | ${''} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' ( a . b ) ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' ( a . b )?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' ( a ) ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' ( a )?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' a ( 1 ) ( 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ( 1 )?.( 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'KeyedRead'} | ${'MemberExpression'} | ${' a [ b ] '} | ${true} | ${true} | ${true} | ${true} + ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. [ b ] '} | ${true} | ${true} | ${true} | ${true} + ${'KeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b [ c ] '} | ${true} | ${true} | ${true} | ${true} + ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b ?. [ c ] '} | ${true} | ${true} | ${true} | ${true} + ${'KeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b () [ c ] '} | ${true} | ${true} | ${true} | ${true} + ${'SafeKeyedRead'} | ${'OptionalMemberExpression'} | ${' a ?. b () ?. [ c ] '} | ${true} | ${true} | ${true} | ${true} + ${'KeyedWrite'} | ${'AssignmentExpression'} | ${' a [ b ] = 1 '} | ${true} | ${true} | ${true} | ${true} + ${'ImplicitReceiver'} | ${'ThisExpression'} | ${' this '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralArray'} | ${'ArrayExpression'} | ${' [ 1 ] '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { "a" : 1 } )'} | ${true} | ${true} | ${true} | ${true} + ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { a : 1 } ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' f ( { a : 1 } ) '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( {a, b: 2} ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' f ( {a, b: 2} ) '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( {a, b} ) '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralMap'} | ${'ObjectExpression'} | ${' ( { a, b} ) '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'BooleanLiteral'} | ${' true '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'Identifier'} | ${' undefined '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'NullLiteral'} | ${' null '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'NumericLiteral'} | ${' ( 1 ) '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'NumericLiteral'} | ${' 1 '} | ${true} | ${true} | ${true} | ${true} + ${'LiteralPrimitive'} | ${'StringLiteral'} | ${' ( "hello" ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' a ( this ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?.( this ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' a ( b) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?.( b) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' a . b ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a . b ?.( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'CallExpression'} | ${' a ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. ( 1 , 2 ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b . c ( ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b . c ?. ( ) '} | ${true} | ${true} | ${true} | ${true} + ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) . c ( ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) . c ?.( ) '} | ${true} | ${true} | ${true} | ${true} + ${'NonNullAssert'} | ${'TSNonNullExpression'} | ${' x ! '} | ${true} | ${true} | ${true} | ${true} + ${'PrefixNot'} | ${'UnaryExpression'} | ${' ! x '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'Identifier'} | ${' ( ( a ) ) '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'Identifier'} | ${' a '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'Identifier'} | ${' a // hello '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'MemberExpression'} | ${' a . b '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'MemberExpression'} | ${' this . a '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b . c '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b ( ) . c '} | ${true} | ${true} | ${true} | ${true} + ${'PropertyWrite'} | ${'AssignmentExpression'} | ${' a . b = 1 '} | ${true} | ${false} | ${false} | ${false} + ${'PropertyWrite'} | ${'AssignmentExpression'} | ${' a = 1 '} | ${true} | ${false} | ${false} | ${false} + ${'Call'} | ${'OptionalCallExpression'} | ${' a ?. b ( ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafeCall'} | ${'OptionalCallExpression'} | ${' a ?. b ?. ( ) '} | ${true} | ${true} | ${true} | ${true} + ${'SafePropertyRead'} | ${'OptionalMemberExpression'} | ${' a ?. b '} | ${true} | ${true} | ${true} | ${true} + ${'TypeofExpression'} | ${'UnaryExpression'} | ${' ( ( typeof {} ) ) '} | ${true} | ${true} | ${true} | ${true} + ${'Binary'} | ${'BinaryExpression'} | ${' typeof {} === "object" '} | ${true} | ${true} | ${true} | ${true} + ${'PrefixNot'} | ${'UnaryExpression'} | ${' ! ( typeof {} === "" ) '} | ${true} | ${true} | ${true} | ${true} + ${'VoidExpression'} | ${'UnaryExpression'} | ${' ( ( void ( ( a() ) ) ) ) '} | ${true} | ${true} | ${true} | ${true} + ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ` a ${ b } \\u0063 ` '} | ${true} | ${true} | ${true} | ${true} + ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ( ( ` a ${ b } \\u0063 ` ) ) '} | ${true} | ${true} | ${true} | ${true} + ${'TaggedTemplateLiteral'} | ${'TaggedTemplateExpression'} | ${' tag ` a ${ b } \\u0063 ` '} | ${true} | ${true} | ${true} | ${true} + ${'TaggedTemplateLiteral'} | ${'TaggedTemplateExpression'} | ${' ( ( ( ( tag ) ) ` a ${ b } \\u0063 ` ) ) '} | ${true} | ${true} | ${true} | ${true} `('($expectedAngularType -> $expectedEstreeType)', (fields) => { for (const method of PARSE_METHODS) { testSection(method, fields); From 8c9fa01ed8868edac813622ab165b1033ab7567f Mon Sep 17 00:00:00 2001 From: fisker Date: Tue, 11 Mar 2025 18:14:00 +0800 Subject: [PATCH 07/14] Test `**` --- tests/transform.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/transform.test.ts b/tests/transform.test.ts index a44835bc..fafb9f30 100644 --- a/tests/transform.test.ts +++ b/tests/transform.test.ts @@ -28,6 +28,7 @@ const PARSE_METHODS = [ describe.each` expectedAngularType | expectedEstreeType | text | parseAction | parseBinding | parseSimpleBinding | parseInterpolationExpression ${'Binary'} | ${'BinaryExpression'} | ${' 0 - 1 '} | ${true} | ${true} | ${true} | ${true} + ${'Binary'} | ${'BinaryExpression'} | ${' a ** b '} | ${true} | ${true} | ${true} | ${true} ${'Binary'} | ${'LogicalExpression'} | ${' a && b '} | ${true} | ${true} | ${true} | ${true} ${'Binary'} | ${'LogicalExpression'} | ${' a ?? b '} | ${true} | ${true} | ${true} | ${true} ${'Unary'} | ${'UnaryExpression'} | ${' - 1 '} | ${true} | ${true} | ${true} | ${true} From c50da5e73ba33a87d9ddef6470fd76eea2c34809 Mon Sep 17 00:00:00 2001 From: fisker Date: Tue, 11 Mar 2025 18:18:58 +0800 Subject: [PATCH 08/14] Fix type --- src/transform-node.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/transform-node.ts b/src/transform-node.ts index 2b1c3fd0..d7e4cc61 100644 --- a/src/transform-node.ts +++ b/src/transform-node.ts @@ -553,8 +553,8 @@ class Transformer extends Source { if (node instanceof angular.TaggedTemplateLiteral) { return this.#create({ type: 'TaggedTemplateExpression', - tag: this.#transform(node.tag), - quasi: this.#transform(node.template), + tag: this.#transform(node.tag) as babel.Expression, + quasi: this.#transform(node.template) as babel.TemplateLiteral, ...node.sourceSpan, }); } From d633a9ef1642f3bbda306a1475b32719ad27429a Mon Sep 17 00:00:00 2001 From: fisker Date: Tue, 11 Mar 2025 18:26:07 +0800 Subject: [PATCH 09/14] Fix coverage --- src/transform-node.ts | 20 +++++++++++++------- src/transform-template-binding.ts | 3 ++- src/utils.ts | 1 + vitest.config.ts | 9 ++++----- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/src/transform-node.ts b/src/transform-node.ts index d7e4cc61..7b6fc746 100644 --- a/src/transform-node.ts +++ b/src/transform-node.ts @@ -126,7 +126,7 @@ class Transformer extends Source { if (node instanceof angular.Interpolation) { const { expressions } = node; - // istanbul ignore next 3 + /* c8 ignore next 3 */ if (expressions.length !== 1) { throw new Error("Unexpected 'Interpolation'"); } @@ -373,7 +373,7 @@ class Transformer extends Source { { type: 'Identifier', name: 'undefined', ...node.sourceSpan }, { hasParentParens: isInParentParens }, ); - // istanbul ignore next + /* c8 ignore next 4 */ default: throw new Error( `Unexpected LiteralPrimitive value type ${typeof value}`, @@ -432,8 +432,6 @@ class Transformer extends Source { node instanceof angular.TypeofExpression || node instanceof angular.VoidExpression ) { - const expression = this.#transform(node.expression); - const operator = node instanceof angular.PrefixNot ? '!' @@ -441,14 +439,20 @@ class Transformer extends Source { ? 'typeof' : node instanceof angular.VoidExpression ? 'void' - : undefined; + : /* c8 ignore next */ + undefined; + + /* c8 ignore next 3 */ + if (!operator) { + throw new Error('Unexpected expression.'); + } let { start } = node.sourceSpan; if (operator === 'typeof' || operator === 'void') { const index = this.text.lastIndexOf(operator, start); - // istanbul ignore next 7 + /* c8 ignore next 7 */ if (index === -1) { throw new Error( `Cannot find operator '${operator}' from index ${start} in ${JSON.stringify( @@ -460,6 +464,8 @@ class Transformer extends Source { start = index; } + const expression = this.#transform(node.expression); + return this.#create( { type: 'UnaryExpression', @@ -610,7 +616,7 @@ class Transformer extends Source { ); } - // istanbul ignore next + /* c8 ignore next */ throw new Error(`Unexpected node type '${node.constructor.name}'`); } } diff --git a/src/transform-template-binding.ts b/src/transform-template-binding.ts index 7d4f1f9c..b5699c2c 100644 --- a/src/transform-template-binding.ts +++ b/src/transform-template-binding.ts @@ -168,13 +168,14 @@ class Transformer extends NodeTransformer { }); const lastNode = body.pop()!; - // istanbul ignore else + if (lastNode.type === 'NGMicrosyntaxExpression') { body.push(updateExpressionAlias(lastNode)); } else if (lastNode.type === 'NGMicrosyntaxKeyedExpression') { const expression = updateExpressionAlias(lastNode.expression); body.push(updateSpanEnd({ ...lastNode, expression }, expression.end)); } else { + /* c8 ignore next 2 */ throw new Error(`Unexpected type ${lastNode.type}`); } } else { diff --git a/src/utils.ts b/src/utils.ts index 44189eb4..3d295f60 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -106,6 +106,7 @@ export function getCharacterLastIndex( } } + /* c8 ignore next 4 */ throw new Error( `Cannot find front char ${pattern} from index ${fromIndex} in ${JSON.stringify( text, diff --git a/vitest.config.ts b/vitest.config.ts index a4b25ac1..f74b83c8 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -10,12 +10,11 @@ export default defineConfig({ reporter: ['lcov', 'text'], include: ['src/**/*.ts'], exclude: ['src/index.ts', 'src/helpers.ts', 'src/types.ts'], - // FIXME thresholds: { - branches: 95, - functions: 95, - lines: 95, - statements: 95, + branches: 100, + functions: 100, + lines: 100, + statements: 100, }, }, }, From 26dba94bd3fb59beb4aa2e9bbbfec58b99d5184f Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Wed, 12 Mar 2025 13:22:38 +0800 Subject: [PATCH 10/14] Update vitest.config.ts --- vitest.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vitest.config.ts b/vitest.config.ts index f74b83c8..89d53f64 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -11,7 +11,7 @@ export default defineConfig({ include: ['src/**/*.ts'], exclude: ['src/index.ts', 'src/helpers.ts', 'src/types.ts'], thresholds: { - branches: 100, + branches: 95, functions: 100, lines: 100, statements: 100, From 71c7b166586b3f33b5dacd2ace2291bb4663865f Mon Sep 17 00:00:00 2001 From: fisker Date: Fri, 25 Apr 2025 09:07:34 +0800 Subject: [PATCH 11/14] Update --- tests/transform.test.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/transform.test.ts b/tests/transform.test.ts index 8fa4d105..31647b98 100644 --- a/tests/transform.test.ts +++ b/tests/transform.test.ts @@ -98,8 +98,7 @@ describe.each` ${'VoidExpression'} | ${'UnaryExpression'} | ${' ( ( void ( ( a() ) ) ) ) '} | ${true} | ${true} | ${true} | ${true} ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ` a ${ b } \\u0063 ` '} | ${true} | ${true} | ${true} | ${true} ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ( ( ` a ${ b } \\u0063 ` ) ) '} | ${true} | ${true} | ${true} | ${true} - ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ( ` a ${ b } \u0063 ` ) '} | ${true} | ${true} | ${true} | ${true} - ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ` \u0063 ` '} | ${true} | ${true} | ${true} | ${true} + ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ` \\u0063 ` '} | ${true} | ${true} | ${true} | ${true} ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ( ( ` ` ) ) '} | ${true} | ${true} | ${true} | ${true} ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' `` '} | ${true} | ${true} | ${true} | ${true} ${'TaggedTemplateLiteral'} | ${'TaggedTemplateExpression'} | ${' tag ` a ${ b } \\u0063 ` '} | ${true} | ${true} | ${true} | ${true} From b9c93fb112271682a8552655ae121b4ebeaf97d3 Mon Sep 17 00:00:00 2001 From: fisker Date: Fri, 25 Apr 2025 09:10:27 +0800 Subject: [PATCH 12/14] Fix version range --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3996fd32..096769c9 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "vitest": "3.0.8" }, "peerDependencies": { - "@angular/compiler": "^19.2.2 || ^20.0.0" + "@angular/compiler": ">=19.2.2 || ^20.0.0" }, "engines": { "node": ">= 20" From 2aadfbc387bffe59778d07971595a631041b17a0 Mon Sep 17 00:00:00 2001 From: fisker Date: Fri, 25 Apr 2025 09:13:21 +0800 Subject: [PATCH 13/14] Update --- package.json | 2 +- yarn.lock | 17 ++++++----------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 096769c9..f30dd2ed 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "release": "yarn build && standard-version" }, "devDependencies": { - "@angular/compiler": "20.0.0-next.1", + "@angular/compiler": "20.0.0-next.8", "@babel/code-frame": "7.26.2", "@babel/parser": "7.26.10", "@babel/types": "7.26.10", diff --git a/yarn.lock b/yarn.lock index 7b7871bc..9ab6f971 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15,17 +15,12 @@ __metadata: languageName: node linkType: hard -"@angular/compiler@npm:20.0.0-next.1": - version: 20.0.0-next.1 - resolution: "@angular/compiler@npm:20.0.0-next.1" +"@angular/compiler@npm:20.0.0-next.8": + version: 20.0.0-next.8 + resolution: "@angular/compiler@npm:20.0.0-next.8" dependencies: tslib: "npm:^2.3.0" - peerDependencies: - "@angular/core": 20.0.0-next.1 - peerDependenciesMeta: - "@angular/core": - optional: true - checksum: 10/b391d6eeda17b6a9277dcc20bed551e270fe3a5d190446fdf3325f25c80f00f2fff2d464879ce8ffeafe596f93b4c4c51fd317a58403d647367b727b2e523ec1 + checksum: 10/6ce4a2b5d4dc85d45560675403f07ac9c900ddf696f1c49942865e0fdbfde4319371ee35f525d658fad189b19da8e52cc6998dd1cdd1ed1f05866b39da2f15cd languageName: node linkType: hard @@ -989,7 +984,7 @@ __metadata: version: 0.0.0-use.local resolution: "angular-estree-parser@workspace:." dependencies: - "@angular/compiler": "npm:20.0.0-next.1" + "@angular/compiler": "npm:20.0.0-next.8" "@babel/code-frame": "npm:7.26.2" "@babel/parser": "npm:7.26.10" "@babel/types": "npm:7.26.10" @@ -1011,7 +1006,7 @@ __metadata: typescript-eslint: "npm:8.26.1" vitest: "npm:3.0.8" peerDependencies: - "@angular/compiler": ^19.2.2 || ^20.0.0 + "@angular/compiler": ">=19.2.2 || ^20.0.0" languageName: unknown linkType: soft From adfc78b97dc4e4a20fac80118892d90bf0c40195 Mon Sep 17 00:00:00 2001 From: fisker Date: Fri, 25 Apr 2025 09:24:39 +0800 Subject: [PATCH 14/14] Fix test --- src/transform-node.ts | 7 ++++++- tests/helpers.ts | 8 ++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/transform-node.ts b/src/transform-node.ts index 4f664cb2..12d07810 100644 --- a/src/transform-node.ts +++ b/src/transform-node.ts @@ -605,6 +605,10 @@ class Transformer extends Source { ); } + if (node instanceof angular.ParenthesizedExpression) { + return this.#transformNode(node.expression); + } + /* c8 ignore next */ throw new Error(`Unexpected node type '${node.constructor.name}'`); } @@ -636,7 +640,8 @@ type SupportedNodes = | angular.TypeofExpression | angular.VoidExpression | angular.TemplateLiteral // Including `TemplateLiteralElement` - | angular.TaggedTemplateLiteral; + | angular.TaggedTemplateLiteral + | angular.ParenthesizedExpression; function transform(node: SupportedNodes, text: string): NGNode { return new Transformer(node, text).node; } diff --git a/tests/helpers.ts b/tests/helpers.ts index 148a4512..59bbf585 100644 --- a/tests/helpers.ts +++ b/tests/helpers.ts @@ -169,9 +169,17 @@ const KNOWN_AST_TYPES = [ 'SafePropertyRead', 'ThisReceiver', 'Interpolation', + 'VoidExpression', + 'TemplateLiteral', + 'TaggedTemplateLiteral', + 'ParenthesizedExpression', ] as const; export function getAngularNodeType(node: angular.AST) { + if (node instanceof angular.ParenthesizedExpression) { + return getAngularNodeType(node.expression); + } + return ( KNOWN_AST_TYPES.find((type) => node instanceof angular[type]) ?? node.constructor.name