refactor(ivy): move metadata registration to its own package (#29698)
Previously, metadata registration (the recording of collected metadata during analysis of directives, pipes, and NgModules) was only used to produce the `LocalModuleScope`, and thus was handled by the `LocalModuleScopeRegistry`. However, the template type-checker also needs information about registered directives, outside of the NgModule scope determinations. Rather than reuse the scope registry for an unintended purpose, this commit introduces new abstractions for metadata registration and lookups in a separate 'metadata' package, which the scope registry implements. This paves the way for a future commit to make use of this metadata for the template type-checking system. Testing strategy: this commit is a refactoring which introduces no new functionality, so existing tests are sufficient. PR Close #29698
This commit is contained in:

committed by
Ben Lesh

parent
410151b07f
commit
9277afce61
@ -12,6 +12,7 @@ ts_library(
|
||||
"//packages/compiler-cli/src/ngtsc/cycles",
|
||||
"//packages/compiler-cli/src/ngtsc/diagnostics",
|
||||
"//packages/compiler-cli/src/ngtsc/imports",
|
||||
"//packages/compiler-cli/src/ngtsc/metadata",
|
||||
"//packages/compiler-cli/src/ngtsc/partial_evaluator",
|
||||
"//packages/compiler-cli/src/ngtsc/reflection",
|
||||
"//packages/compiler-cli/src/ngtsc/routing",
|
||||
|
@ -13,9 +13,10 @@ import * as ts from 'typescript';
|
||||
import {CycleAnalyzer} from '../../cycles';
|
||||
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
|
||||
import {DefaultImportRecorder, ModuleResolver, Reference, ReferenceEmitter} from '../../imports';
|
||||
import {DirectiveMeta, MetadataRegistry, extractDirectiveGuards} from '../../metadata';
|
||||
import {EnumValue, PartialEvaluator} from '../../partial_evaluator';
|
||||
import {ClassDeclaration, Decorator, ReflectionHost, filterToMembersWithDecorator, reflectObjectLiteral} from '../../reflection';
|
||||
import {LocalModuleScopeRegistry, ScopeDirective, extractDirectiveGuards} from '../../scope';
|
||||
import {LocalModuleScopeRegistry} from '../../scope';
|
||||
import {AnalysisOutput, CompileResult, DecoratorHandler, DetectResult, HandlerPrecedence, ResolveResult} from '../../transform';
|
||||
import {TypeCheckContext} from '../../typecheck';
|
||||
import {tsSourceMapBug29300Fixed} from '../../util/src/ts_source_map_bug_29300';
|
||||
@ -41,14 +42,14 @@ export class ComponentDecoratorHandler implements
|
||||
DecoratorHandler<ComponentHandlerData, Decorator> {
|
||||
constructor(
|
||||
private reflector: ReflectionHost, private evaluator: PartialEvaluator,
|
||||
private scopeRegistry: LocalModuleScopeRegistry, private isCore: boolean,
|
||||
private resourceLoader: ResourceLoader, private rootDirs: string[],
|
||||
private metaRegistry: MetadataRegistry, private scopeRegistry: LocalModuleScopeRegistry,
|
||||
private isCore: boolean, private resourceLoader: ResourceLoader, private rootDirs: string[],
|
||||
private defaultPreserveWhitespaces: boolean, private i18nUseExternalIds: boolean,
|
||||
private moduleResolver: ModuleResolver, private cycleAnalyzer: CycleAnalyzer,
|
||||
private refEmitter: ReferenceEmitter, private defaultImportRecorder: DefaultImportRecorder) {}
|
||||
|
||||
private literalCache = new Map<Decorator, ts.ObjectLiteralExpression>();
|
||||
private boundTemplateCache = new Map<ts.Declaration, BoundTarget<ScopeDirective>>();
|
||||
private boundTemplateCache = new Map<ts.Declaration, BoundTarget<DirectiveMeta>>();
|
||||
private elementSchemaRegistry = new DomElementSchemaRegistry();
|
||||
|
||||
/**
|
||||
@ -211,7 +212,7 @@ export class ComponentDecoratorHandler implements
|
||||
// determined.
|
||||
if (metadata.selector !== null) {
|
||||
const ref = new Reference(node);
|
||||
this.scopeRegistry.registerDirective({
|
||||
this.metaRegistry.registerDirectiveMetadata({
|
||||
ref,
|
||||
name: node.name.text,
|
||||
selector: metadata.selector,
|
||||
@ -220,6 +221,7 @@ export class ComponentDecoratorHandler implements
|
||||
outputs: metadata.outputs,
|
||||
queries: metadata.queries.map(query => query.propertyName),
|
||||
isComponent: true, ...extractDirectiveGuards(node, this.reflector),
|
||||
baseClass: null,
|
||||
});
|
||||
}
|
||||
|
||||
@ -302,7 +304,7 @@ export class ComponentDecoratorHandler implements
|
||||
return;
|
||||
}
|
||||
const scope = this.scopeRegistry.getScopeForComponent(node);
|
||||
const matcher = new SelectorMatcher<ScopeDirective>();
|
||||
const matcher = new SelectorMatcher<DirectiveMeta>();
|
||||
if (scope !== null) {
|
||||
for (const meta of scope.compilation.directives) {
|
||||
matcher.addSelectables(CssSelector.parse(meta.selector), meta);
|
||||
@ -343,7 +345,7 @@ export class ComponentDecoratorHandler implements
|
||||
// Set up the R3TargetBinder, as well as a 'directives' array and a 'pipes' map that are later
|
||||
// fed to the TemplateDefinitionBuilder. First, a SelectorMatcher is constructed to match
|
||||
// directives that are in scope.
|
||||
const matcher = new SelectorMatcher<ScopeDirective&{expression: Expression}>();
|
||||
const matcher = new SelectorMatcher<DirectiveMeta&{expression: Expression}>();
|
||||
const directives: {selector: string, expression: Expression}[] = [];
|
||||
|
||||
for (const dir of scope.compilation.directives) {
|
||||
|
@ -11,10 +11,11 @@ import * as ts from 'typescript';
|
||||
|
||||
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
|
||||
import {DefaultImportRecorder, Reference} from '../../imports';
|
||||
import {MetadataRegistry} from '../../metadata';
|
||||
import {extractDirectiveGuards} from '../../metadata/src/util';
|
||||
import {DynamicValue, EnumValue, PartialEvaluator} from '../../partial_evaluator';
|
||||
import {ClassDeclaration, ClassMember, ClassMemberKind, Decorator, ReflectionHost, filterToMembersWithDecorator, reflectObjectLiteral} from '../../reflection';
|
||||
import {LocalModuleScopeRegistry} from '../../scope/src/local';
|
||||
import {extractDirectiveGuards} from '../../scope/src/util';
|
||||
import {AnalysisOutput, CompileResult, DecoratorHandler, DetectResult, HandlerPrecedence} from '../../transform';
|
||||
|
||||
import {generateSetClassMetadataCall} from './metadata';
|
||||
@ -30,8 +31,8 @@ export class DirectiveDecoratorHandler implements
|
||||
DecoratorHandler<DirectiveHandlerData, Decorator> {
|
||||
constructor(
|
||||
private reflector: ReflectionHost, private evaluator: PartialEvaluator,
|
||||
private scopeRegistry: LocalModuleScopeRegistry,
|
||||
private defaultImportRecorder: DefaultImportRecorder, private isCore: boolean) {}
|
||||
private metaRegistry: MetadataRegistry, private defaultImportRecorder: DefaultImportRecorder,
|
||||
private isCore: boolean) {}
|
||||
|
||||
readonly precedence = HandlerPrecedence.PRIMARY;
|
||||
|
||||
@ -59,7 +60,7 @@ export class DirectiveDecoratorHandler implements
|
||||
// when this directive appears in an `@NgModule` scope, its selector can be determined.
|
||||
if (analysis && analysis.selector !== null) {
|
||||
const ref = new Reference(node);
|
||||
this.scopeRegistry.registerDirective({
|
||||
this.metaRegistry.registerDirectiveMetadata({
|
||||
ref,
|
||||
name: node.name.text,
|
||||
selector: analysis.selector,
|
||||
@ -68,6 +69,7 @@ export class DirectiveDecoratorHandler implements
|
||||
outputs: analysis.outputs,
|
||||
queries: analysis.queries.map(query => query.propertyName),
|
||||
isComponent: false, ...extractDirectiveGuards(node, this.reflector),
|
||||
baseClass: null,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ import * as ts from 'typescript';
|
||||
|
||||
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
|
||||
import {DefaultImportRecorder, Reference, ReferenceEmitter} from '../../imports';
|
||||
import {MetadataRegistry} from '../../metadata';
|
||||
import {PartialEvaluator, ResolvedValue} from '../../partial_evaluator';
|
||||
import {ClassDeclaration, Decorator, ReflectionHost, reflectObjectLiteral, typeNodeToValueExpr} from '../../reflection';
|
||||
import {NgModuleRouteAnalyzer} from '../../routing';
|
||||
@ -39,7 +40,7 @@ export interface NgModuleAnalysis {
|
||||
export class NgModuleDecoratorHandler implements DecoratorHandler<NgModuleAnalysis, Decorator> {
|
||||
constructor(
|
||||
private reflector: ReflectionHost, private evaluator: PartialEvaluator,
|
||||
private scopeRegistry: LocalModuleScopeRegistry,
|
||||
private metaRegistry: MetadataRegistry, private scopeRegistry: LocalModuleScopeRegistry,
|
||||
private referencesRegistry: ReferencesRegistry, private isCore: boolean,
|
||||
private routeAnalyzer: NgModuleRouteAnalyzer|null, private refEmitter: ReferenceEmitter,
|
||||
private defaultImportRecorder: DefaultImportRecorder) {}
|
||||
@ -134,8 +135,12 @@ export class NgModuleDecoratorHandler implements DecoratorHandler<NgModuleAnalys
|
||||
// Register this module's information with the LocalModuleScopeRegistry. This ensures that
|
||||
// during the compile() phase, the module's metadata is available for selector scope
|
||||
// computation.
|
||||
this.scopeRegistry.registerNgModule(
|
||||
node, {declarations: declarationRefs, imports: importRefs, exports: exportRefs});
|
||||
this.metaRegistry.registerNgModuleMetadata({
|
||||
ref: new Reference(node),
|
||||
declarations: declarationRefs,
|
||||
imports: importRefs,
|
||||
exports: exportRefs
|
||||
});
|
||||
|
||||
const valueContext = node.getSourceFile();
|
||||
|
||||
|
@ -11,6 +11,7 @@ import * as ts from 'typescript';
|
||||
|
||||
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
|
||||
import {DefaultImportRecorder, Reference} from '../../imports';
|
||||
import {MetadataRegistry} from '../../metadata';
|
||||
import {PartialEvaluator} from '../../partial_evaluator';
|
||||
import {ClassDeclaration, Decorator, ReflectionHost, reflectObjectLiteral} from '../../reflection';
|
||||
import {LocalModuleScopeRegistry} from '../../scope/src/local';
|
||||
@ -27,8 +28,8 @@ export interface PipeHandlerData {
|
||||
export class PipeDecoratorHandler implements DecoratorHandler<PipeHandlerData, Decorator> {
|
||||
constructor(
|
||||
private reflector: ReflectionHost, private evaluator: PartialEvaluator,
|
||||
private scopeRegistry: LocalModuleScopeRegistry,
|
||||
private defaultImportRecorder: DefaultImportRecorder, private isCore: boolean) {}
|
||||
private metaRegistry: MetadataRegistry, private defaultImportRecorder: DefaultImportRecorder,
|
||||
private isCore: boolean) {}
|
||||
|
||||
readonly precedence = HandlerPrecedence.PRIMARY;
|
||||
|
||||
@ -76,7 +77,7 @@ export class PipeDecoratorHandler implements DecoratorHandler<PipeHandlerData, D
|
||||
ErrorCode.VALUE_HAS_WRONG_TYPE, pipeNameExpr, `@Pipe.name must be a string`);
|
||||
}
|
||||
const ref = new Reference(clazz);
|
||||
this.scopeRegistry.registerPipe({ref, name: pipeName});
|
||||
this.metaRegistry.registerPipeMetadata({ref, name: pipeName});
|
||||
|
||||
let pure = true;
|
||||
if (pipe.has('pure')) {
|
||||
|
@ -15,6 +15,7 @@ ts_library(
|
||||
"//packages/compiler-cli/src/ngtsc/cycles",
|
||||
"//packages/compiler-cli/src/ngtsc/diagnostics",
|
||||
"//packages/compiler-cli/src/ngtsc/imports",
|
||||
"//packages/compiler-cli/src/ngtsc/metadata",
|
||||
"//packages/compiler-cli/src/ngtsc/partial_evaluator",
|
||||
"//packages/compiler-cli/src/ngtsc/path",
|
||||
"//packages/compiler-cli/src/ngtsc/reflection",
|
||||
|
@ -11,6 +11,7 @@ import * as ts from 'typescript';
|
||||
import {CycleAnalyzer, ImportGraph} from '../../cycles';
|
||||
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
|
||||
import {ModuleResolver, NOOP_DEFAULT_IMPORT_RECORDER, ReferenceEmitter} from '../../imports';
|
||||
import {DtsMetadataReader, LocalMetadataRegistry} from '../../metadata';
|
||||
import {PartialEvaluator} from '../../partial_evaluator';
|
||||
import {TypeScriptReflectionHost, isNamedClassDeclaration} from '../../reflection';
|
||||
import {LocalModuleScopeRegistry, MetadataDtsModuleScopeResolver} from '../../scope';
|
||||
@ -48,14 +49,16 @@ describe('ComponentDecoratorHandler', () => {
|
||||
const moduleResolver = new ModuleResolver(program, options, host);
|
||||
const importGraph = new ImportGraph(moduleResolver);
|
||||
const cycleAnalyzer = new CycleAnalyzer(importGraph);
|
||||
const metaRegistry = new LocalMetadataRegistry();
|
||||
const dtsReader = new DtsMetadataReader(checker, reflectionHost);
|
||||
const scopeRegistry = new LocalModuleScopeRegistry(
|
||||
new MetadataDtsModuleScopeResolver(checker, reflectionHost, null), new ReferenceEmitter([]),
|
||||
metaRegistry, new MetadataDtsModuleScopeResolver(dtsReader, null), new ReferenceEmitter([]),
|
||||
null);
|
||||
const refEmitter = new ReferenceEmitter([]);
|
||||
|
||||
const handler = new ComponentDecoratorHandler(
|
||||
reflectionHost, evaluator, scopeRegistry, false, new NoopResourceLoader(), [''], false,
|
||||
true, moduleResolver, cycleAnalyzer, refEmitter, NOOP_DEFAULT_IMPORT_RECORDER);
|
||||
reflectionHost, evaluator, metaRegistry, scopeRegistry, false, new NoopResourceLoader(),
|
||||
[''], false, true, moduleResolver, cycleAnalyzer, refEmitter, NOOP_DEFAULT_IMPORT_RECORDER);
|
||||
const TestCmp = getDeclaration(program, 'entry.ts', 'TestCmp', isNamedClassDeclaration);
|
||||
const detected = handler.detect(TestCmp, reflectionHost.getDecoratorsOfDeclaration(TestCmp));
|
||||
if (detected === undefined) {
|
||||
|
@ -9,6 +9,7 @@
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {NOOP_DEFAULT_IMPORT_RECORDER, ReferenceEmitter} from '../../imports';
|
||||
import {DtsMetadataReader, LocalMetadataRegistry} from '../../metadata';
|
||||
import {PartialEvaluator} from '../../partial_evaluator';
|
||||
import {ClassDeclaration, TypeScriptReflectionHost, isNamedClassDeclaration} from '../../reflection';
|
||||
import {LocalModuleScopeRegistry, MetadataDtsModuleScopeResolver} from '../../scope';
|
||||
@ -40,8 +41,10 @@ describe('DirectiveDecoratorHandler', () => {
|
||||
const checker = program.getTypeChecker();
|
||||
const reflectionHost = new TestReflectionHost(checker);
|
||||
const evaluator = new PartialEvaluator(reflectionHost, checker);
|
||||
const metaReader = new LocalMetadataRegistry();
|
||||
const dtsReader = new DtsMetadataReader(checker, reflectionHost);
|
||||
const scopeRegistry = new LocalModuleScopeRegistry(
|
||||
new MetadataDtsModuleScopeResolver(checker, reflectionHost, null), new ReferenceEmitter([]),
|
||||
metaReader, new MetadataDtsModuleScopeResolver(dtsReader, null), new ReferenceEmitter([]),
|
||||
null);
|
||||
const handler = new DirectiveDecoratorHandler(
|
||||
reflectionHost, evaluator, scopeRegistry, NOOP_DEFAULT_IMPORT_RECORDER, false);
|
||||
|
@ -11,6 +11,7 @@ import {R3Reference} from '@angular/compiler/src/compiler';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {LocalIdentifierStrategy, NOOP_DEFAULT_IMPORT_RECORDER, ReferenceEmitter} from '../../imports';
|
||||
import {DtsMetadataReader, LocalMetadataRegistry} from '../../metadata';
|
||||
import {PartialEvaluator} from '../../partial_evaluator';
|
||||
import {TypeScriptReflectionHost, isNamedClassDeclaration} from '../../reflection';
|
||||
import {LocalModuleScopeRegistry, MetadataDtsModuleScopeResolver} from '../../scope';
|
||||
@ -55,14 +56,16 @@ describe('NgModuleDecoratorHandler', () => {
|
||||
const reflectionHost = new TypeScriptReflectionHost(checker);
|
||||
const evaluator = new PartialEvaluator(reflectionHost, checker);
|
||||
const referencesRegistry = new NoopReferencesRegistry();
|
||||
const metaRegistry = new LocalMetadataRegistry();
|
||||
const dtsReader = new DtsMetadataReader(checker, reflectionHost);
|
||||
const scopeRegistry = new LocalModuleScopeRegistry(
|
||||
new MetadataDtsModuleScopeResolver(checker, reflectionHost, null), new ReferenceEmitter([]),
|
||||
metaRegistry, new MetadataDtsModuleScopeResolver(dtsReader, null), new ReferenceEmitter([]),
|
||||
null);
|
||||
const refEmitter = new ReferenceEmitter([new LocalIdentifierStrategy()]);
|
||||
|
||||
const handler = new NgModuleDecoratorHandler(
|
||||
reflectionHost, evaluator, scopeRegistry, referencesRegistry, false, null, refEmitter,
|
||||
NOOP_DEFAULT_IMPORT_RECORDER);
|
||||
reflectionHost, evaluator, metaRegistry, scopeRegistry, referencesRegistry, false, null,
|
||||
refEmitter, NOOP_DEFAULT_IMPORT_RECORDER);
|
||||
const TestModule = getDeclaration(program, 'entry.ts', 'TestModule', isNamedClassDeclaration);
|
||||
const detected =
|
||||
handler.detect(TestModule, reflectionHost.getDecoratorsOfDeclaration(TestModule));
|
||||
|
Reference in New Issue
Block a user