fix(language-service): bound attributes should not break directive matching (#41597)

The language service uses an elements attributes to determine if it
matches a directive in the component scope. We do this by accumulating
all attribute bindings and matching against the selectors for the
available directives. The compiler itself does a similar thing. In
addition, the compiler does not use the value of `BoundAttribute`s to
match directives (cdf1ea1951/packages/compiler/src/render3/view/util.ts (L174-L206)). This commit changes the language
service to also ignore bound attribute values for directive matching.

Fixes https://github.com/angular/vscode-ng-language-service/issues/1278

PR Close #41597
This commit is contained in:
Andrew Scott 2021-04-13 09:38:14 -07:00 committed by Zach Arend
parent fd9a7ca8c9
commit bd34bc9e89
2 changed files with 10 additions and 1 deletions

View File

@ -151,6 +151,15 @@ describe('quick info', () => {
expect(toText(documentation)).toBe('This Component provides the `test-comp` selector.'); expect(toText(documentation)).toBe('This Component provides the `test-comp` selector.');
}); });
it('should work for components with bound attributes', () => {
const {documentation} = expectQuickInfo({
templateOverride: `<t¦est-comp [attr.id]="'1' + '2'" [attr.name]="'myName'"></test-comp>`,
expectedSpanText: `<test-comp [attr.id]="'1' + '2'" [attr.name]="'myName'"></test-comp>`,
expectedDisplayString: '(component) AppModule.TestComponent'
});
expect(toText(documentation)).toBe('This Component provides the `test-comp` selector.');
});
it('should work for structural directives', () => { it('should work for structural directives', () => {
const {documentation} = expectQuickInfo({ const {documentation} = expectQuickInfo({
templateOverride: `<div *¦ngFor="let item of heroes"></div>`, templateOverride: `<div *¦ngFor="let item of heroes"></div>`,

View File

@ -171,7 +171,7 @@ function getFirstComponentForTemplateFile(fileName: string, compiler: NgCompiler
* Given an attribute node, converts it to string form. * Given an attribute node, converts it to string form.
*/ */
function toAttributeString(attribute: t.TextAttribute|t.BoundAttribute|t.BoundEvent): string { function toAttributeString(attribute: t.TextAttribute|t.BoundAttribute|t.BoundEvent): string {
if (attribute instanceof t.BoundEvent) { if (attribute instanceof t.BoundEvent || attribute instanceof t.BoundAttribute) {
return `[${attribute.name}]`; return `[${attribute.name}]`;
} else { } else {
return `[${attribute.name}=${attribute.valueSpan?.toString() ?? ''}]`; return `[${attribute.name}=${attribute.valueSpan?.toString() ?? ''}]`;