Skip to content

Commit f060df5

Browse files
authored
Merge pull request #1549 from sonallux/fix/input-output-signals
fix: input and output signals are listed in properties
2 parents 351b401 + 22a3bc7 commit f060df5

File tree

8 files changed

+575
-270
lines changed

8 files changed

+575
-270
lines changed

src/app/compiler/angular-dependencies.ts

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -252,20 +252,14 @@ export class AngularDependencies extends FrameworkDependencies {
252252
if (IO.constructor && !Configuration.mainData.disableConstructors) {
253253
deps.constructorObj = IO.constructor;
254254
}
255-
if (IO.inputs) {
256-
deps.inputsClass = IO.inputs;
257-
}
258-
if (IO.outputs) {
259-
deps.outputsClass = IO.outputs;
260-
}
255+
deps.inputsClass = IO.inputs ?? [];
256+
deps.outputsClass = IO.outputs ?? [];
261257
if (IO.properties) {
262-
deps.properties = IO.properties;
263-
deps.inputsClass = deps.inputsClass
264-
? deps.inputsClass.concat(this.componentHelper.getInputSignals(IO.properties))
265-
: this.componentHelper.getInputSignals(IO.properties);
266-
deps.outputsClass = deps.outputsClass
267-
? deps.outputsClass.concat(this.componentHelper.getOutputSignals(IO.properties))
268-
: this.componentHelper.getOutputSignals(IO.properties);
258+
const {inputSignals, outputSignals, properties} = this.componentHelper.getInputOutputSignals(IO.properties);
259+
260+
deps.inputsClass = deps.inputsClass.concat(inputSignals)
261+
deps.outputsClass = deps.outputsClass.concat(outputSignals)
262+
deps.propertiesClass = properties;
269263
}
270264
if (IO.description) {
271265
deps.description = IO.description;

src/app/compiler/angular/deps/component-dep.factory.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,11 @@ export class ComponentDepFactory {
8989
componentDep.accessors = IO.accessors;
9090
}
9191
if (IO.properties) {
92-
componentDep.inputsClass = componentDep.inputsClass.concat(
93-
this.helper.getInputSignals(IO.properties)
94-
);
95-
componentDep.outputsClass = componentDep.outputsClass.concat(
96-
this.helper.getOutputSignals(IO.properties)
97-
);
92+
const {inputSignals, outputSignals, properties} = this.helper.getInputOutputSignals(IO.properties);
93+
94+
componentDep.inputsClass = componentDep.inputsClass.concat(inputSignals)
95+
componentDep.outputsClass = componentDep.outputsClass.concat(outputSignals)
96+
componentDep.propertiesClass = properties;
9897
}
9998

10099
return componentDep;

src/app/compiler/angular/deps/directive-dep.factory.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ export class DirectiveDepFactory {
2626

2727
standalone: this.helper.getComponentStandalone(props, srcFile) ? true : false,
2828

29-
inputsClass: this.helper.getInputSignals(IO.properties).concat(IO.inputs),
30-
outputsClass: this.helper.getOutputSignals(IO.properties).concat(IO.outputs),
29+
inputsClass: IO.inputs,
30+
outputsClass: IO.outputs,
3131

3232
deprecated: IO.deprecated,
3333
deprecationMessage: IO.deprecationMessage,
@@ -58,6 +58,13 @@ export class DirectiveDepFactory {
5858
if (IO.accessors) {
5959
directiveDeps.accessors = IO.accessors;
6060
}
61+
if (IO.properties) {
62+
const {inputSignals, outputSignals, properties} = this.helper.getInputOutputSignals(IO.properties);
63+
64+
directiveDeps.inputsClass = directiveDeps.inputsClass.concat(inputSignals)
65+
directiveDeps.outputsClass = directiveDeps.outputsClass.concat(outputSignals)
66+
directiveDeps.propertiesClass = properties;
67+
}
6168
return directiveDeps;
6269
}
6370
}

src/app/compiler/angular/deps/helpers/component-helper.ts

Lines changed: 72 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -135,42 +135,58 @@ export class ComponentHelper {
135135
return this.symbolHelper.getSymbolDeps(props, 'inputs', srcFile);
136136
}
137137

138-
public getInputSignals(props) {
138+
public getInputOutputSignals(props) {
139139
const inputSignals = [];
140-
props?.forEach(prop => {
141-
const config =
142-
this.getSignalConfig('input', prop.defaultValue) ??
143-
this.getSignalConfig('model', prop.defaultValue);
144-
145-
if (config) {
146-
const newInput = {
147-
...prop,
148-
...config
149-
};
140+
const outputSignals = [];
141+
const properties = [];
150142

151-
inputSignals.push(newInput);
143+
props.forEach(prop => {
144+
const inputSignal = this.getInputSignal(prop);
145+
if (inputSignal) {
146+
inputSignals.push(inputSignal)
152147
}
153-
});
154-
return inputSignals;
155-
}
156148

157-
public getOutputSignals(props) {
158-
const outputSignals = [];
159-
props?.forEach(prop => {
160-
const config =
161-
this.getSignalConfig('output', prop.defaultValue) ??
162-
this.getSignalConfig('model', prop.defaultValue);
163-
164-
if (config) {
165-
const newInput = {
166-
...prop,
167-
...config
168-
};
149+
const outputSignal = this.getOutputSignal(prop);
150+
if (outputSignal) {
151+
outputSignals.push(outputSignal)
152+
}
169153

170-
outputSignals.push(newInput);
154+
if (!inputSignal && !outputSignal) {
155+
properties.push(prop)
171156
}
172157
});
173-
return outputSignals;
158+
159+
return {inputSignals, outputSignals, properties}
160+
}
161+
162+
public getInputSignal(prop) {
163+
const config =
164+
this.getSignalConfig('input', prop.defaultValue) ??
165+
this.getSignalConfig('model', prop.defaultValue);
166+
167+
if (config) {
168+
return {
169+
...prop,
170+
...config
171+
};
172+
}
173+
174+
return undefined;
175+
}
176+
177+
public getOutputSignal(prop) {
178+
const config =
179+
this.getSignalConfig('output', prop.defaultValue) ??
180+
this.getSignalConfig('model', prop.defaultValue);
181+
182+
if (config) {
183+
return {
184+
...prop,
185+
...config
186+
};
187+
}
188+
189+
return undefined;
174190
}
175191

176192
private getSignalConfig(type: 'input' | 'output' | 'model', defaultValue: string) {
@@ -204,7 +220,7 @@ export class ComponentHelper {
204220

205221
const result = {
206222
required: !!required,
207-
type,
223+
type: this.parseSignalType(type),
208224
defaultValue
209225
};
210226

@@ -219,6 +235,32 @@ export class ComponentHelper {
219235
}
220236
}
221237

238+
public parseSignalType(type: string) {
239+
if (!type) {
240+
return type;
241+
}
242+
243+
// adjust union string expression like: 'foo' | 'bar' | 'test'
244+
// which should be outputed as: "foo" | "bar" | "test"
245+
246+
const unionTypeRegex = /^'([\w-]+)'\s?\|\s?('([\w-]+)'|.*)$/
247+
let typeRest = type;
248+
let newType = "";
249+
let typeMatch: RegExpMatchArray;
250+
while ((typeMatch = typeRest.match(unionTypeRegex))) {
251+
const [, first, rest, second] = typeMatch;
252+
if (second) {
253+
newType += `"${first}" | "${second}"`;
254+
type = newType;
255+
break;
256+
}
257+
newType += `"${first}" | `;
258+
typeRest = rest;
259+
}
260+
261+
return type;
262+
}
263+
222264
public getComponentStandalone(
223265
props: ReadonlyArray<ts.ObjectLiteralElementLike>,
224266
srcFile: ts.SourceFile

test/fixtures/sample-files/foo.component.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Component, EventEmitter, Input, input, Output, output } from '@angular/core';
1+
import { Component, EventEmitter, Input, input, Output, output, model } from '@angular/core';
22

33
/**
44
* FooComponent description
@@ -44,12 +44,12 @@ export class FooComponent {
4444
/**
4545
* An example aliased input using the object syntax
4646
*/
47-
@Input({ alias: 'aliasedInput' }) objectAliasedInput: string;
47+
@Input({ alias: 'aliasedInputObjectSyntax' }) objectAliasedInput: string;
4848

4949
/**
5050
* An example aliased required input using the object syntax
5151
*/
52-
@Input({ alias: 'aliasedInput', required: true }) aliasedAndRequired: string;
52+
@Input({ alias: 'aliasedAndRequiredInput', required: true }) aliasedAndRequired: string;
5353

5454
/**
5555
* An example output
@@ -86,6 +86,11 @@ export class FooComponent {
8686
*/
8787
public readonly aliasedOutputSignal = output(null, { alias: 'aliasedOutSignal' });
8888

89+
/**
90+
* An example model input signal
91+
*/
92+
public readonly modelInputSignal = model(0);
93+
8994
/**
9095
* constructor description
9196
* @param {boolean} myprop description

test/fixtures/todomvc-ng2/src/app/about/compodoc/compodoc.component.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,10 @@ export class CompodocComponent {
5050
*/
5151

5252
outputSignal = output();
53-
outputSignalWithDefaultValue = output(this.defaultValue);
54-
outputSignalWithDefaultStringValue = output('value');
55-
outputSignalWithAlias = output(0, { alias: 'aliasedSignal' });
53+
outputSignalWithAlias = output({ alias: 'aliasedSignal' });
5654

57-
requiredOutputSignal = output.required();
58-
requiredOutputSignalWithType = output.required<number>();
59-
60-
outputSignalWithType = output<string>('value');
61-
outputSignalWithStringType = output<'value'>('value');
62-
outputSignalWithMultipleTypes = output<string | number>(0);
63-
outputSignalWithMultipleMixedTypes = output<'asc' | 'dsc' | number>('asc');
55+
outputSignalWithType = output<string>();
56+
outputSignalWithStringType = output<'value'>();
57+
outputSignalWithMultipleTypes = output<string | number>();
58+
outputSignalWithMultipleMixedTypes = output<'asc' | 'dsc' | number>();
6459
}

0 commit comments

Comments
 (0)