Skip to content

Commit

Permalink
fix: 🐛 (setters) parse input setters
Browse files Browse the repository at this point in the history
  • Loading branch information
nivekcode committed Mar 13, 2024
1 parent f6d243f commit c014307
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 6 deletions.
23 changes: 23 additions & 0 deletions src/parser/shared/parser/field-decorator.parser.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,27 @@ describe('Field Decorator', function () {
outputs: expectedOutputs,
});
});

it('should parse input setters', () => {
const ast = tsquery.ast(`
export class MyTestClass {
@Input() set myInput(value: string){
console.log(value);
};
}
`);

const expectedInputs = [
{
decorator: '@Input()',
name: 'myInput',
type: 'string',
field: '@Input() set myInput(value: string){\n console.log(value);\n }',
},
];
expect(parseInputsAndOutputs(ast)).toEqual({
inputs: expectedInputs,
outputs: [],
});
});
});
53 changes: 49 additions & 4 deletions src/parser/shared/parser/field-decorator.parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,57 @@ import { NgParselFieldDecorator } from '../model/decorator.model.js';
export function parseInputsAndOutputs(ast: ts.SourceFile): {
inputs: NgParselFieldDecorator[];
outputs: NgParselFieldDecorator[];
} {
return parseDecorators(ast);
}

function parseDecorators(ast: ts.SourceFile): {
inputs: NgParselFieldDecorator[];
outputs: NgParselFieldDecorator[];
} {
const parsedPropertyDeclarations = parseDecoratedPropertyDeclarations(ast);
return {
inputs: [...parseDecoratedSetters(ast), ...parsedPropertyDeclarations.inputs],
outputs: [...parsedPropertyDeclarations.outputs],
};
}

function parseDecoratedSetters(ast: ts.SourceFile): NgParselFieldDecorator[] {
const decoratedSetters = [...tsquery(ast, 'SetAccessor:has(Decorator)')];
const decoratedSettersPropertyDeclaration = [...tsquery(ast, 'SetAccessor:has(Decorator) > Decorator')];

const inputSetters = [];

for (let i = 0; i < decoratedSetters.length; i++) {
const decoratorName = decoratedSettersPropertyDeclaration[i]?.getText();

if (!decoratorName?.startsWith('@Input')) {
continue;
}

const name = (decoratedSetters[i] as any)?.name?.getText();
const type = (decoratedSetters[i] as any)?.parameters[0]?.type?.getText();

inputSetters.push({
decorator: '@Input()',
name,
type,
field: decoratedSetters[i]?.getText() || '',
});
}

return inputSetters;
}

function parseDecoratedPropertyDeclarations(ast: ts.SourceFile): {
inputs: NgParselFieldDecorator[];
outputs: NgParselFieldDecorator[];
} {
/*
This is afaik the only way to get the Decorator name
- getDecorators() returns nothing
- canHaveDecorators() returns false
*/
This is afaik the only way to get the Decorator name
- getDecorators() returns nothing
- canHaveDecorators() returns false
*/
const decoratorPropertyDecorator = [...tsquery(ast, 'PropertyDeclaration:has(Decorator) > Decorator')];
const decoratorPropertyDeclaration = [...tsquery(ast, 'PropertyDeclaration:has(Decorator)')];

Expand Down
10 changes: 8 additions & 2 deletions test-spa/src/app/foo/foo.component.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import {Component, EventEmitter, Input, Output} from "@angular/core";
import { Component, EventEmitter, input, Input, Output } from '@angular/core';

@Component({
selector: 'foo',
templateUrl: './foo.component.html',
styleUrls: ['./foo.styles.scss']
styleUrls: ['./foo.styles.scss'],
})
export class FooComponent {
@Input() test: string | undefined;
@Input() set myValue(value: string) {
console.log(value);
}

name = input<string>('Paul Atreides');

@Output() fooChanged = new EventEmitter();
foo: string | undefined;
}

0 comments on commit c014307

Please sign in to comment.