Skip to content

Commit 92c4123

Browse files
crisbetoatscott
authored andcommitted
refactor(compiler): integrate new AST nodes into visitors (#60724)
Updates the various visitors to add placeholders for the new AST nodes. PR Close #60724
1 parent 42039b7 commit 92c4123

File tree

7 files changed

+110
-4
lines changed

7 files changed

+110
-4
lines changed

packages/compiler-cli/src/ngtsc/indexer/src/template.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@ import {
1818
TmplAstBoundDeferredTrigger,
1919
TmplAstBoundEvent,
2020
TmplAstBoundText,
21+
TmplAstComponent,
2122
TmplAstDeferredBlock,
2223
TmplAstDeferredBlockError,
2324
TmplAstDeferredBlockLoading,
2425
TmplAstDeferredBlockPlaceholder,
2526
TmplAstDeferredTrigger,
27+
TmplAstDirective,
2628
TmplAstElement,
2729
TmplAstForLoopBlock,
2830
TmplAstForLoopBlockEmpty,
@@ -242,6 +244,7 @@ class TemplateVisitor extends TmplAstRecursiveVisitor {
242244
this.visitAll(element.references);
243245
this.visitAll(element.inputs);
244246
this.visitAll(element.attributes);
247+
this.visitAll(element.directives);
245248
this.visitAll(element.children);
246249
this.visitAll(element.outputs);
247250
}
@@ -253,6 +256,7 @@ class TemplateVisitor extends TmplAstRecursiveVisitor {
253256
this.identifiers.add(templateIdentifier);
254257
}
255258

259+
this.visitAll(template.directives);
256260
this.visitAll(template.variables);
257261
this.visitAll(template.attributes);
258262
this.visitAll(template.templateAttrs);
@@ -363,6 +367,14 @@ class TemplateVisitor extends TmplAstRecursiveVisitor {
363367
this.visitExpression(decl.value);
364368
}
365369

370+
override visitComponent(component: TmplAstComponent): void {
371+
throw new Error('TODO');
372+
}
373+
374+
override visitDirective(directive: TmplAstDirective): void {
375+
throw new Error('TODO');
376+
}
377+
366378
/** Creates an identifier for a template element or template node. */
367379
private elementOrTemplateToIdentifier(
368380
node: TmplAstElement | TmplAstTemplate,

packages/compiler-cli/src/ngtsc/typecheck/extended/api/api.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@ import {
1515
TmplAstBoundDeferredTrigger,
1616
TmplAstBoundEvent,
1717
TmplAstBoundText,
18+
TmplAstComponent,
1819
TmplAstContent,
1920
TmplAstDeferredBlock,
2021
TmplAstDeferredBlockError,
2122
TmplAstDeferredBlockLoading,
2223
TmplAstDeferredBlockPlaceholder,
2324
TmplAstDeferredTrigger,
25+
TmplAstDirective,
2426
TmplAstElement,
2527
TmplAstForLoopBlock,
2628
TmplAstForLoopBlockEmpty,
@@ -185,6 +187,7 @@ class TemplateVisitor<Code extends ErrorCode>
185187
this.visitAllNodes(element.attributes);
186188
this.visitAllNodes(element.inputs);
187189
this.visitAllNodes(element.outputs);
190+
this.visitAllNodes(element.directives);
188191
this.visitAllNodes(element.references);
189192
this.visitAllNodes(element.children);
190193
}
@@ -201,6 +204,8 @@ class TemplateVisitor<Code extends ErrorCode>
201204
this.visitAllNodes(template.outputs);
202205
}
203206

207+
this.visitAllNodes(template.directives);
208+
204209
// TODO(crisbeto): remove this condition when deleting `canVisitStructuralAttributes`.
205210
if (this.check.canVisitStructuralAttributes || isInlineTemplate) {
206211
// `templateAttrs` aren't transferred over to the inner element so we always have to visit them.
@@ -291,6 +296,22 @@ class TemplateVisitor<Code extends ErrorCode>
291296
this.visitAst(decl.value);
292297
}
293298

299+
visitComponent(component: TmplAstComponent) {
300+
this.visitAllNodes(component.attributes);
301+
this.visitAllNodes(component.inputs);
302+
this.visitAllNodes(component.outputs);
303+
this.visitAllNodes(component.directives);
304+
this.visitAllNodes(component.references);
305+
this.visitAllNodes(component.children);
306+
}
307+
308+
visitDirective(directive: TmplAstDirective) {
309+
this.visitAllNodes(directive.attributes);
310+
this.visitAllNodes(directive.inputs);
311+
this.visitAllNodes(directive.outputs);
312+
this.visitAllNodes(directive.references);
313+
}
314+
294315
getDiagnostics(template: TmplAstNode[]): NgTemplateDiagnostic<Code>[] {
295316
this.diagnostics = [];
296317
this.visitAllNodes(template);

packages/compiler/src/render3/view/t2_binder.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,14 @@ import {
2222
BoundEvent,
2323
BoundText,
2424
Comment,
25+
Component,
2526
Content,
2627
DeferredBlock,
2728
DeferredBlockError,
2829
DeferredBlockLoading,
2930
DeferredBlockPlaceholder,
3031
DeferredTrigger,
32+
Directive,
3133
Element,
3234
ForLoopBlock,
3335
ForLoopBlockEmpty,
@@ -338,6 +340,8 @@ class Scope implements Visitor {
338340
}
339341

340342
visitElement(element: Element) {
343+
element.directives.forEach((node) => node.visit(this));
344+
341345
// `Element`s in the template may have `Reference`s which are captured in the scope.
342346
element.references.forEach((node) => this.visitReference(node));
343347

@@ -348,6 +352,8 @@ class Scope implements Visitor {
348352
}
349353

350354
visitTemplate(template: Template) {
355+
template.directives.forEach((node) => node.visit(this));
356+
351357
// References on a <ng-template> are defined in the outer scope, so capture them before
352358
// processing the template's child scope.
353359
template.references.forEach((node) => this.visitReference(node));
@@ -418,6 +424,14 @@ class Scope implements Visitor {
418424
this.maybeDeclare(decl);
419425
}
420426

427+
visitComponent(component: Component) {
428+
throw new Error('TODO');
429+
}
430+
431+
visitDirective(directive: Directive) {
432+
throw new Error('TODO');
433+
}
434+
421435
// Unused visitors.
422436
visitBoundAttribute(attr: BoundAttribute) {}
423437
visitBoundEvent(event: BoundEvent) {}
@@ -537,6 +551,11 @@ class DirectiveBinder<DirectiveT extends DirectiveMeta> implements Visitor {
537551
// Do this by building up a `CssSelector` for the node.
538552
const cssSelector = createCssSelectorFromNode(node);
539553

554+
// TODO(crisbeto): account for selectorless directives here.
555+
if (node.directives.length > 0) {
556+
throw new Error('TODO');
557+
}
558+
540559
// Next, use the `SelectorMatcher` to get the list of directives on the node.
541560
const directives: DirectiveT[] = [];
542561
this.matcher.match(cssSelector, (_selector, results) => directives.push(...results));
@@ -660,6 +679,14 @@ class DirectiveBinder<DirectiveT extends DirectiveMeta> implements Visitor {
660679
content.children.forEach((child) => child.visit(this));
661680
}
662681

682+
visitComponent(component: Component) {
683+
throw new Error('TODO');
684+
}
685+
686+
visitDirective(directive: Directive) {
687+
throw new Error('TODO');
688+
}
689+
663690
// Unused visitors.
664691
visitVariable(variable: Variable): void {}
665692
visitReference(reference: Reference): void {}
@@ -806,6 +833,7 @@ class TemplateBinder extends RecursiveAstVisitor implements Visitor {
806833
// Visit the inputs, outputs, and children of the element.
807834
element.inputs.forEach(this.visitNode);
808835
element.outputs.forEach(this.visitNode);
836+
element.directives.forEach(this.visitNode);
809837
element.children.forEach(this.visitNode);
810838
element.references.forEach(this.visitNode);
811839
}
@@ -814,6 +842,7 @@ class TemplateBinder extends RecursiveAstVisitor implements Visitor {
814842
// First, visit inputs, outputs and template attributes of the template node.
815843
template.inputs.forEach(this.visitNode);
816844
template.outputs.forEach(this.visitNode);
845+
template.directives.forEach(this.visitNode);
817846
template.templateAttrs.forEach(this.visitNode);
818847
template.references.forEach(this.visitNode);
819848

@@ -835,6 +864,14 @@ class TemplateBinder extends RecursiveAstVisitor implements Visitor {
835864
}
836865
}
837866

867+
visitComponent(component: Component) {
868+
throw new Error('TODO');
869+
}
870+
871+
visitDirective(directive: Directive) {
872+
throw new Error('TODO');
873+
}
874+
838875
// Unused template visitors
839876
visitText(text: Text) {}
840877
visitTextAttribute(attribute: TextAttribute) {}

packages/compiler/test/render3/util/expression.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,12 @@ class ExpressionSourceHumanizer extends e.RecursiveAstVisitor implements t.Visit
137137
}
138138

139139
visitTemplate(ast: t.Template) {
140+
t.visitAll(this, ast.directives);
140141
t.visitAll(this, ast.children);
141142
t.visitAll(this, ast.templateAttrs);
142143
}
143144
visitElement(ast: t.Element) {
145+
t.visitAll(this, ast.directives);
144146
t.visitAll(this, ast.children);
145147
t.visitAll(this, ast.inputs);
146148
t.visitAll(this, ast.outputs);
@@ -231,6 +233,18 @@ class ExpressionSourceHumanizer extends e.RecursiveAstVisitor implements t.Visit
231233
visitLetDeclaration(decl: t.LetDeclaration) {
232234
decl.value.visit(this);
233235
}
236+
237+
visitComponent(ast: t.Component) {
238+
t.visitAll(this, ast.children);
239+
t.visitAll(this, ast.directives);
240+
t.visitAll(this, ast.inputs);
241+
t.visitAll(this, ast.outputs);
242+
}
243+
244+
visitDirective(ast: t.Directive) {
245+
t.visitAll(this, ast.inputs);
246+
t.visitAll(this, ast.outputs);
247+
}
234248
}
235249

236250
/**

packages/compiler/test/render3/view/util.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,11 +105,13 @@ export function findExpression(tmpl: a.Node[], expr: string): e.AST | null {
105105
}
106106

107107
function findExpressionInNode(node: a.Node, expr: string): e.AST | null {
108-
if (node instanceof a.Element || node instanceof a.Template) {
108+
if (node instanceof a.Element || node instanceof a.Template || node instanceof a.Component) {
109109
return findExpression([...node.inputs, ...node.outputs, ...node.children], expr);
110+
} else if (node instanceof a.Directive) {
111+
return findExpression([...node.inputs, ...node.outputs], expr);
110112
} else if (node instanceof a.BoundAttribute || node instanceof a.BoundText) {
111113
const ts = toStringExpression(node.value);
112-
return toStringExpression(node.value) === expr ? node.value : null;
114+
return ts === expr ? node.value : null;
113115
} else if (node instanceof a.BoundEvent) {
114116
return toStringExpression(node.handler) === expr ? node.handler : null;
115117
} else {
@@ -148,12 +150,14 @@ export function parseR3(
148150
preserveWhitespaces?: boolean;
149151
leadingTriviaChars?: string[];
150152
ignoreError?: boolean;
153+
selectorlessEnabled?: boolean;
151154
} = {},
152155
): Render3ParseResult {
153156
const htmlParser = new HtmlParser();
154157
const parseResult = htmlParser.parse(input, 'path:://to/template', {
155158
tokenizeExpansionForms: true,
156159
leadingTriviaChars: options.leadingTriviaChars ?? LEADING_TRIVIA_CHARS,
160+
selectorlessEnabled: options.selectorlessEnabled,
157161
});
158162

159163
if (parseResult.errors.length > 0 && !options.ignoreError) {

packages/core/schematics/utils/template_ast_visitor.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ import type {
3333
TmplAstVariable,
3434
TmplAstUnknownBlock,
3535
TmplAstLetDeclaration,
36+
TmplAstComponent,
37+
TmplAstDirective,
3638
} from '@angular/compiler';
3739

3840
/**
@@ -81,6 +83,8 @@ export class TemplateAstVisitor implements TmplAstRecursiveVisitor {
8183
visitIfBlock(block: TmplAstIfBlock): void {}
8284
visitIfBlockBranch(block: TmplAstIfBlockBranch): void {}
8385
visitLetDeclaration(decl: TmplAstLetDeclaration): void {}
86+
visitComponent(component: TmplAstComponent): void {}
87+
visitDirective(directive: TmplAstDirective): void {}
8488

8589
/**
8690
* Visits all the provided nodes in order using this Visitor's visit methods.

packages/language-service/src/template_target.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@ import {
2121
TmplAstBoundDeferredTrigger,
2222
TmplAstBoundEvent,
2323
TmplAstBoundText,
24+
TmplAstComponent,
2425
TmplAstContent,
2526
TmplAstDeferredBlock,
2627
TmplAstDeferredBlockError,
2728
TmplAstDeferredBlockLoading,
2829
TmplAstDeferredBlockPlaceholder,
2930
TmplAstDeferredTrigger,
31+
TmplAstDirective,
3032
TmplAstElement,
3133
TmplAstForLoopBlock,
3234
TmplAstForLoopBlockEmpty,
@@ -480,7 +482,11 @@ class TemplateTargetVisitor implements TmplAstVisitor {
480482
}
481483

482484
visitElementOrTemplate(element: TmplAstTemplate | TmplAstElement) {
485+
const isTemplate = element instanceof TmplAstTemplate;
483486
this.visitAll(element.attributes);
487+
if (!isTemplate) {
488+
this.visitAll(element.directives);
489+
}
484490
this.visitAll(element.inputs);
485491
// We allow the path to contain both the `TmplAstBoundAttribute` and `TmplAstBoundEvent` for
486492
// two-way bindings but do not want the path to contain both the `TmplAstBoundAttribute` with
@@ -495,11 +501,11 @@ class TemplateTargetVisitor implements TmplAstVisitor {
495501
return;
496502
}
497503
this.visitAll(element.outputs);
498-
if (element instanceof TmplAstTemplate) {
504+
if (isTemplate) {
499505
this.visitAll(element.templateAttrs);
500506
}
501507
this.visitAll(element.references);
502-
if (element instanceof TmplAstTemplate) {
508+
if (isTemplate) {
503509
this.visitAll(element.variables);
504510
}
505511

@@ -620,6 +626,14 @@ class TemplateTargetVisitor implements TmplAstVisitor {
620626
this.visitBinding(decl.value);
621627
}
622628

629+
visitComponent(component: TmplAstComponent) {
630+
throw new Error('TODO');
631+
}
632+
633+
visitDirective(directive: TmplAstDirective) {
634+
throw new Error('TODO');
635+
}
636+
623637
visitAll(nodes: TmplAstNode[]) {
624638
for (const node of nodes) {
625639
this.visit(node);

0 commit comments

Comments
 (0)