mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
refactor(migrations): speed up reference resolution in templates (#58106)
Instead of inspecting all types of property accesses, we can use a similar optimization we did for TS references— leveraging the list of known field names to minimize type checker calls. PR Close #58106
This commit is contained in:
parent
03af45540c
commit
37483926ea
4 changed files with 33 additions and 5 deletions
|
|
@ -38,6 +38,7 @@ export function identifyHostBindingReferences<D extends ClassFieldDescriptor>(
|
|||
reflector: ReflectionHost,
|
||||
result: ReferenceResult<D>,
|
||||
knownFields: KnownFields<D>,
|
||||
fieldNamesToConsiderForReferenceLookup: Set<string> | null,
|
||||
) {
|
||||
if (node.name === undefined) {
|
||||
return;
|
||||
|
|
@ -97,6 +98,7 @@ export function identifyHostBindingReferences<D extends ClassFieldDescriptor>(
|
|||
null,
|
||||
node,
|
||||
knownFields,
|
||||
fieldNamesToConsiderForReferenceLookup,
|
||||
);
|
||||
|
||||
for (const [rawName, expression] of hostMap.entries()) {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import {absoluteFrom} from '@angular/compiler-cli/src/ngtsc/file_system';
|
|||
import {PartialEvaluator} from '@angular/compiler-cli/src/ngtsc/partial_evaluator';
|
||||
import {ClassDeclaration, ReflectionHost} from '@angular/compiler-cli/src/ngtsc/reflection';
|
||||
import {CompilationMode} from '@angular/compiler-cli/src/ngtsc/transform';
|
||||
import {TemplateTypeChecker} from '@angular/compiler-cli/src/ngtsc/typecheck/api';
|
||||
import {OptimizeFor, TemplateTypeChecker} from '@angular/compiler-cli/src/ngtsc/typecheck/api';
|
||||
import ts from 'typescript';
|
||||
import {ProgramInfo, projectFile} from '../../../../../utils/tsurge';
|
||||
import {TemplateReferenceVisitor} from './template_reference_visitor';
|
||||
|
|
@ -38,9 +38,10 @@ export function identifyTemplateReferences<D extends ClassFieldDescriptor>(
|
|||
options: NgCompilerOptions,
|
||||
result: ReferenceResult<D>,
|
||||
knownFields: KnownFields<D>,
|
||||
fieldNamesToConsiderForReferenceLookup: Set<string> | null,
|
||||
) {
|
||||
const template =
|
||||
templateTypeChecker.getTemplate(node) ??
|
||||
templateTypeChecker.getTemplate(node, OptimizeFor.WholeProgram) ??
|
||||
// If there is no template registered in the TCB or compiler, the template may
|
||||
// be skipped due to an explicit `jit: true` setting. We try to detect this case
|
||||
// and parse the template manually.
|
||||
|
|
@ -54,7 +55,13 @@ export function identifyTemplateReferences<D extends ClassFieldDescriptor>(
|
|||
);
|
||||
|
||||
if (template !== null) {
|
||||
const visitor = new TemplateReferenceVisitor(checker, templateTypeChecker, node, knownFields);
|
||||
const visitor = new TemplateReferenceVisitor(
|
||||
checker,
|
||||
templateTypeChecker,
|
||||
node,
|
||||
knownFields,
|
||||
fieldNamesToConsiderForReferenceLookup,
|
||||
);
|
||||
template.forEach((node) => node.visit(visitor));
|
||||
|
||||
for (const res of visitor.result) {
|
||||
|
|
@ -67,7 +74,7 @@ export function identifyTemplateReferences<D extends ClassFieldDescriptor>(
|
|||
if (templateFilePath === '') {
|
||||
// TODO: Incorporate a TODO potentially.
|
||||
console.error(
|
||||
`Found reference to input ${res.targetField.key} that cannot be ` +
|
||||
`Found reference to field ${res.targetField.key} that cannot be ` +
|
||||
`migrated because the template cannot be parsed with source map information ` +
|
||||
`(in file: ${node.getSourceFile().fileName}).`,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -79,11 +79,20 @@ export function createFindAllSourceFileReferencesVisitor<D extends ClassFieldDes
|
|||
programInfo.userOptions,
|
||||
result,
|
||||
knownFields,
|
||||
fieldNamesToConsiderForReferenceLookup,
|
||||
);
|
||||
perfCounters.template += (currentTimeInMs() - lastTime) / 1000;
|
||||
lastTime = currentTimeInMs();
|
||||
|
||||
identifyHostBindingReferences(node, programInfo, checker, reflector, result, knownFields);
|
||||
identifyHostBindingReferences(
|
||||
node,
|
||||
programInfo,
|
||||
checker,
|
||||
reflector,
|
||||
result,
|
||||
knownFields,
|
||||
fieldNamesToConsiderForReferenceLookup,
|
||||
);
|
||||
|
||||
perfCounters.hostBindings += (currentTimeInMs() - lastTime) / 1000;
|
||||
lastTime = currentTimeInMs();
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ export class TemplateReferenceVisitor<
|
|||
templateTypeChecker: TemplateTypeChecker,
|
||||
componentClass: ts.ClassDeclaration,
|
||||
knownFields: KnownFields<D>,
|
||||
fieldNamesToConsiderForReferenceLookup: Set<string> | null,
|
||||
) {
|
||||
super();
|
||||
this.expressionVisitor = new TemplateExpressionReferenceVisitor(
|
||||
|
|
@ -88,6 +89,7 @@ export class TemplateReferenceVisitor<
|
|||
templateTypeChecker,
|
||||
componentClass,
|
||||
knownFields,
|
||||
fieldNamesToConsiderForReferenceLookup,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -244,6 +246,7 @@ export class TemplateExpressionReferenceVisitor<
|
|||
private templateTypeChecker: TemplateTypeChecker | null,
|
||||
private componentClass: ts.ClassDeclaration,
|
||||
private knownFields: KnownFields<D>,
|
||||
private fieldNamesToConsiderForReferenceLookup: Set<string> | null,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
|
@ -294,6 +297,13 @@ export class TemplateExpressionReferenceVisitor<
|
|||
* a known field. If so, the result is captured.
|
||||
*/
|
||||
private _inspectPropertyAccess(ast: PropertyRead | PropertyWrite, astPath: AST[]) {
|
||||
if (
|
||||
this.fieldNamesToConsiderForReferenceLookup !== null &&
|
||||
!this.fieldNamesToConsiderForReferenceLookup.has(ast.name)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isWrite = !!(
|
||||
ast instanceof PropertyWrite ||
|
||||
(this.activeTmplAstNode && isTwoWayBindingNode(this.activeTmplAstNode))
|
||||
|
|
|
|||
Loading…
Reference in a new issue