From 9b35787bb3447d14476c21710587c2f6fa7bc3ac Mon Sep 17 00:00:00 2001 From: Alex Rickabaugh Date: Tue, 29 Mar 2022 16:26:40 -0700 Subject: [PATCH] refactor(compiler-cli): unify tracked template scope dependencies (#45672) Previously, the compiler tracked directives and pipes in template scopes separately. This commit refactors the scope system to unify them into a single data structure, disambiguated by a `kind` field. PR Close #45672 --- .../annotations/component/src/handler.ts | 165 ++++++++++-------- .../ngtsc/annotations/component/src/scope.ts | 47 ++--- .../annotations/directive/src/handler.ts | 4 +- .../annotations/ng_module/src/handler.ts | 5 +- .../src/ngtsc/annotations/src/pipe.ts | 4 +- .../src/ngtsc/metadata/src/api.ts | 11 +- .../src/ngtsc/metadata/src/dts.ts | 6 +- .../compiler-cli/src/ngtsc/scope/src/api.ts | 10 +- .../src/ngtsc/scope/src/dependency.ts | 20 +-- .../compiler-cli/src/ngtsc/scope/src/local.ts | 41 ++--- .../src/ngtsc/scope/src/typecheck.ts | 20 +-- .../compiler-cli/src/ngtsc/scope/src/util.ts | 3 +- .../src/ngtsc/scope/test/dependency_spec.ts | 7 +- .../src/ngtsc/scope/test/local_spec.ts | 13 +- .../src/ngtsc/typecheck/src/checker.ts | 64 +++---- .../src/ngtsc/typecheck/testing/index.ts | 16 +- .../pipes/GOLDEN_PARTIAL.js | 2 +- .../pipes/pipes_my_app_def.js | 2 +- .../queries/GOLDEN_PARTIAL.js | 6 +- .../property_bindings/GOLDEN_PARTIAL.js | 2 +- .../r3_view_compiler_di/di/GOLDEN_PARTIAL.js | 2 +- .../compiler-cli/test/ngtsc/ngtsc_spec.ts | 4 +- .../src/references_and_rename.ts | 6 +- 23 files changed, 227 insertions(+), 233 deletions(-) diff --git a/packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts b/packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts index 547d4f1e28804..fb9c61fe22e62 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/component/src/handler.ts @@ -16,7 +16,7 @@ import {assertSuccessfulReferenceEmit, ImportedFile, ModuleResolver, Reference, import {DependencyTracker} from '../../../incremental/api'; import {extractSemanticTypeParameters, SemanticDepGraphUpdater} from '../../../incremental/semantic_graph'; import {IndexingContext} from '../../../indexer'; -import {DirectiveMeta, extractDirectiveTypeCheckMeta, InjectableClassRegistry, MetadataReader, MetadataRegistry, MetaType, ResourceRegistry} from '../../../metadata'; +import {DirectiveMeta, extractDirectiveTypeCheckMeta, InjectableClassRegistry, MetadataReader, MetadataRegistry, MetaKind, PipeMeta, ResourceRegistry} from '../../../metadata'; import {PartialEvaluator} from '../../../partial_evaluator'; import {PerfEvent, PerfRecorder} from '../../../perf'; import {ClassDeclaration, DeclarationNode, Decorator, ReflectionHost, reflectObjectLiteral} from '../../../reflection'; @@ -446,7 +446,7 @@ export class ComponentDecoratorHandler implements // the information about the component is available during the compile() phase. const ref = new Reference(node); this.metaRegistry.registerDirectiveMetadata({ - type: MetaType.Directive, + kind: MetaKind.Directive, ref, name: node.name.text, selector: analysis.meta.selector, @@ -482,9 +482,9 @@ export class ComponentDecoratorHandler implements return null; } - for (const directive of scope.compilation.directives) { - if (directive.selector !== null) { - matcher.addSelectables(CssSelector.parse(directive.selector), directive); + for (const dep of scope.compilation.dependencies) { + if (dep.kind === MetaKind.Directive && dep.selector !== null) { + matcher.addSelectables(CssSelector.parse(dep.selector), dep); } } } @@ -584,15 +584,15 @@ export class ComponentDecoratorHandler implements type MatchedDirective = DirectiveMeta&{selector: string}; const matcher = new SelectorMatcher(); - for (const dir of scope.directives) { - if (dir.selector !== null) { - matcher.addSelectables(CssSelector.parse(dir.selector), dir as MatchedDirective); + const pipes = new Map(); + + for (const dep of scope.dependencies) { + if (dep.kind === MetaKind.Directive && dep.selector !== null) { + matcher.addSelectables(CssSelector.parse(dep.selector), dep as MatchedDirective); + } else if (dep.kind === MetaKind.Pipe) { + pipes.set(dep.name, dep); } } - const pipes = new Map>(); - for (const pipe of scope.pipes) { - pipes.set(pipe.name, pipe.ref); - } // Next, the component template AST is bound using the R3TargetBinder. This produces a // BoundTarget, which is similar to a ts.TypeChecker. @@ -602,65 +602,95 @@ export class ComponentDecoratorHandler implements // The BoundTarget knows which directives and pipes matched the template. type UsedDirective = R3DirectiveDependencyMetadata& {ref: Reference, importedFile: ImportedFile}; - const usedDirectives: UsedDirective[] = bound.getUsedDirectives().map(directive => { - const type = this.refEmitter.emit(directive.ref, context); - assertSuccessfulReferenceEmit( - type, node.name, directive.isComponent ? 'component' : 'directive'); - return { - kind: R3TemplateDependencyKind.Directive, - ref: directive.ref, - type: type.expression, - importedFile: type.importedFile, - selector: directive.selector, - inputs: directive.inputs.propertyNames, - outputs: directive.outputs.propertyNames, - exportAs: directive.exportAs, - isComponent: directive.isComponent, - }; - }); + + const used = new Set(); + for (const dir of bound.getUsedDirectives()) { + used.add(dir.ref.node); + } + for (const name of bound.getUsedPipes()) { + if (!pipes.has(name)) { + continue; + } + used.add(pipes.get(name)!.ref.node); + } type UsedPipe = R3PipeDependencyMetadata&{ ref: Reference, importedFile: ImportedFile, }; - const usedPipes: UsedPipe[] = []; - for (const pipeName of bound.getUsedPipes()) { - if (!pipes.has(pipeName)) { - continue; + + const declarations: (UsedPipe|UsedDirective)[] = []; + + // Transform the dependencies list, filtering out unused dependencies. + for (const dep of scope.dependencies) { + switch (dep.kind) { + case MetaKind.Directive: + if (!used.has(dep.ref.node)) { + continue; + } + const dirType = this.refEmitter.emit(dep.ref, context); + assertSuccessfulReferenceEmit( + dirType, node.name, dep.isComponent ? 'component' : 'directive'); + + declarations.push({ + kind: R3TemplateDependencyKind.Directive, + ref: dep.ref, + type: dirType.expression, + importedFile: dirType.importedFile, + selector: dep.selector!, + inputs: dep.inputs.propertyNames, + outputs: dep.outputs.propertyNames, + exportAs: dep.exportAs, + isComponent: dep.isComponent, + }); + break; + case MetaKind.Pipe: + if (!used.has(dep.ref.node)) { + continue; + } + + const pipeType = this.refEmitter.emit(dep.ref, context); + assertSuccessfulReferenceEmit(pipeType, node.name, 'pipe'); + + declarations.push({ + kind: R3TemplateDependencyKind.Pipe, + type: pipeType.expression, + name: dep.name, + ref: dep.ref, + importedFile: pipeType.importedFile, + }); + break; } - const pipe = pipes.get(pipeName)!; - const type = this.refEmitter.emit(pipe, context); - assertSuccessfulReferenceEmit(type, node.name, 'pipe'); - usedPipes.push({ - kind: R3TemplateDependencyKind.Pipe, - type: type.expression, - name: pipeName, - ref: pipe, - importedFile: type.importedFile, - }); } + + const isUsedDirective = (decl: UsedDirective|UsedPipe): decl is UsedDirective => + decl.kind === R3TemplateDependencyKind.Directive; + const isUsedPipe = (decl: UsedDirective|UsedPipe): decl is UsedPipe => + decl.kind === R3TemplateDependencyKind.Pipe; + + const getSemanticReference = (decl: UsedDirective|UsedPipe) => + this.semanticDepGraphUpdater!.getSemanticReference(decl.ref.node, decl.type); + if (this.semanticDepGraphUpdater !== null) { - symbol.usedDirectives = usedDirectives.map( - dir => this.semanticDepGraphUpdater!.getSemanticReference(dir.ref.node, dir.type)); - symbol.usedPipes = usedPipes.map( - pipe => this.semanticDepGraphUpdater!.getSemanticReference(pipe.ref.node, pipe.type)); + symbol.usedDirectives = declarations.filter(isUsedDirective).map(getSemanticReference); + symbol.usedPipes = declarations.filter(isUsedPipe).map(getSemanticReference); } // Scan through the directives/pipes actually used in the template and check whether any // import which needs to be generated would create a cycle. const cyclesFromDirectives = new Map(); - for (const usedDirective of usedDirectives) { - const cycle = - this._checkForCyclicImport(usedDirective.importedFile, usedDirective.type, context); - if (cycle !== null) { - cyclesFromDirectives.set(usedDirective, cycle); - } - } const cyclesFromPipes = new Map(); - for (const usedPipe of usedPipes) { - const cycle = this._checkForCyclicImport(usedPipe.importedFile, usedPipe.type, context); + for (const usedDep of declarations) { + const cycle = this._checkForCyclicImport(usedDep.importedFile, usedDep.type, context); if (cycle !== null) { - cyclesFromPipes.set(usedPipe, cycle); + switch (usedDep.kind) { + case R3TemplateDependencyKind.Directive: + cyclesFromDirectives.set(usedDep, cycle); + break; + case R3TemplateDependencyKind.Pipe: + cyclesFromPipes.set(usedDep, cycle); + break; + } } } @@ -668,25 +698,17 @@ export class ComponentDecoratorHandler implements if (!cycleDetected) { // No cycle was detected. Record the imports that need to be created in the cycle detector // so that future cyclic import checks consider their production. - for (const {type, importedFile} of usedDirectives) { - this._recordSyntheticImport(importedFile, type, context); - } - for (const {type, importedFile} of usedPipes) { + for (const {type, importedFile} of declarations) { this._recordSyntheticImport(importedFile, type, context); } - // Check whether the directive/pipe arrays in ɵcmp need to be wrapped in closures. - // This is required if any directive/pipe reference is to a declaration in the same file + // Check whether the dependencies arrays in ɵcmp need to be wrapped in a closure. + // This is required if any dependency reference is to a declaration in the same file // but declared after this component. const wrapDirectivesAndPipesInClosure = - usedDirectives.some( - dir => isExpressionForwardReference(dir.type, node.name, context)) || - usedPipes.some(pipe => isExpressionForwardReference(pipe.type, node.name, context)); - - data.declarations = [ - ...usedDirectives, - ...usedPipes, - ]; + declarations.some(decl => isExpressionForwardReference(decl.type, node.name, context)); + + data.declarations = declarations; data.declarationListEmitMode = wrapDirectivesAndPipesInClosure ? DeclarationListEmitMode.Closure : DeclarationListEmitMode.Direct; @@ -696,7 +718,8 @@ export class ComponentDecoratorHandler implements // create a cycle. Instead, mark this component as requiring remote scoping, so that the // NgModule file will take care of setting the directives for the component. this.scopeRegistry.setComponentRemoteScope( - node, usedDirectives.map(dir => dir.ref), usedPipes.map(pipe => pipe.ref)); + node, declarations.filter(isUsedDirective).map(dir => dir.ref), + declarations.filter(isUsedPipe).map(pipe => pipe.ref)); symbol.isRemotelyScoped = true; // If a semantic graph is being tracked, record the fact that this component is remotely diff --git a/packages/compiler-cli/src/ngtsc/annotations/component/src/scope.ts b/packages/compiler-cli/src/ngtsc/annotations/component/src/scope.ts index 18c429eca6db5..8cc860eeb012c 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/component/src/scope.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/component/src/scope.ts @@ -15,9 +15,10 @@ import {ComponentScopeReader, DtsModuleScopeResolver, ExportScope, LocalModuleSc import {ComponentAnalysisData} from './metadata'; +export type DependencyMeta = DirectiveMeta|PipeMeta; + export interface ScopeTemplateResult { - directives: DirectiveMeta[]; - pipes: PipeMeta[]; + dependencies: DependencyMeta[]; diagnostics: ts.Diagnostic[]; ngModule: ClassDeclaration|null; } @@ -43,8 +44,7 @@ export function scopeTemplate( if (scope !== null) { // This is an NgModule-ful component, so use scope information coming from the NgModule. return { - directives: scope.compilation.directives, - pipes: scope.compilation.pipes, + dependencies: scope.compilation.dependencies, ngModule: scope.ngModule, diagnostics: [], }; @@ -53,8 +53,7 @@ export function scopeTemplate( if (analysis.imports === null) { // Early exit for standalone components that don't declare imports (empty scope). return { - directives: [], - pipes: [], + dependencies: [], ngModule: null, diagnostics: [], }; @@ -64,10 +63,16 @@ export function scopeTemplate( // We need to deduplicate directives/pipes in `imports`, as any given directive/pipe may be // present in the export scope of more than one NgModule (or just listed more than once). - const directives = new Map(); - const pipes = new Map(); + const seen = new Set(); + const dependencies: DependencyMeta[] = []; for (const ref of analysis.imports.resolved) { + if (seen.has(ref.node)) { + // This imported type has already been processed, so don't process it a second time. + continue; + } + seen.add(ref.node); + // Determine if this import is a component/directive/pipe/NgModule. const dirMeta = metaReader.getDirectiveMetadata(ref); if (dirMeta !== null) { @@ -79,9 +84,7 @@ export function scopeTemplate( continue; } - if (!directives.has(ref.node)) { - directives.set(ref.node, dirMeta); - } + dependencies.push(dirMeta); continue; } @@ -114,33 +117,21 @@ export function scopeTemplate( return null; } - for (const dir of scope.exported.directives) { - if (!directives.has(dir.ref.node)) { - directives.set(dir.ref.node, dir); - } - } - - for (const pipe of scope.exported.pipes) { - if (!pipes.has(pipe.ref.node)) { - pipes.set(pipe.ref.node, pipe); - } - } + dependencies.push(...scope.exported.dependencies); } } return { - directives: Array.from(directives.values()), - pipes: Array.from(pipes.values()), - diagnostics, + dependencies, ngModule: null, + diagnostics, }; } else { // This is a "free" component, and is neither standalone nor declared in an NgModule. // This should probably be an error now that we have standalone components, but that would be a - // breaking change. For now, preserve the old behavior (treat is as having an empty scope). + // breaking change. For now, preserve the old behavior (treat it as having an empty scope). return { - directives: [], - pipes: [], + dependencies: [], ngModule: null, diagnostics: [], }; diff --git a/packages/compiler-cli/src/ngtsc/annotations/directive/src/handler.ts b/packages/compiler-cli/src/ngtsc/annotations/directive/src/handler.ts index a20427f047f13..5a304483c339f 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/directive/src/handler.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/directive/src/handler.ts @@ -11,7 +11,7 @@ import ts from 'typescript'; import {Reference} from '../../../imports'; import {extractSemanticTypeParameters, SemanticDepGraphUpdater} from '../../../incremental/semantic_graph'; -import {ClassPropertyMapping, DirectiveTypeCheckMeta, extractDirectiveTypeCheckMeta, InjectableClassRegistry, MetadataReader, MetadataRegistry, MetaType} from '../../../metadata'; +import {ClassPropertyMapping, DirectiveTypeCheckMeta, extractDirectiveTypeCheckMeta, InjectableClassRegistry, MetadataReader, MetadataRegistry, MetaKind} from '../../../metadata'; import {PartialEvaluator} from '../../../partial_evaluator'; import {PerfEvent, PerfRecorder} from '../../../perf'; import {ClassDeclaration, ClassMember, ClassMemberKind, Decorator, ReflectionHost} from '../../../reflection'; @@ -132,7 +132,7 @@ export class DirectiveDecoratorHandler implements // the information about the directive is available during the compile() phase. const ref = new Reference(node); this.metaRegistry.registerDirectiveMetadata({ - type: MetaType.Directive, + kind: MetaKind.Directive, ref, name: node.name.text, selector: analysis.meta.selector, diff --git a/packages/compiler-cli/src/ngtsc/annotations/ng_module/src/handler.ts b/packages/compiler-cli/src/ngtsc/annotations/ng_module/src/handler.ts index 4babae210c135..d8a540d33271a 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/ng_module/src/handler.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/ng_module/src/handler.ts @@ -12,7 +12,7 @@ import ts from 'typescript'; import {ErrorCode, FatalDiagnosticError, makeDiagnostic, makeRelatedInformation} from '../../../diagnostics'; import {assertSuccessfulReferenceEmit, Reference, ReferenceEmitter} from '../../../imports'; import {isArrayEqual, isReferenceEqual, isSymbolEqual, SemanticReference, SemanticSymbol} from '../../../incremental/semantic_graph'; -import {InjectableClassRegistry, MetadataReader, MetadataRegistry} from '../../../metadata'; +import {InjectableClassRegistry, MetadataReader, MetadataRegistry, MetaKind} from '../../../metadata'; import {PartialEvaluator, ResolvedValue} from '../../../partial_evaluator'; import {PerfEvent, PerfRecorder} from '../../../perf'; import {ClassDeclaration, Decorator, isNamedClassDeclaration, ReflectionHost, reflectObjectLiteral, typeNodeToValueExpr} from '../../../reflection'; @@ -738,8 +738,7 @@ export class NgModuleDecoratorHandler implements } function isNgModule(node: ClassDeclaration, compilation: ScopeData): boolean { - return !compilation.directives.some(directive => directive.ref.node === node) && - !compilation.pipes.some(pipe => pipe.ref.node === node); + return !compilation.dependencies.some(dep => dep.ref.node === node); } /** diff --git a/packages/compiler-cli/src/ngtsc/annotations/src/pipe.ts b/packages/compiler-cli/src/ngtsc/annotations/src/pipe.ts index 685de36f35191..97fcd3d8ee22e 100644 --- a/packages/compiler-cli/src/ngtsc/annotations/src/pipe.ts +++ b/packages/compiler-cli/src/ngtsc/annotations/src/pipe.ts @@ -12,7 +12,7 @@ import ts from 'typescript'; import {ErrorCode, FatalDiagnosticError} from '../../diagnostics'; import {Reference} from '../../imports'; import {SemanticSymbol} from '../../incremental/semantic_graph'; -import {InjectableClassRegistry, MetadataRegistry, MetaType} from '../../metadata'; +import {InjectableClassRegistry, MetadataRegistry, MetaKind} from '../../metadata'; import {PartialEvaluator} from '../../partial_evaluator'; import {PerfEvent, PerfRecorder} from '../../perf'; import {ClassDeclaration, Decorator, ReflectionHost, reflectObjectLiteral} from '../../reflection'; @@ -154,7 +154,7 @@ export class PipeDecoratorHandler implements register(node: ClassDeclaration, analysis: Readonly): void { const ref = new Reference(node); this.metaRegistry.registerPipeMetadata({ - type: MetaType.Pipe, + kind: MetaKind.Pipe, ref, name: analysis.meta.pipeName, nameExpr: analysis.pipeNameExpr, diff --git a/packages/compiler-cli/src/ngtsc/metadata/src/api.ts b/packages/compiler-cli/src/ngtsc/metadata/src/api.ts index a26967483e64a..91c2d71825588 100644 --- a/packages/compiler-cli/src/ngtsc/metadata/src/api.ts +++ b/packages/compiler-cli/src/ngtsc/metadata/src/api.ts @@ -95,16 +95,19 @@ export interface DirectiveTypeCheckMeta { isGeneric: boolean; } -export enum MetaType { - Pipe, +/** + * Disambiguates different kinds of compiler metadata objects. + */ +export enum MetaKind { Directive, + Pipe, } /** * Metadata collected for a directive within an NgModule's scope. */ export interface DirectiveMeta extends T2DirectiveMeta, DirectiveTypeCheckMeta { - type: MetaType.Directive; + kind: MetaKind.Directive; ref: Reference; /** @@ -171,7 +174,7 @@ export interface TemplateGuardMeta { * Metadata for a pipe within an NgModule's scope. */ export interface PipeMeta { - type: MetaType.Pipe; + kind: MetaKind.Pipe; ref: Reference; name: string; nameExpr: ts.Expression|null; diff --git a/packages/compiler-cli/src/ngtsc/metadata/src/dts.ts b/packages/compiler-cli/src/ngtsc/metadata/src/dts.ts index 88ba4ffc5d6ee..77d116322cf40 100644 --- a/packages/compiler-cli/src/ngtsc/metadata/src/dts.ts +++ b/packages/compiler-cli/src/ngtsc/metadata/src/dts.ts @@ -11,7 +11,7 @@ import ts from 'typescript'; import {Reference} from '../../imports'; import {ClassDeclaration, isNamedClassDeclaration, ReflectionHost, TypeValueReferenceKind} from '../../reflection'; -import {DirectiveMeta, MetadataReader, MetaType, NgModuleMeta, PipeMeta} from './api'; +import {DirectiveMeta, MetadataReader, MetaKind, NgModuleMeta, PipeMeta} from './api'; import {ClassPropertyMapping} from './property_mapping'; import {extractDirectiveTypeCheckMeta, extractReferencesFromType, readStringArrayType, readStringMapType, readStringType} from './util'; @@ -95,7 +95,7 @@ export class DtsMetadataReader implements MetadataReader { const outputs = ClassPropertyMapping.fromMappedObject(readStringMapType(def.type.typeArguments[4])); return { - type: MetaType.Directive, + kind: MetaKind.Directive, ref, name: clazz.name.text, isComponent, @@ -135,7 +135,7 @@ export class DtsMetadataReader implements MetadataReader { } const name = type.literal.text; return { - type: MetaType.Pipe, + kind: MetaKind.Pipe, ref, name, nameExpr: null, diff --git a/packages/compiler-cli/src/ngtsc/scope/src/api.ts b/packages/compiler-cli/src/ngtsc/scope/src/api.ts index 8e7c0cff5a8dc..3d73f0d8b2a59 100644 --- a/packages/compiler-cli/src/ngtsc/scope/src/api.ts +++ b/packages/compiler-cli/src/ngtsc/scope/src/api.ts @@ -17,15 +17,7 @@ import {ClassDeclaration} from '../../reflection'; * Data for one of a given NgModule's scopes (either compilation scope or export scopes). */ export interface ScopeData { - /** - * Directives in the exported scope of the module. - */ - directives: DirectiveMeta[]; - - /** - * Pipes in the exported scope of the module. - */ - pipes: PipeMeta[]; + dependencies: Array; /** * Whether some module or component in this scope contains errors and is thus semantically diff --git a/packages/compiler-cli/src/ngtsc/scope/src/dependency.ts b/packages/compiler-cli/src/ngtsc/scope/src/dependency.ts index fbb31abe2e5d5..26ff8179a6806 100644 --- a/packages/compiler-cli/src/ngtsc/scope/src/dependency.ts +++ b/packages/compiler-cli/src/ngtsc/scope/src/dependency.ts @@ -56,8 +56,7 @@ export class MetadataDtsModuleScopeResolver implements DtsModuleScopeResolver { } // Build up the export scope - those directives and pipes made visible by this module. - const directives: DirectiveMeta[] = []; - const pipes: PipeMeta[] = []; + const dependencies: Array = []; const meta = this.dtsMetaReader.getNgModuleMetadata(ref); if (meta === null) { @@ -77,7 +76,7 @@ export class MetadataDtsModuleScopeResolver implements DtsModuleScopeResolver { const directive = this.dtsMetaReader.getDirectiveMetadata(exportRef); if (directive !== null) { const isReExport = !declarations.has(exportRef.node); - directives.push(this.maybeAlias(directive, sourceFile, isReExport)); + dependencies.push(this.maybeAlias(directive, sourceFile, isReExport)); continue; } @@ -85,7 +84,7 @@ export class MetadataDtsModuleScopeResolver implements DtsModuleScopeResolver { const pipe = this.dtsMetaReader.getPipeMetadata(exportRef); if (pipe !== null) { const isReExport = !declarations.has(exportRef.node); - pipes.push(this.maybeAlias(pipe, sourceFile, isReExport)); + dependencies.push(this.maybeAlias(pipe, sourceFile, isReExport)); continue; } @@ -97,8 +96,7 @@ export class MetadataDtsModuleScopeResolver implements DtsModuleScopeResolver { // required. if (this.aliasingHost === null) { // Fast path when aliases aren't required. - directives.push(...exportScope.exported.directives); - pipes.push(...exportScope.exported.pipes); + dependencies.push(...exportScope.exported.dependencies); } else { // It's necessary to rewrite the `Reference`s to add alias expressions. This way, imports // generated to these directives and pipes will use a shallow import to `sourceFile` @@ -108,11 +106,8 @@ export class MetadataDtsModuleScopeResolver implements DtsModuleScopeResolver { // source file as the re-exporting NgModule. This can happen if both a directive, its // NgModule, and the re-exporting NgModule are all in the same file. In this case, // no import alias is needed as it would go to the same file anyway. - for (const directive of exportScope.exported.directives) { - directives.push(this.maybeAlias(directive, sourceFile, /* isReExport */ true)); - } - for (const pipe of exportScope.exported.pipes) { - pipes.push(this.maybeAlias(pipe, sourceFile, /* isReExport */ true)); + for (const dep of exportScope.exported.dependencies) { + dependencies.push(this.maybeAlias(dep, sourceFile, /* isReExport */ true)); } } } @@ -124,8 +119,7 @@ export class MetadataDtsModuleScopeResolver implements DtsModuleScopeResolver { const exportScope: ExportScope = { exported: { - directives, - pipes, + dependencies, isPoisoned: false, }, }; diff --git a/packages/compiler-cli/src/ngtsc/scope/src/local.ts b/packages/compiler-cli/src/ngtsc/scope/src/local.ts index e0afcfe29902b..296a1e057c5c1 100644 --- a/packages/compiler-cli/src/ngtsc/scope/src/local.ts +++ b/packages/compiler-cli/src/ngtsc/scope/src/local.ts @@ -11,7 +11,7 @@ import ts from 'typescript'; import {ErrorCode, makeDiagnostic, makeRelatedInformation} from '../../diagnostics'; import {AliasingHost, assertSuccessfulReferenceEmit, Reexport, Reference, ReferenceEmitter} from '../../imports'; -import {DirectiveMeta, MetadataReader, MetadataRegistry, NgModuleMeta, PipeMeta} from '../../metadata'; +import {DirectiveMeta, MetadataReader, MetadataRegistry, MetaKind, NgModuleMeta, PipeMeta} from '../../metadata'; import {ClassDeclaration, DeclarationNode} from '../../reflection'; import {identifierOfNode, nodeNameForError} from '../../util/src/typescript'; @@ -285,11 +285,12 @@ export class LocalModuleScopeRegistry implements MetadataRegistry, ComponentScop } } - for (const directive of importScope.exported.directives) { - compilationDirectives.set(directive.ref.node, directive); - } - for (const pipe of importScope.exported.pipes) { - compilationPipes.set(pipe.ref.node, pipe); + for (const dep of importScope.exported.dependencies) { + if (dep.kind === MetaKind.Directive) { + compilationDirectives.set(dep.ref.node, dep); + } else if (dep.kind === MetaKind.Pipe) { + compilationPipes.set(dep.ref.node, dep); + } } // Successfully processed the import as an NgModule (even if it had errors). @@ -401,11 +402,12 @@ export class LocalModuleScopeRegistry implements MetadataRegistry, ComponentScop } } else if (exportScope !== null) { // decl is an NgModule. - for (const directive of exportScope.exported.directives) { - exportDirectives.set(directive.ref.node, directive); - } - for (const pipe of exportScope.exported.pipes) { - exportPipes.set(pipe.ref.node, pipe); + for (const dep of exportScope.exported.dependencies) { + if (dep.kind == MetaKind.Directive) { + exportDirectives.set(dep.ref.node, dep); + } else if (dep.kind === MetaKind.Pipe) { + exportPipes.set(dep.ref.node, dep); + } } } else if (compilationDirectives.has(decl.node)) { // decl is a directive or component in the compilation scope of this NgModule. @@ -431,20 +433,19 @@ export class LocalModuleScopeRegistry implements MetadataRegistry, ComponentScop } const exported: ScopeData = { - directives: Array.from(exportDirectives.values()), - pipes: Array.from(exportPipes.values()), + dependencies: [...exportDirectives.values(), ...exportPipes.values()], isPoisoned, }; - const reexports = this.getReexports(ngModule, ref, declared, exported, diagnostics); + const reexports = + this.getReexports(ngModule, ref, declared, exported.dependencies, diagnostics); // Finally, produce the `LocalModuleScope` with both the compilation and export scopes. const scope: LocalModuleScope = { ngModule: ngModule.ref.node, compilation: { - directives: Array.from(compilationDirectives.values()), - pipes: Array.from(compilationPipes.values()), + dependencies: [...compilationDirectives.values(), ...compilationPipes.values()], isPoisoned, }, exported, @@ -518,8 +519,7 @@ export class LocalModuleScopeRegistry implements MetadataRegistry, ComponentScop private getReexports( ngModule: NgModuleMeta, ref: Reference, declared: Set, - exported: {directives: DirectiveMeta[], pipes: PipeMeta[]}, - diagnostics: ts.Diagnostic[]): Reexport[]|null { + exported: Array, diagnostics: ts.Diagnostic[]): Reexport[]|null { let reexports: Reexport[]|null = null; const sourceFile = ref.node.getSourceFile(); if (this.aliasingHost === null) { @@ -569,10 +569,7 @@ export class LocalModuleScopeRegistry implements MetadataRegistry, ComponentScop diagnostics.push(reexportCollision(ngModuleRef.node, prevRef, exportRef)); } }; - for (const {ref} of exported.directives) { - addReexport(ref); - } - for (const {ref} of exported.pipes) { + for (const {ref} of exported) { addReexport(ref); } return reexports; diff --git a/packages/compiler-cli/src/ngtsc/scope/src/typecheck.ts b/packages/compiler-cli/src/ngtsc/scope/src/typecheck.ts index 0ac9a8acbb14d..f4512bde8a993 100644 --- a/packages/compiler-cli/src/ngtsc/scope/src/typecheck.ts +++ b/packages/compiler-cli/src/ngtsc/scope/src/typecheck.ts @@ -10,7 +10,7 @@ import {CssSelector, SchemaMetadata, SelectorMatcher} from '@angular/compiler'; import ts from 'typescript'; import {Reference} from '../../imports'; -import {DirectiveMeta, flattenInheritedDirectiveMetadata, MetadataReader} from '../../metadata'; +import {DirectiveMeta, flattenInheritedDirectiveMetadata, MetadataReader, MetaKind} from '../../metadata'; import {ClassDeclaration} from '../../reflection'; import {ComponentScopeReader} from './api'; @@ -89,22 +89,20 @@ export class TypeCheckScopeRegistry { return this.scopeCache.get(scope.ngModule)!; } - for (const meta of scope.compilation.directives) { - if (meta.selector !== null) { + for (const meta of scope.compilation.dependencies) { + if (meta.kind === MetaKind.Directive && meta.selector !== null) { const extMeta = this.getTypeCheckDirectiveMetadata(meta.ref); matcher.addSelectables(CssSelector.parse(meta.selector), extMeta); directives.push(extMeta); + } else if (meta.kind === MetaKind.Pipe) { + if (!ts.isClassDeclaration(meta.ref.node)) { + throw new Error(`Unexpected non-class declaration ${ + ts.SyntaxKind[meta.ref.node.kind]} for pipe ${meta.ref.debugName}`); + } + pipes.set(meta.name, meta.ref as Reference>); } } - for (const {name, ref} of scope.compilation.pipes) { - if (!ts.isClassDeclaration(ref.node)) { - throw new Error(`Unexpected non-class declaration ${ - ts.SyntaxKind[ref.node.kind]} for pipe ${ref.debugName}`); - } - pipes.set(name, ref as Reference>); - } - const typeCheckScope: TypeCheckScope = { matcher, directives, diff --git a/packages/compiler-cli/src/ngtsc/scope/src/util.ts b/packages/compiler-cli/src/ngtsc/scope/src/util.ts index 48d2bab508061..236a6e7379393 100644 --- a/packages/compiler-cli/src/ngtsc/scope/src/util.ts +++ b/packages/compiler-cli/src/ngtsc/scope/src/util.ts @@ -36,8 +36,7 @@ export function makeNotStandaloneDiagnostic( let relatedInformation: ts.DiagnosticRelatedInformation[]|undefined = undefined; if (scope !== null) { // The directive/pipe in question is declared in an NgModule. Check if it's also exported. - const isExported = scope.exported.directives.some(exp => exp.ref.node === ref.node) || - scope.exported.pipes.some(exp => exp.ref.node === ref.node); + const isExported = scope.exported.dependencies.some(dep => dep.ref.node === ref.node); if (isExported) { relatedInformation = [makeRelatedInformation( scope.ngModule.name, diff --git a/packages/compiler-cli/src/ngtsc/scope/test/dependency_spec.ts b/packages/compiler-cli/src/ngtsc/scope/test/dependency_spec.ts index 95d8d75bb09f3..8094a6ea2b894 100644 --- a/packages/compiler-cli/src/ngtsc/scope/test/dependency_spec.ts +++ b/packages/compiler-cli/src/ngtsc/scope/test/dependency_spec.ts @@ -145,7 +145,7 @@ runInEachFileSystem(() => { expect(scopeToRefs(scope).map(ref => ref.node)).toEqual([Dir.node]); // Explicitly verify that the directive has the correct owning module. - expect(scope.exported.directives[0].ref.bestGuessOwningModule).toEqual({ + expect(scope.exported.dependencies[0].ref.bestGuessOwningModule).toEqual({ specifier: 'declaration', resolutionContext: ModuleB.node.getSourceFile().fileName, }); @@ -278,9 +278,8 @@ runInEachFileSystem(() => { }); function scopeToRefs(scope: ExportScope): Reference[] { - const directives = scope.exported.directives.map(dir => dir.ref); - const pipes = scope.exported.pipes.map(pipe => pipe.ref); - return [...directives, ...pipes].sort((a, b) => a.debugName!.localeCompare(b.debugName!)); + return scope.exported.dependencies.map(dep => dep.ref) + .sort((a, b) => a.debugName!.localeCompare(b.debugName!)); } function getAlias(ref: Reference): ExternalReference|null { diff --git a/packages/compiler-cli/src/ngtsc/scope/test/local_spec.ts b/packages/compiler-cli/src/ngtsc/scope/test/local_spec.ts index 1d88b7942cea8..d686741ac955b 100644 --- a/packages/compiler-cli/src/ngtsc/scope/test/local_spec.ts +++ b/packages/compiler-cli/src/ngtsc/scope/test/local_spec.ts @@ -9,7 +9,7 @@ import ts from 'typescript'; import {Reference, ReferenceEmitter} from '../../imports'; -import {ClassPropertyMapping, CompoundMetadataRegistry, DirectiveMeta, DtsMetadataReader, LocalMetadataRegistry, MetadataRegistry, MetaType, PipeMeta} from '../../metadata'; +import {ClassPropertyMapping, CompoundMetadataRegistry, DirectiveMeta, DtsMetadataReader, LocalMetadataRegistry, MetadataRegistry, MetaKind, PipeMeta} from '../../metadata'; import {ClassDeclaration} from '../../reflection'; import {LocalModuleScope, ScopeData} from '../src/api'; import {DtsModuleScopeResolver} from '../src/dependency'; @@ -192,7 +192,7 @@ describe('LocalModuleScopeRegistry', () => { }); const scope = scopeRegistry.getScopeOfModule(Module.node) as LocalModuleScope; - expect(scope.compilation.directives[0].ref.getIdentityIn(idSf)).toBe(id); + expect(scope.compilation.dependencies[0].ref.getIdentityIn(idSf)).toBe(id); }); it('should allow directly exporting a directive that\'s not imported', () => { @@ -260,7 +260,7 @@ describe('LocalModuleScopeRegistry', () => { function fakeDirective(ref: Reference): DirectiveMeta { const name = ref.debugName!; return { - type: MetaType.Directive, + kind: MetaKind.Directive, ref, name, selector: `[${ref.debugName}]`, @@ -287,7 +287,7 @@ function fakeDirective(ref: Reference): DirectiveMeta { function fakePipe(ref: Reference): PipeMeta { const name = ref.debugName!; return { - type: MetaType.Pipe, + kind: MetaKind.Pipe, ref, name, nameExpr: null, @@ -302,7 +302,6 @@ class MockDtsModuleScopeResolver implements DtsModuleScopeResolver { } function scopeToRefs(scopeData: ScopeData): Reference[] { - const directives = scopeData.directives.map(dir => dir.ref); - const pipes = scopeData.pipes.map(pipe => pipe.ref); - return [...directives, ...pipes].sort((a, b) => a.debugName!.localeCompare(b.debugName!)); + return scopeData.dependencies.map(dep => dep.ref) + .sort((a, b) => a.debugName!.localeCompare(b.debugName!)); } diff --git a/packages/compiler-cli/src/ngtsc/typecheck/src/checker.ts b/packages/compiler-cli/src/ngtsc/typecheck/src/checker.ts index f56bf220f1cef..b4fe07ede014e 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/src/checker.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/src/checker.ts @@ -13,6 +13,7 @@ import {ErrorCode, ngErrorCode} from '../../diagnostics'; import {absoluteFrom, absoluteFromSourceFile, AbsoluteFsPath, getSourceFileOrError} from '../../file_system'; import {Reference, ReferenceEmitter} from '../../imports'; import {IncrementalBuild} from '../../incremental/api'; +import {MetaKind} from '../../metadata'; import {PerfCheckpoint, PerfEvent, PerfPhase, PerfRecorder} from '../../perf'; import {ProgramDriver, UpdateMode} from '../../program_driver'; import {ClassDeclaration, isNamedClassDeclaration, ReflectionHost} from '../../reflection'; @@ -633,42 +634,43 @@ export class TemplateTypeCheckerImpl implements TemplateTypeChecker { }; const typeChecker = this.programDriver.getProgram().getTypeChecker(); - for (const dir of scope.compilation.directives) { - if (dir.selector === null) { - // Skip this directive, it can't be added to a template anyway. - continue; - } - const tsSymbol = typeChecker.getSymbolAtLocation(dir.ref.node.name); - if (!isSymbolWithValueDeclaration(tsSymbol)) { - continue; - } - - let ngModule: ClassDeclaration|null = null; - const moduleScopeOfDir = this.componentScopeReader.getScopeForComponent(dir.ref.node); - if (moduleScopeOfDir !== null) { - ngModule = moduleScopeOfDir.ngModule; - } + for (const dep of scope.compilation.dependencies) { + if (dep.kind === MetaKind.Directive) { + if (dep.selector === null) { + // Skip this directive, it can't be added to a template anyway. + continue; + } + const tsSymbol = typeChecker.getSymbolAtLocation(dep.ref.node.name); + if (!isSymbolWithValueDeclaration(tsSymbol)) { + continue; + } - data.directives.push({ - isComponent: dir.isComponent, - isStructural: dir.isStructural, - selector: dir.selector, - tsSymbol, - ngModule, - }); - } + let ngModule: ClassDeclaration|null = null; + const moduleScopeOfDir = this.componentScopeReader.getScopeForComponent(dep.ref.node); + if (moduleScopeOfDir !== null) { + ngModule = moduleScopeOfDir.ngModule; + } - for (const pipe of scope.compilation.pipes) { - const tsSymbol = typeChecker.getSymbolAtLocation(pipe.ref.node.name); - if (tsSymbol === undefined) { - continue; + data.directives.push({ + isComponent: dep.isComponent, + isStructural: dep.isStructural, + selector: dep.selector, + tsSymbol, + ngModule, + }); + } else if (dep.kind === MetaKind.Pipe) { + const tsSymbol = typeChecker.getSymbolAtLocation(dep.ref.node.name); + if (tsSymbol === undefined) { + continue; + } + data.pipes.push({ + name: dep.name, + tsSymbol, + }); } - data.pipes.push({ - name: pipe.name, - tsSymbol, - }); } + this.scopeCache.set(component, data); return data; } diff --git a/packages/compiler-cli/src/ngtsc/typecheck/testing/index.ts b/packages/compiler-cli/src/ngtsc/typecheck/testing/index.ts index f77c8f42bd2dd..864d01422e75a 100644 --- a/packages/compiler-cli/src/ngtsc/typecheck/testing/index.ts +++ b/packages/compiler-cli/src/ngtsc/typecheck/testing/index.ts @@ -13,7 +13,7 @@ import {absoluteFrom, AbsoluteFsPath, getSourceFileOrError, LogicalFileSystem} f import {TestFile} from '../../file_system/testing'; import {AbsoluteModuleStrategy, LocalIdentifierStrategy, LogicalProjectStrategy, ModuleResolver, Reexport, Reference, ReferenceEmitter, RelativePathStrategy} from '../../imports'; import {NOOP_INCREMENTAL_BUILD} from '../../incremental'; -import {ClassPropertyMapping, CompoundMetadataReader, MetaType} from '../../metadata'; +import {ClassPropertyMapping, CompoundMetadataReader, MetaKind} from '../../metadata'; import {NOOP_PERF_RECORDER} from '../../perf'; import {TsCreateProgramDriver} from '../../program_driver'; import {ClassDeclaration, isNamedClassDeclaration, TypeScriptReflectionHost} from '../../reflection'; @@ -508,8 +508,7 @@ export function setup(targets: TypeCheckingTarget[], overrides: { // This class wasn't part of the target set of components with templates, but is // probably a declaration used in one of them. Return an empty scope. const emptyScope: ScopeData = { - directives: [], - pipes: [], + dependencies: [], isPoisoned: false, }; return { @@ -610,8 +609,7 @@ export function getClass(sf: ts.SourceFile, name: string): ClassDeclaration{{ name | myPipe:1:2:3:4:5 }} {{ name ? 1 : 2 | myPipe }}

', isInline: true, dependencies: [{ kind: "pipe", type: MyPurePipe, name: "myPurePipe" }, { kind: "pipe", type: MyPipe, name: "myPipe" }] }); +MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", type: MyApp, selector: "my-app", ngImport: i0, template: '{{name | myPipe:size | myPurePipe:size }}

{{ name | myPipe:1:2:3:4:5 }} {{ name ? 1 : 2 | myPipe }}

', isInline: true, dependencies: [{ kind: "pipe", type: MyPipe, name: "myPipe" }, { kind: "pipe", type: MyPurePipe, name: "myPurePipe" }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyApp, decorators: [{ type: Component, args: [{ diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/pipes/pipes_my_app_def.js b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/pipes/pipes_my_app_def.js index 415e29d5c6199..454b7bd580ad2 100644 --- a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/pipes/pipes_my_app_def.js +++ b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/pipes/pipes_my_app_def.js @@ -24,6 +24,6 @@ MyApp.ɵcmp = /*@__PURE__*/ $r3$.ɵɵdefineComponent({ $r3$.ɵɵtextInterpolate2("", $r3$.ɵɵpipeBindV(5, 9, $r3$.ɵɵpureFunction1(18, $c0$, ctx.name)), " ", ctx.name ? 1 : $r3$.ɵɵpipeBind1(6, 16, 2), ""); } }, - dependencies: [MyPurePipe, MyPipe], + dependencies: [MyPipe, MyPurePipe], encapsulation: 2 }); diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/GOLDEN_PARTIAL.js b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/GOLDEN_PARTIAL.js index 897c5a044505a..4fc447e8e3c71 100644 --- a/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/GOLDEN_PARTIAL.js +++ b/packages/compiler-cli/test/compliance/test_cases/r3_compiler_compliance/components_and_directives/queries/GOLDEN_PARTIAL.js @@ -451,7 +451,7 @@ MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "0.0.0-
- `, isInline: true, dependencies: [{ kind: "component", type: i0.forwardRef(function () { return ContentQueryComponent; }), selector: "content-query-component" }, { kind: "directive", type: i0.forwardRef(function () { return SomeDirective; }), selector: "[someDir]" }] }); + `, isInline: true, dependencies: [{ kind: "directive", type: i0.forwardRef(function () { return SomeDirective; }), selector: "[someDir]" }, { kind: "component", type: i0.forwardRef(function () { return ContentQueryComponent; }), selector: "content-query-component" }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyApp, decorators: [{ type: Component, args: [{ @@ -529,7 +529,7 @@ MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "0.0.0-
- `, isInline: true, dependencies: [{ kind: "component", type: i0.forwardRef(function () { return ContentQueryComponent; }), selector: "content-query-component" }, { kind: "directive", type: i0.forwardRef(function () { return SomeDirective; }), selector: "[someDir]" }] }); + `, isInline: true, dependencies: [{ kind: "directive", type: i0.forwardRef(function () { return SomeDirective; }), selector: "[someDir]" }, { kind: "component", type: i0.forwardRef(function () { return ContentQueryComponent; }), selector: "content-query-component" }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyApp, decorators: [{ type: Component, args: [{ @@ -700,7 +700,7 @@ MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "0.0.0-
- `, isInline: true, dependencies: [{ kind: "component", type: i0.forwardRef(function () { return ContentQueryComponent; }), selector: "content-query-component" }, { kind: "directive", type: i0.forwardRef(function () { return SomeDirective; }), selector: "[someDir]" }] }); + `, isInline: true, dependencies: [{ kind: "directive", type: i0.forwardRef(function () { return SomeDirective; }), selector: "[someDir]" }, { kind: "component", type: i0.forwardRef(function () { return ContentQueryComponent; }), selector: "content-query-component" }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyApp, decorators: [{ type: Component, args: [{ diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_bindings/property_bindings/GOLDEN_PARTIAL.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_bindings/property_bindings/GOLDEN_PARTIAL.js index e124504d23a8c..f9475299ce11e 100644 --- a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_bindings/property_bindings/GOLDEN_PARTIAL.js +++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_bindings/property_bindings/GOLDEN_PARTIAL.js @@ -519,7 +519,7 @@ MyComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: " - `, isInline: true, dependencies: [{ kind: "directive", type: SpanDir, selector: "span", inputs: ["someProp"] }, { kind: "component", type: CustomEl, selector: "custom-element", inputs: ["prop", "otherProp"] }] }); + `, isInline: true, dependencies: [{ kind: "component", type: CustomEl, selector: "custom-element", inputs: ["prop", "otherProp"] }, { kind: "directive", type: SpanDir, selector: "span", inputs: ["someProp"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyComponent, decorators: [{ type: Component, args: [{ diff --git a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_di/di/GOLDEN_PARTIAL.js b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_di/di/GOLDEN_PARTIAL.js index 1772053770611..673a476cf091e 100644 --- a/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_di/di/GOLDEN_PARTIAL.js +++ b/packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_di/di/GOLDEN_PARTIAL.js @@ -373,7 +373,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDE export class MyApp { } MyApp.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyApp, deps: [], target: i0.ɵɵFactoryTarget.Component }); -MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", type: MyApp, selector: "my-app", ngImport: i0, template: '{{0 | myPipe | myOtherPipe}}', isInline: true, dependencies: [{ kind: "pipe", type: MyOtherPipe, name: "myOtherPipe" }, { kind: "pipe", type: MyPipe, name: "myPipe" }] }); +MyApp.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", type: MyApp, selector: "my-app", ngImport: i0, template: '{{0 | myPipe | myOtherPipe}}', isInline: true, dependencies: [{ kind: "pipe", type: MyPipe, name: "myPipe" }, { kind: "pipe", type: MyOtherPipe, name: "myOtherPipe" }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "0.0.0-PLACEHOLDER", ngImport: i0, type: MyApp, decorators: [{ type: Component, args: [{ selector: 'my-app', template: '{{0 | myPipe | myOtherPipe}}' }] diff --git a/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts b/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts index 4bfc675caa3d4..2e313862dfd0b 100644 --- a/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts +++ b/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts @@ -931,7 +931,7 @@ function allTests(os: string) { const jsContents = trim(env.getContents('test.js')); expect(jsContents) - .toContain('dependencies: [DirectiveA, DirectiveB, ComponentA, ComponentB]'); + .toContain('dependencies: [DirectiveA, ComponentA, DirectiveB, ComponentB]'); }); it('should respect imported module order while processing Directives and Components', () => { @@ -995,7 +995,7 @@ function allTests(os: string) { const jsContents = trim(env.getContents('test.js')); expect(jsContents) - .toContain('dependencies: [DirectiveA, DirectiveB, ComponentA, ComponentB]'); + .toContain('dependencies: [DirectiveA, ComponentA, DirectiveB, ComponentB]'); }); it('should compile Components with a templateUrl in a different rootDir', () => { diff --git a/packages/language-service/src/references_and_rename.ts b/packages/language-service/src/references_and_rename.ts index 648d0f0d2a2fb..d6252755756a8 100644 --- a/packages/language-service/src/references_and_rename.ts +++ b/packages/language-service/src/references_and_rename.ts @@ -8,7 +8,7 @@ import {AST, TmplAstNode} from '@angular/compiler'; import {NgCompiler} from '@angular/compiler-cli/src/ngtsc/core'; import {absoluteFrom} from '@angular/compiler-cli/src/ngtsc/file_system'; -import {MetaType, PipeMeta} from '@angular/compiler-cli/src/ngtsc/metadata'; +import {MetaKind, PipeMeta} from '@angular/compiler-cli/src/ngtsc/metadata'; import {PerfPhase} from '@angular/compiler-cli/src/ngtsc/perf'; import {ProgramDriver} from '@angular/compiler-cli/src/ngtsc/program_driver'; import {SymbolKind} from '@angular/compiler-cli/src/ngtsc/typecheck/api'; @@ -308,7 +308,7 @@ export class RenameBuilder { if (targetDetails.symbol.kind === SymbolKind.Pipe) { const meta = this.compiler.getMeta(targetDetails.symbol.classSymbol.tsSymbol.valueDeclaration); - if (meta === null || meta.type !== MetaType.Pipe) { + if (meta === null || meta.kind !== MetaKind.Pipe) { return null; } const renameRequest = this.buildPipeRenameRequest(meta); @@ -337,7 +337,7 @@ export class RenameBuilder { return null; } const meta = getParentClassMeta(requestNode, this.compiler); - if (meta !== null && meta.type === MetaType.Pipe && meta.nameExpr === requestNode) { + if (meta !== null && meta.kind === MetaKind.Pipe && meta.nameExpr === requestNode) { return this.buildPipeRenameRequest(meta); } else { return {type: RequestKind.DirectFromTypeScript, requestNode};