diff --git a/package.json b/package.json index 6ce356ec..f30dd2ed 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "release": "yarn build && standard-version" }, "devDependencies": { - "@angular/compiler": "19.2.2", + "@angular/compiler": "20.0.0-next.8", "@babel/code-frame": "7.26.2", "@babel/parser": "7.26.10", "@babel/types": "7.26.10", @@ -50,7 +50,7 @@ "vitest": "3.0.8" }, "peerDependencies": { - "@angular/compiler": ">=19.2.2" + "@angular/compiler": ">=19.2.2 || ^20.0.0" }, "engines": { "node": ">= 20" diff --git a/src/transform-node.ts b/src/transform-node.ts index 97a8b4bd..12d07810 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}`, @@ -427,20 +427,35 @@ class Transformer extends Source { ); } - const isPrefixNot = node instanceof angular.PrefixNot; - if (isPrefixNot || node instanceof angular.TypeofExpression) { - const expression = this.#transform(node.expression); + if ( + node instanceof angular.PrefixNot || + node instanceof angular.TypeofExpression || + node instanceof angular.VoidExpression + ) { + const operator = + node instanceof angular.PrefixNot + ? '!' + : node instanceof angular.TypeofExpression + ? 'typeof' + : node instanceof angular.VoidExpression + ? 'void' + : /* c8 ignore next */ + undefined; + + /* c8 ignore next 3 */ + if (!operator) { + throw new Error('Unexpected expression.'); + } - const operator = isPrefixNot ? '!' : 'typeof'; let { start } = node.sourceSpan; - if (!isPrefixNot) { + 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( + `Cannot find operator '${operator}' from index ${start} in ${JSON.stringify( this.text, )}`, ); @@ -449,6 +464,8 @@ class Transformer extends Source { start = index; } + const expression = this.#transform(node.expression); + return this.#create( { type: 'UnaryExpression', @@ -539,6 +556,15 @@ class Transformer extends Source { ); } + if (node instanceof angular.TaggedTemplateLiteral) { + return this.#create({ + type: 'TaggedTemplateExpression', + tag: this.#transform(node.tag) as babel.Expression, + quasi: this.#transform(node.template) as babel.TemplateLiteral, + ...node.sourceSpan, + }); + } + if (node instanceof angular.TemplateLiteral) { const { elements, expressions } = node; @@ -579,7 +605,11 @@ class Transformer extends Source { ); } - // istanbul ignore next + if (node instanceof angular.ParenthesizedExpression) { + return this.#transformNode(node.expression); + } + + /* c8 ignore next */ throw new Error(`Unexpected node type '${node.constructor.name}'`); } } @@ -608,7 +638,10 @@ type SupportedNodes = | angular.EmptyExpr | angular.PrefixNot | angular.TypeofExpression - | angular.TemplateLiteral; // Including `TemplateLiteralElement` + | angular.VoidExpression + | angular.TemplateLiteral // Including `TemplateLiteralElement` + | angular.TaggedTemplateLiteral + | angular.ParenthesizedExpression; function transform(node: SupportedNodes, text: string): NGNode { return new Transformer(node, text).node; } 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/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 diff --git a/tests/transform.test.ts b/tests/transform.test.ts index d44eef2b..31647b98 100644 --- a/tests/transform.test.ts +++ b/tests/transform.test.ts @@ -26,79 +26,83 @@ 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} - ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ` \u0063 ` '} | ${true} | ${true} | ${true} | ${true} - ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' ( ( ` ` ) ) '} | ${true} | ${true} | ${true} | ${true} - ${'TemplateLiteral'} | ${'TemplateLiteral'} | ${' `` '} | ${true} | ${true} | ${true} | ${true} + 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} + ${'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} + ${'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} + ${'TaggedTemplateLiteral'} | ${'TaggedTemplateExpression'} | ${' ( ( ( ( tag ) ) ` a ${ b } \\u0063 ` ) ) '} | ${true} | ${true} | ${true} | ${true} `('($expectedAngularType -> $expectedEstreeType)', (fields) => { for (const method of PARSE_METHODS) { testSection(method, fields); diff --git a/vitest.config.ts b/vitest.config.ts index a4b25ac1..89d53f64 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, + functions: 100, + lines: 100, + statements: 100, }, }, }, diff --git a/yarn.lock b/yarn.lock index 4f5ce1f9..9ab6f971 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15,17 +15,12 @@ __metadata: languageName: node linkType: hard -"@angular/compiler@npm:19.2.2": - version: 19.2.2 - resolution: "@angular/compiler@npm:19.2.2" +"@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": 19.2.2 - peerDependenciesMeta: - "@angular/core": - optional: true - checksum: 10/2c427e4e4696f8ce357e432a517d12a0730f9cbdb1306b5be49f9d4f7bd54b76442cfaba8f82579152bc814402e5f666bb5092c994f43c3022bb9a93e8d64db6 + 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:19.2.2" + "@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" + "@angular/compiler": ">=19.2.2 || ^20.0.0" languageName: unknown linkType: soft