From 44039a4b16dcc9a3b9c2430dd5a43629c8f7faf0 Mon Sep 17 00:00:00 2001 From: Ayaz Hafiz Date: Mon, 22 Jul 2019 10:24:43 -0700 Subject: [PATCH] feat(ivy): pass information about used directive selectors on elements (#31782) Extend indexing API interface to provide information about used directives' selectors on template elements. This enables an indexer to xref element attributes to the directives that match them. The current way this matching is done is by mapping selectors to indexed directives. However, this fails in cases where the directive is not indexed by the indexer API, like for transitive dependencies. This solution is much more general. PR Close #31782 --- .../compiler-cli/src/ngtsc/indexer/src/api.ts | 8 +++++++- .../src/ngtsc/indexer/src/template.ts | 7 ++++++- .../src/ngtsc/indexer/test/template_spec.ts | 15 ++++++++++++++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/packages/compiler-cli/src/ngtsc/indexer/src/api.ts b/packages/compiler-cli/src/ngtsc/indexer/src/api.ts index 2841620fab..978d635719 100644 --- a/packages/compiler-cli/src/ngtsc/indexer/src/api.ts +++ b/packages/compiler-cli/src/ngtsc/indexer/src/api.ts @@ -8,6 +8,7 @@ import {ParseSourceFile} from '@angular/compiler'; import * as ts from 'typescript'; +import {ClassDeclaration} from '../../reflection'; /** * Describes the kind of identifier found in a template. @@ -38,6 +39,11 @@ export interface MethodIdentifier extends TemplateIdentifier { kind: IdentifierK /** Describes an element attribute in a template. */ export interface AttributeIdentifier extends TemplateIdentifier { kind: IdentifierKind.Attribute; } +/** A reference to a directive node and its selector. */ +interface DirectiveReference { + node: ClassDeclaration; + selector: string; +} /** * Describes an indexed element in a template. The name of an `ElementIdentifier` is the entire * element tag, which can be parsed by an indexer to determine where used directives should be @@ -50,7 +56,7 @@ export interface ElementIdentifier extends TemplateIdentifier { attributes: Set; /** Directives applied to an element. */ - usedDirectives: Set; + usedDirectives: Set; } /** diff --git a/packages/compiler-cli/src/ngtsc/indexer/src/template.ts b/packages/compiler-cli/src/ngtsc/indexer/src/template.ts index 12f32bc2d4..3b68d15318 100644 --- a/packages/compiler-cli/src/ngtsc/indexer/src/template.ts +++ b/packages/compiler-cli/src/ngtsc/indexer/src/template.ts @@ -157,7 +157,12 @@ class TemplateVisitor extends TmplAstRecursiveVisitor { span: new AbsoluteSourceSpan(start, start + name.length), kind: IdentifierKind.Element, attributes: new Set(attributes), - usedDirectives: new Set(usedDirectives.map(dir => dir.ref.node)), + usedDirectives: new Set(usedDirectives.map(dir => { + return { + node: dir.ref.node, + selector: dir.selector, + }; + })), }; this.identifiers.add(elId); diff --git a/packages/compiler-cli/src/ngtsc/indexer/test/template_spec.ts b/packages/compiler-cli/src/ngtsc/indexer/test/template_spec.ts index 6da72750c6..7f27a7b340 100644 --- a/packages/compiler-cli/src/ngtsc/indexer/test/template_spec.ts +++ b/packages/compiler-cli/src/ngtsc/indexer/test/template_spec.ts @@ -246,7 +246,20 @@ runInEachFileSystem(() => { const refs = getTemplateIdentifiers(boundTemplate); const [ref] = Array.from(refs); const usedDirectives = (ref as ElementIdentifier).usedDirectives; - expect(usedDirectives).toEqual(new Set([declA, declB, declC])); + expect(usedDirectives).toEqual(new Set([ + { + node: declA, + selector: 'a-selector', + }, + { + node: declB, + selector: '[b-selector]', + }, + { + node: declC, + selector: ':not(never-selector)', + } + ])); }); }); });