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};