From 9ad4bf1dfd77665564273428b4a421dde1439f79 Mon Sep 17 00:00:00 2001 From: Joshua Morony Date: Fri, 1 Mar 2024 20:16:49 +1030 Subject: [PATCH 1/2] fix(convert-signal-inputs): fail gracefully for automatic semicolon insertion issues --- .../__snapshots__/generator.spec.ts.snap | 14 +++++ .../convert-signal-inputs/generator.spec.ts | 16 +++++ .../convert-signal-inputs/generator.ts | 59 +++++++++++-------- 3 files changed, 63 insertions(+), 26 deletions(-) diff --git a/libs/plugin/src/generators/convert-signal-inputs/__snapshots__/generator.spec.ts.snap b/libs/plugin/src/generators/convert-signal-inputs/__snapshots__/generator.spec.ts.snap index b744c6cc..c622829d 100644 --- a/libs/plugin/src/generators/convert-signal-inputs/__snapshots__/generator.spec.ts.snap +++ b/libs/plugin/src/generators/convert-signal-inputs/__snapshots__/generator.spec.ts.snap @@ -229,3 +229,17 @@ exports[`convertSignalInputsGenerator should convert properly for templateUrl 2`

{{ data().normalInput }}

" `; + +exports[`convertSignalInputsGenerator should fail gracefully for issue #290 1`] = ` +" +import { Component } from '@angular/core'; +import { input } from "@angular/core"; + +@Component({}) +export class MyCmp { + inputWithoutType = input(); + noColon = true + inputWithoutType = input();; +} +" +`; diff --git a/libs/plugin/src/generators/convert-signal-inputs/generator.spec.ts b/libs/plugin/src/generators/convert-signal-inputs/generator.spec.ts index 3d09940c..0dd2345a 100644 --- a/libs/plugin/src/generators/convert-signal-inputs/generator.spec.ts +++ b/libs/plugin/src/generators/convert-signal-inputs/generator.spec.ts @@ -180,6 +180,15 @@ export class RequestInfoComponent implements OnInit { this.submitter$.next(); } }`, + issue290: ` +import { Component } from '@angular/core'; + +@Component({}) +export class MyCmp { + @Input() inputWithoutType; + noColon = true +} +`, } as const; describe('convertSignalInputsGenerator', () => { @@ -245,4 +254,11 @@ describe('convertSignalInputsGenerator', () => { const [updated] = readContent(); expect(updated).toMatchSnapshot(); }); + + it('should fail gracefully for issue #290', async () => { + const readContent = setup('issue290'); + await convertSignalInputsGenerator(tree, options); + const [updated] = readContent(); + expect(updated).toMatchSnapshot(); + }); }); diff --git a/libs/plugin/src/generators/convert-signal-inputs/generator.ts b/libs/plugin/src/generators/convert-signal-inputs/generator.ts index 2e35160f..c211b15e 100644 --- a/libs/plugin/src/generators/convert-signal-inputs/generator.ts +++ b/libs/plugin/src/generators/convert-signal-inputs/generator.ts @@ -286,32 +286,39 @@ export async function convertSignalInputsGenerator( targetClass.forEachChild((node) => { if (Node.isPropertyDeclaration(node)) { - const inputDecorator = node.getDecorator('Input'); - if (inputDecorator) { - const { name, isReadonly, docs, scope, hasOverrideKeyword } = - node.getStructure(); - - const newProperty = targetClass.addProperty({ - name, - isReadonly, - docs, - scope, - hasOverrideKeyword, - initializer: getSignalInputInitializer( - contentsStore, - targetClass.getName(), - inputDecorator, - node, - ), - }); - - node.replaceWithText(newProperty.print()); - - // remove old class property Input - newProperty.remove(); - - // track converted inputs - convertedInputs.add(name); + // fail gracefully for nodes not terminated with a semi-colon + try { + const inputDecorator = node.getDecorator('Input'); + if (inputDecorator) { + const { name, isReadonly, docs, scope, hasOverrideKeyword } = + node.getStructure(); + + const newProperty = targetClass.addProperty({ + name, + isReadonly, + docs, + scope, + hasOverrideKeyword, + initializer: getSignalInputInitializer( + contentsStore, + targetClass.getName(), + inputDecorator, + node, + ), + }); + + node.replaceWithText(newProperty.print()); + + // remove old class property Input + newProperty.remove(); + + // track converted inputs + convertedInputs.add(name); + } + } catch (err) { + logger.warn( + `[ngxtension] "${path}" Failed to parse node, consider formatting with prettier and trying again`, + ); } } }); From ee3bccf67e352819576d400bd0d33d8cff41dbe0 Mon Sep 17 00:00:00 2001 From: Joshua Morony Date: Fri, 1 Mar 2024 21:12:52 +1030 Subject: [PATCH 2/2] fix(convert-signal-inputs): throw if parsing failes due to ASI --- .../__snapshots__/generator.spec.ts.snap | 14 ----- .../convert-signal-inputs/generator.spec.ts | 9 +-- .../convert-signal-inputs/generator.ts | 59 ++++++++++--------- 3 files changed, 35 insertions(+), 47 deletions(-) diff --git a/libs/plugin/src/generators/convert-signal-inputs/__snapshots__/generator.spec.ts.snap b/libs/plugin/src/generators/convert-signal-inputs/__snapshots__/generator.spec.ts.snap index c622829d..b744c6cc 100644 --- a/libs/plugin/src/generators/convert-signal-inputs/__snapshots__/generator.spec.ts.snap +++ b/libs/plugin/src/generators/convert-signal-inputs/__snapshots__/generator.spec.ts.snap @@ -229,17 +229,3 @@ exports[`convertSignalInputsGenerator should convert properly for templateUrl 2`

{{ data().normalInput }}

" `; - -exports[`convertSignalInputsGenerator should fail gracefully for issue #290 1`] = ` -" -import { Component } from '@angular/core'; -import { input } from "@angular/core"; - -@Component({}) -export class MyCmp { - inputWithoutType = input(); - noColon = true - inputWithoutType = input();; -} -" -`; diff --git a/libs/plugin/src/generators/convert-signal-inputs/generator.spec.ts b/libs/plugin/src/generators/convert-signal-inputs/generator.spec.ts index 0dd2345a..02f69afc 100644 --- a/libs/plugin/src/generators/convert-signal-inputs/generator.spec.ts +++ b/libs/plugin/src/generators/convert-signal-inputs/generator.spec.ts @@ -255,10 +255,11 @@ describe('convertSignalInputsGenerator', () => { expect(updated).toMatchSnapshot(); }); - it('should fail gracefully for issue #290', async () => { + it('should fail for issue #290', async () => { const readContent = setup('issue290'); - await convertSignalInputsGenerator(tree, options); - const [updated] = readContent(); - expect(updated).toMatchSnapshot(); + await expect(async () => { + await convertSignalInputsGenerator(tree, options); + readContent(); + }).rejects.toThrow(); }); }); diff --git a/libs/plugin/src/generators/convert-signal-inputs/generator.ts b/libs/plugin/src/generators/convert-signal-inputs/generator.ts index c211b15e..dce682c6 100644 --- a/libs/plugin/src/generators/convert-signal-inputs/generator.ts +++ b/libs/plugin/src/generators/convert-signal-inputs/generator.ts @@ -286,39 +286,40 @@ export async function convertSignalInputsGenerator( targetClass.forEachChild((node) => { if (Node.isPropertyDeclaration(node)) { - // fail gracefully for nodes not terminated with a semi-colon - try { - const inputDecorator = node.getDecorator('Input'); - if (inputDecorator) { - const { name, isReadonly, docs, scope, hasOverrideKeyword } = - node.getStructure(); - - const newProperty = targetClass.addProperty({ - name, - isReadonly, - docs, - scope, - hasOverrideKeyword, - initializer: getSignalInputInitializer( - contentsStore, - targetClass.getName(), - inputDecorator, - node, - ), - }); - - node.replaceWithText(newProperty.print()); + const inputDecorator = node.getDecorator('Input'); + if (inputDecorator) { + const { name, isReadonly, docs, scope, hasOverrideKeyword } = + node.getStructure(); + + const newProperty = targetClass.addProperty({ + name, + isReadonly, + docs, + scope, + hasOverrideKeyword, + initializer: getSignalInputInitializer( + contentsStore, + targetClass.getName(), + inputDecorator, + node, + ), + }); + + node.replaceWithText(newProperty.print()); + // fail gracefully for nodes not terminated with a semi-colon + try { // remove old class property Input newProperty.remove(); - - // track converted inputs - convertedInputs.add(name); + } catch (err) { + logger.warn( + `[ngxtension] "${path}" Failed to parse node, check that declarations are terminated with a semicolon and try again`, + ); + throw err; } - } catch (err) { - logger.warn( - `[ngxtension] "${path}" Failed to parse node, consider formatting with prettier and trying again`, - ); + + // track converted inputs + convertedInputs.add(name); } } });