refactor(compiler-cli): Return symbols for all matching inputs (#40144)
This commit ensures that the template type checker returns symbols for all inputs if an attribute binds to more than one. PR Close #40144
This commit is contained in:
@@ -13,7 +13,7 @@ import {AbsoluteFsPath} from '../../file_system';
|
||||
import {ClassDeclaration} from '../../reflection';
|
||||
import {ComponentScopeReader} from '../../scope';
|
||||
import {isAssignment} from '../../util/src/typescript';
|
||||
import {DirectiveSymbol, DomBindingSymbol, ElementSymbol, ExpressionSymbol, InputBindingSymbol, OutputBindingSymbol, PipeSymbol, ReferenceSymbol, ShimLocation, Symbol, SymbolKind, TemplateSymbol, TsNodeSymbolInfo, TypeCheckableDirectiveMeta, VariableSymbol} from '../api';
|
||||
import {BindingSymbol, DirectiveSymbol, DomBindingSymbol, ElementSymbol, ExpressionSymbol, InputBindingSymbol, OutputBindingSymbol, PipeSymbol, ReferenceSymbol, ShimLocation, Symbol, SymbolKind, TemplateSymbol, TsNodeSymbolInfo, TypeCheckableDirectiveMeta, VariableSymbol} from '../api';
|
||||
|
||||
import {ExpressionIdentifier, findAllMatchingNodes, findFirstMatchingNode, hasExpressionIdentifier} from './comments';
|
||||
import {TemplateData} from './context';
|
||||
@@ -253,31 +253,35 @@ export class SymbolBuilder {
|
||||
return host !== null ? {kind: SymbolKind.DomBinding, host} : null;
|
||||
}
|
||||
|
||||
const node = findFirstMatchingNode(
|
||||
const nodes = findAllMatchingNodes(
|
||||
this.typeCheckBlock, {withSpan: binding.sourceSpan, filter: isAssignment});
|
||||
if (node === null || !isAccessExpression(node.left)) {
|
||||
return null;
|
||||
}
|
||||
const bindings: BindingSymbol[] = [];
|
||||
for (const node of nodes) {
|
||||
if (!isAccessExpression(node.left)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const symbolInfo = this.getSymbolOfTsNode(node.left);
|
||||
if (symbolInfo === null || symbolInfo.tsSymbol === null) {
|
||||
return null;
|
||||
}
|
||||
const symbolInfo = this.getSymbolOfTsNode(node.left);
|
||||
if (symbolInfo === null || symbolInfo.tsSymbol === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const target = this.getDirectiveSymbolForAccessExpression(node.left, consumer);
|
||||
if (target === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
kind: SymbolKind.Input,
|
||||
bindings: [{
|
||||
const target = this.getDirectiveSymbolForAccessExpression(node.left, consumer);
|
||||
if (target === null) {
|
||||
continue;
|
||||
}
|
||||
bindings.push({
|
||||
...symbolInfo,
|
||||
tsSymbol: symbolInfo.tsSymbol,
|
||||
kind: SymbolKind.Binding,
|
||||
target,
|
||||
}],
|
||||
};
|
||||
});
|
||||
}
|
||||
if (bindings.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {kind: SymbolKind.Input, bindings};
|
||||
}
|
||||
|
||||
private getDirectiveSymbolForAccessExpression(
|
||||
|
||||
+7
-7
@@ -1136,7 +1136,7 @@ runInEachFileSystem(() => {
|
||||
.toEqual('TestDir');
|
||||
});
|
||||
|
||||
it('returns the first directive match when two directives have the same input', () => {
|
||||
it('returns the all inputs when two directives have the same input', () => {
|
||||
const fileName = absoluteFrom('/main.ts');
|
||||
const dirFile = absoluteFrom('/dir.ts');
|
||||
const templateString = `<div dir otherDir [inputA]="'my input A'"></div>`;
|
||||
@@ -1178,12 +1178,12 @@ runInEachFileSystem(() => {
|
||||
const inputAbinding = (nodes[0] as TmplAstElement).inputs[0];
|
||||
const symbol = templateTypeChecker.getSymbolOfNode(inputAbinding, cmp)!;
|
||||
assertInputBindingSymbol(symbol);
|
||||
expect(
|
||||
(symbol.bindings[0].tsSymbol!.declarations[0] as ts.PropertyDeclaration).name.getText())
|
||||
.toEqual('inputA');
|
||||
expect((symbol.bindings[0].tsSymbol!.declarations[0] as ts.PropertyDeclaration)
|
||||
.parent.name?.text)
|
||||
.toEqual('TestDir');
|
||||
expect(new Set(symbol.bindings.map(
|
||||
b => (b.tsSymbol!.declarations[0] as ts.PropertyDeclaration).name.getText())))
|
||||
.toEqual(new Set(['inputA', 'otherDirInputA']));
|
||||
expect(new Set(symbol.bindings.map(
|
||||
b => (b.tsSymbol!.declarations[0] as ts.PropertyDeclaration).parent.name?.text)))
|
||||
.toEqual(new Set(['TestDir', 'OtherDir']));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user