refactor(ivy): split apart the 'metadata' package in the ngtsc compiler (#27743)
This refactoring moves code around between a few of the ngtsc subpackages, with the goal of having a more logical package structure. Additional interfaces are also introduced where they make sense. The 'metadata' package formerly contained both the partial evaluator, the TypeScriptReflectionHost as well as some other reflection functions, and the Reference interface and various implementations. This package was split into 3 parts. The partial evaluator now has its own package 'partial_evaluator', and exists behind an interface PartialEvaluator instead of a top-level function. In the future this will be useful for reducing churn as the partial evaluator becomes more complicated. The TypeScriptReflectionHost and other miscellaneous functions have moved into a new 'reflection' package. The former 'host' package which contained the ReflectionHost interface and associated types was also merged into this new 'reflection' package. Finally, the Reference APIs were moved to the 'imports' package, which will consolidate all import-related logic in ngtsc. PR Close #27743
This commit is contained in:

committed by
Kara Erickson

parent
37b716b298
commit
2a6108af97
@ -12,8 +12,9 @@ ts_library(
|
||||
deps = [
|
||||
"//packages/compiler",
|
||||
"//packages/compiler-cli/src/ngtsc/diagnostics",
|
||||
"//packages/compiler-cli/src/ngtsc/host",
|
||||
"//packages/compiler-cli/src/ngtsc/metadata",
|
||||
"//packages/compiler-cli/src/ngtsc/imports",
|
||||
"//packages/compiler-cli/src/ngtsc/partial_evaluator",
|
||||
"//packages/compiler-cli/src/ngtsc/reflection",
|
||||
"//packages/compiler-cli/src/ngtsc/transform",
|
||||
"//packages/compiler-cli/src/ngtsc/typecheck",
|
||||
"@ngdeps//@types/node",
|
||||
|
@ -9,8 +9,8 @@
|
||||
import {R3BaseRefMetaData, compileBaseDefFromMetadata} from '@angular/compiler';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {ClassMember, Decorator, ReflectionHost} from '../../host';
|
||||
import {staticallyResolve} from '../../metadata';
|
||||
import {PartialEvaluator} from '../../partial_evaluator';
|
||||
import {ClassMember, Decorator, ReflectionHost} from '../../reflection';
|
||||
import {AnalysisOutput, CompileResult, DecoratorHandler} from '../../transform';
|
||||
import {isAngularCore} from './util';
|
||||
|
||||
@ -26,7 +26,7 @@ function containsNgTopLevelDecorator(decorators: Decorator[] | null): boolean {
|
||||
|
||||
export class BaseDefDecoratorHandler implements
|
||||
DecoratorHandler<R3BaseRefMetaData, R3BaseRefDecoratorDetection> {
|
||||
constructor(private checker: ts.TypeChecker, private reflector: ReflectionHost, ) {}
|
||||
constructor(private reflector: ReflectionHost, private evaluator: PartialEvaluator) {}
|
||||
|
||||
detect(node: ts.ClassDeclaration, decorators: Decorator[]|null): R3BaseRefDecoratorDetection
|
||||
|undefined {
|
||||
@ -69,7 +69,7 @@ export class BaseDefDecoratorHandler implements
|
||||
const args = decorator.args;
|
||||
let value: string|[string, string];
|
||||
if (args && args.length > 0) {
|
||||
const resolvedValue = staticallyResolve(args[0], this.reflector, this.checker);
|
||||
const resolvedValue = this.evaluator.evaluate(args[0]);
|
||||
if (typeof resolvedValue !== 'string') {
|
||||
throw new TypeError('Input alias does not resolve to a string value');
|
||||
}
|
||||
@ -88,7 +88,7 @@ export class BaseDefDecoratorHandler implements
|
||||
const args = decorator.args;
|
||||
let value: string;
|
||||
if (args && args.length > 0) {
|
||||
const resolvedValue = staticallyResolve(args[0], this.reflector, this.checker);
|
||||
const resolvedValue = this.evaluator.evaluate(args[0]);
|
||||
if (typeof resolvedValue !== 'string') {
|
||||
throw new TypeError('Output alias does not resolve to a string value');
|
||||
}
|
||||
|
@ -11,8 +11,9 @@ import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
|
||||
import {Decorator, ReflectionHost} from '../../host';
|
||||
import {AbsoluteReference, Reference, ResolvedReference, filterToMembersWithDecorator, reflectObjectLiteral, staticallyResolve} from '../../metadata';
|
||||
import {ResolvedReference} from '../../imports';
|
||||
import {PartialEvaluator} from '../../partial_evaluator';
|
||||
import {Decorator, ReflectionHost, filterToMembersWithDecorator, reflectObjectLiteral} from '../../reflection';
|
||||
import {AnalysisOutput, CompileResult, DecoratorHandler} from '../../transform';
|
||||
import {TypeCheckContext, TypeCheckableDirectiveMeta} from '../../typecheck';
|
||||
|
||||
@ -37,7 +38,7 @@ export interface ComponentHandlerData {
|
||||
export class ComponentDecoratorHandler implements
|
||||
DecoratorHandler<ComponentHandlerData, Decorator> {
|
||||
constructor(
|
||||
private checker: ts.TypeChecker, private reflector: ReflectionHost,
|
||||
private reflector: ReflectionHost, private evaluator: PartialEvaluator,
|
||||
private scopeRegistry: SelectorScopeRegistry, private isCore: boolean,
|
||||
private resourceLoader: ResourceLoader, private rootDirs: string[],
|
||||
private defaultPreserveWhitespaces: boolean, private i18nUseExternalIds: boolean) {}
|
||||
@ -62,7 +63,7 @@ export class ComponentDecoratorHandler implements
|
||||
|
||||
if (this.resourceLoader.preload !== undefined && component.has('templateUrl')) {
|
||||
const templateUrlExpr = component.get('templateUrl') !;
|
||||
const templateUrl = staticallyResolve(templateUrlExpr, this.reflector, this.checker);
|
||||
const templateUrl = this.evaluator.evaluate(templateUrlExpr);
|
||||
if (typeof templateUrl !== 'string') {
|
||||
throw new FatalDiagnosticError(
|
||||
ErrorCode.VALUE_HAS_WRONG_TYPE, templateUrlExpr, 'templateUrl must be a string');
|
||||
@ -97,7 +98,7 @@ export class ComponentDecoratorHandler implements
|
||||
// @Component inherits @Directive, so begin by extracting the @Directive metadata and building
|
||||
// on it.
|
||||
const directiveResult = extractDirectiveMetadata(
|
||||
node, decorator, this.checker, this.reflector, this.isCore,
|
||||
node, decorator, this.reflector, this.evaluator, this.isCore,
|
||||
this.elementSchemaRegistry.getDefaultComponentElementName());
|
||||
if (directiveResult === undefined) {
|
||||
// `extractDirectiveMetadata` returns undefined when the @Directive has `jit: true`. In this
|
||||
@ -112,7 +113,7 @@ export class ComponentDecoratorHandler implements
|
||||
let templateStr: string|null = null;
|
||||
if (component.has('templateUrl')) {
|
||||
const templateUrlExpr = component.get('templateUrl') !;
|
||||
const templateUrl = staticallyResolve(templateUrlExpr, this.reflector, this.checker);
|
||||
const templateUrl = this.evaluator.evaluate(templateUrlExpr);
|
||||
if (typeof templateUrl !== 'string') {
|
||||
throw new FatalDiagnosticError(
|
||||
ErrorCode.VALUE_HAS_WRONG_TYPE, templateUrlExpr, 'templateUrl must be a string');
|
||||
@ -120,7 +121,7 @@ export class ComponentDecoratorHandler implements
|
||||
templateStr = this.resourceLoader.load(templateUrl, containingFile);
|
||||
} else if (component.has('template')) {
|
||||
const templateExpr = component.get('template') !;
|
||||
const resolvedTemplate = staticallyResolve(templateExpr, this.reflector, this.checker);
|
||||
const resolvedTemplate = this.evaluator.evaluate(templateExpr);
|
||||
if (typeof resolvedTemplate !== 'string') {
|
||||
throw new FatalDiagnosticError(
|
||||
ErrorCode.VALUE_HAS_WRONG_TYPE, templateExpr, 'template must be a string');
|
||||
@ -134,7 +135,7 @@ export class ComponentDecoratorHandler implements
|
||||
let preserveWhitespaces: boolean = this.defaultPreserveWhitespaces;
|
||||
if (component.has('preserveWhitespaces')) {
|
||||
const expr = component.get('preserveWhitespaces') !;
|
||||
const value = staticallyResolve(expr, this.reflector, this.checker);
|
||||
const value = this.evaluator.evaluate(expr);
|
||||
if (typeof value !== 'boolean') {
|
||||
throw new FatalDiagnosticError(
|
||||
ErrorCode.VALUE_HAS_WRONG_TYPE, expr, 'preserveWhitespaces must be a boolean');
|
||||
@ -161,7 +162,7 @@ export class ComponentDecoratorHandler implements
|
||||
let interpolation: InterpolationConfig = DEFAULT_INTERPOLATION_CONFIG;
|
||||
if (component.has('interpolation')) {
|
||||
const expr = component.get('interpolation') !;
|
||||
const value = staticallyResolve(expr, this.reflector, this.checker);
|
||||
const value = this.evaluator.evaluate(expr);
|
||||
if (!Array.isArray(value) || value.length !== 2 ||
|
||||
!value.every(element => typeof element === 'string')) {
|
||||
throw new FatalDiagnosticError(
|
||||
@ -200,21 +201,21 @@ export class ComponentDecoratorHandler implements
|
||||
const coreModule = this.isCore ? undefined : '@angular/core';
|
||||
const viewChildFromFields = queriesFromFields(
|
||||
filterToMembersWithDecorator(decoratedElements, 'ViewChild', coreModule), this.reflector,
|
||||
this.checker);
|
||||
this.evaluator);
|
||||
const viewChildrenFromFields = queriesFromFields(
|
||||
filterToMembersWithDecorator(decoratedElements, 'ViewChildren', coreModule), this.reflector,
|
||||
this.checker);
|
||||
this.evaluator);
|
||||
const viewQueries = [...viewChildFromFields, ...viewChildrenFromFields];
|
||||
|
||||
if (component.has('queries')) {
|
||||
const queriesFromDecorator = extractQueriesFromDecorator(
|
||||
component.get('queries') !, this.reflector, this.checker, this.isCore);
|
||||
component.get('queries') !, this.reflector, this.evaluator, this.isCore);
|
||||
viewQueries.push(...queriesFromDecorator.view);
|
||||
}
|
||||
|
||||
let styles: string[]|null = null;
|
||||
if (component.has('styles')) {
|
||||
styles = parseFieldArrayValue(component, 'styles', this.reflector, this.checker);
|
||||
styles = parseFieldArrayValue(component, 'styles', this.evaluator);
|
||||
}
|
||||
|
||||
let styleUrls = this._extractStyleUrls(component);
|
||||
@ -227,8 +228,7 @@ export class ComponentDecoratorHandler implements
|
||||
|
||||
let encapsulation: number = 0;
|
||||
if (component.has('encapsulation')) {
|
||||
encapsulation = parseInt(staticallyResolve(
|
||||
component.get('encapsulation') !, this.reflector, this.checker) as string);
|
||||
encapsulation = parseInt(this.evaluator.evaluate(component.get('encapsulation') !) as string);
|
||||
}
|
||||
|
||||
let animations: Expression|null = null;
|
||||
@ -333,7 +333,7 @@ export class ComponentDecoratorHandler implements
|
||||
}
|
||||
|
||||
const styleUrlsExpr = component.get('styleUrls') !;
|
||||
const styleUrls = staticallyResolve(styleUrlsExpr, this.reflector, this.checker);
|
||||
const styleUrls = this.evaluator.evaluate(styleUrlsExpr);
|
||||
if (!Array.isArray(styleUrls) || !styleUrls.every(url => typeof url === 'string')) {
|
||||
throw new FatalDiagnosticError(
|
||||
ErrorCode.VALUE_HAS_WRONG_TYPE, styleUrlsExpr, 'styleUrls must be an array of strings');
|
||||
|
@ -10,8 +10,9 @@ import {ConstantPool, Expression, R3DirectiveMetadata, R3QueryMetadata, Statemen
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
|
||||
import {ClassMember, ClassMemberKind, Decorator, Import, ReflectionHost} from '../../host';
|
||||
import {Reference, ResolvedReference, filterToMembersWithDecorator, reflectObjectLiteral, staticallyResolve} from '../../metadata';
|
||||
import {Reference, ResolvedReference} from '../../imports';
|
||||
import {PartialEvaluator} from '../../partial_evaluator';
|
||||
import {ClassMember, ClassMemberKind, Decorator, ReflectionHost, filterToMembersWithDecorator, reflectObjectLiteral} from '../../reflection';
|
||||
import {AnalysisOutput, CompileResult, DecoratorHandler} from '../../transform';
|
||||
|
||||
import {generateSetClassMetadataCall} from './metadata';
|
||||
@ -27,7 +28,7 @@ export interface DirectiveHandlerData {
|
||||
export class DirectiveDecoratorHandler implements
|
||||
DecoratorHandler<DirectiveHandlerData, Decorator> {
|
||||
constructor(
|
||||
private checker: ts.TypeChecker, private reflector: ReflectionHost,
|
||||
private reflector: ReflectionHost, private evaluator: PartialEvaluator,
|
||||
private scopeRegistry: SelectorScopeRegistry, private isCore: boolean) {}
|
||||
|
||||
detect(node: ts.Declaration, decorators: Decorator[]|null): Decorator|undefined {
|
||||
@ -40,7 +41,7 @@ export class DirectiveDecoratorHandler implements
|
||||
|
||||
analyze(node: ts.ClassDeclaration, decorator: Decorator): AnalysisOutput<DirectiveHandlerData> {
|
||||
const directiveResult =
|
||||
extractDirectiveMetadata(node, decorator, this.checker, this.reflector, this.isCore);
|
||||
extractDirectiveMetadata(node, decorator, this.reflector, this.evaluator, this.isCore);
|
||||
const analysis = directiveResult && directiveResult.metadata;
|
||||
|
||||
// If the directive has a selector, it should be registered with the `SelectorScopeRegistry` so
|
||||
@ -92,8 +93,8 @@ export class DirectiveDecoratorHandler implements
|
||||
* Helper function to extract metadata from a `Directive` or `Component`.
|
||||
*/
|
||||
export function extractDirectiveMetadata(
|
||||
clazz: ts.ClassDeclaration, decorator: Decorator, checker: ts.TypeChecker,
|
||||
reflector: ReflectionHost, isCore: boolean, defaultSelector: string | null = null): {
|
||||
clazz: ts.ClassDeclaration, decorator: Decorator, reflector: ReflectionHost,
|
||||
evaluator: PartialEvaluator, isCore: boolean, defaultSelector: string | null = null): {
|
||||
decorator: Map<string, ts.Expression>,
|
||||
metadata: R3DirectiveMetadata,
|
||||
decoratedElements: ClassMember[],
|
||||
@ -127,29 +128,29 @@ export function extractDirectiveMetadata(
|
||||
// Construct the map of inputs both from the @Directive/@Component
|
||||
// decorator, and the decorated
|
||||
// fields.
|
||||
const inputsFromMeta = parseFieldToPropertyMapping(directive, 'inputs', reflector, checker);
|
||||
const inputsFromMeta = parseFieldToPropertyMapping(directive, 'inputs', evaluator);
|
||||
const inputsFromFields = parseDecoratedFields(
|
||||
filterToMembersWithDecorator(decoratedElements, 'Input', coreModule), reflector, checker,
|
||||
filterToMembersWithDecorator(decoratedElements, 'Input', coreModule), evaluator,
|
||||
resolveInput);
|
||||
|
||||
// And outputs.
|
||||
const outputsFromMeta = parseFieldToPropertyMapping(directive, 'outputs', reflector, checker);
|
||||
const outputsFromMeta = parseFieldToPropertyMapping(directive, 'outputs', evaluator);
|
||||
const outputsFromFields = parseDecoratedFields(
|
||||
filterToMembersWithDecorator(decoratedElements, 'Output', coreModule), reflector, checker,
|
||||
filterToMembersWithDecorator(decoratedElements, 'Output', coreModule), evaluator,
|
||||
resolveOutput) as{[field: string]: string};
|
||||
// Construct the list of queries.
|
||||
const contentChildFromFields = queriesFromFields(
|
||||
filterToMembersWithDecorator(decoratedElements, 'ContentChild', coreModule), reflector,
|
||||
checker);
|
||||
evaluator);
|
||||
const contentChildrenFromFields = queriesFromFields(
|
||||
filterToMembersWithDecorator(decoratedElements, 'ContentChildren', coreModule), reflector,
|
||||
checker);
|
||||
evaluator);
|
||||
|
||||
const queries = [...contentChildFromFields, ...contentChildrenFromFields];
|
||||
|
||||
if (directive.has('queries')) {
|
||||
const queriesFromDecorator =
|
||||
extractQueriesFromDecorator(directive.get('queries') !, reflector, checker, isCore);
|
||||
extractQueriesFromDecorator(directive.get('queries') !, reflector, evaluator, isCore);
|
||||
queries.push(...queriesFromDecorator.content);
|
||||
}
|
||||
|
||||
@ -157,7 +158,7 @@ export function extractDirectiveMetadata(
|
||||
let selector = defaultSelector;
|
||||
if (directive.has('selector')) {
|
||||
const expr = directive.get('selector') !;
|
||||
const resolved = staticallyResolve(expr, reflector, checker);
|
||||
const resolved = evaluator.evaluate(expr);
|
||||
if (typeof resolved !== 'string') {
|
||||
throw new FatalDiagnosticError(
|
||||
ErrorCode.VALUE_HAS_WRONG_TYPE, expr, `selector must be a string`);
|
||||
@ -165,7 +166,7 @@ export function extractDirectiveMetadata(
|
||||
selector = resolved;
|
||||
}
|
||||
|
||||
const host = extractHostBindings(directive, decoratedElements, reflector, checker, coreModule);
|
||||
const host = extractHostBindings(directive, decoratedElements, evaluator, coreModule);
|
||||
|
||||
const providers: Expression|null =
|
||||
directive.has('providers') ? new WrappedNodeExpr(directive.get('providers') !) : null;
|
||||
@ -179,7 +180,7 @@ export function extractDirectiveMetadata(
|
||||
let exportAs: string|null = null;
|
||||
if (directive.has('exportAs')) {
|
||||
const expr = directive.get('exportAs') !;
|
||||
const resolved = staticallyResolve(expr, reflector, checker);
|
||||
const resolved = evaluator.evaluate(expr);
|
||||
if (typeof resolved !== 'string') {
|
||||
throw new FatalDiagnosticError(
|
||||
ErrorCode.VALUE_HAS_WRONG_TYPE, expr, `exportAs must be a string`);
|
||||
@ -207,14 +208,14 @@ export function extractDirectiveMetadata(
|
||||
|
||||
export function extractQueryMetadata(
|
||||
exprNode: ts.Node, name: string, args: ReadonlyArray<ts.Expression>, propertyName: string,
|
||||
reflector: ReflectionHost, checker: ts.TypeChecker): R3QueryMetadata {
|
||||
reflector: ReflectionHost, evaluator: PartialEvaluator): R3QueryMetadata {
|
||||
if (args.length === 0) {
|
||||
throw new FatalDiagnosticError(
|
||||
ErrorCode.DECORATOR_ARITY_WRONG, exprNode, `@${name} must have arguments`);
|
||||
}
|
||||
const first = name === 'ViewChild' || name === 'ContentChild';
|
||||
const node = unwrapForwardRef(args[0], reflector);
|
||||
const arg = staticallyResolve(node, reflector, checker);
|
||||
const arg = evaluator.evaluate(node);
|
||||
|
||||
// Extract the predicate
|
||||
let predicate: Expression|string[]|null = null;
|
||||
@ -244,7 +245,7 @@ export function extractQueryMetadata(
|
||||
}
|
||||
|
||||
if (options.has('descendants')) {
|
||||
const descendantsValue = staticallyResolve(options.get('descendants') !, reflector, checker);
|
||||
const descendantsValue = evaluator.evaluate(options.get('descendants') !);
|
||||
if (typeof descendantsValue !== 'boolean') {
|
||||
throw new Error(`@${name} options.descendants must be a boolean`);
|
||||
}
|
||||
@ -261,7 +262,7 @@ export function extractQueryMetadata(
|
||||
}
|
||||
|
||||
export function extractQueriesFromDecorator(
|
||||
queryData: ts.Expression, reflector: ReflectionHost, checker: ts.TypeChecker,
|
||||
queryData: ts.Expression, reflector: ReflectionHost, evaluator: PartialEvaluator,
|
||||
isCore: boolean): {
|
||||
content: R3QueryMetadata[],
|
||||
view: R3QueryMetadata[],
|
||||
@ -283,7 +284,7 @@ export function extractQueriesFromDecorator(
|
||||
}
|
||||
|
||||
const query = extractQueryMetadata(
|
||||
queryExpr, type.name, queryExpr.arguments || [], propertyName, reflector, checker);
|
||||
queryExpr, type.name, queryExpr.arguments || [], propertyName, reflector, evaluator);
|
||||
if (type.name.startsWith('Content')) {
|
||||
content.push(query);
|
||||
} else {
|
||||
@ -307,14 +308,14 @@ function isStringArrayOrDie(value: any, name: string): value is string[] {
|
||||
}
|
||||
|
||||
export function parseFieldArrayValue(
|
||||
directive: Map<string, ts.Expression>, field: string, reflector: ReflectionHost,
|
||||
checker: ts.TypeChecker): null|string[] {
|
||||
directive: Map<string, ts.Expression>, field: string, evaluator: PartialEvaluator): null|
|
||||
string[] {
|
||||
if (!directive.has(field)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Resolve the field of interest from the directive metadata to a string[].
|
||||
const value = staticallyResolve(directive.get(field) !, reflector, checker);
|
||||
const value = evaluator.evaluate(directive.get(field) !);
|
||||
if (!isStringArrayOrDie(value, field)) {
|
||||
throw new Error(`Failed to resolve @Directive.${field}`);
|
||||
}
|
||||
@ -327,9 +328,9 @@ export function parseFieldArrayValue(
|
||||
* correctly shaped metadata object.
|
||||
*/
|
||||
function parseFieldToPropertyMapping(
|
||||
directive: Map<string, ts.Expression>, field: string, reflector: ReflectionHost,
|
||||
checker: ts.TypeChecker): {[field: string]: string} {
|
||||
const metaValues = parseFieldArrayValue(directive, field, reflector, checker);
|
||||
directive: Map<string, ts.Expression>, field: string,
|
||||
evaluator: PartialEvaluator): {[field: string]: string} {
|
||||
const metaValues = parseFieldArrayValue(directive, field, evaluator);
|
||||
if (!metaValues) {
|
||||
return EMPTY_OBJECT;
|
||||
}
|
||||
@ -350,8 +351,7 @@ function parseFieldToPropertyMapping(
|
||||
* object.
|
||||
*/
|
||||
function parseDecoratedFields(
|
||||
fields: {member: ClassMember, decorators: Decorator[]}[], reflector: ReflectionHost,
|
||||
checker: ts.TypeChecker,
|
||||
fields: {member: ClassMember, decorators: Decorator[]}[], evaluator: PartialEvaluator,
|
||||
mapValueResolver: (publicName: string, internalName: string) =>
|
||||
string | [string, string]): {[field: string]: string | [string, string]} {
|
||||
return fields.reduce(
|
||||
@ -363,7 +363,7 @@ function parseDecoratedFields(
|
||||
if (decorator.args == null || decorator.args.length === 0) {
|
||||
results[fieldName] = fieldName;
|
||||
} else if (decorator.args.length === 1) {
|
||||
const property = staticallyResolve(decorator.args[0], reflector, checker);
|
||||
const property = evaluator.evaluate(decorator.args[0]);
|
||||
if (typeof property !== 'string') {
|
||||
throw new Error(`Decorator argument must resolve to a string`);
|
||||
}
|
||||
@ -389,7 +389,7 @@ function resolveOutput(publicName: string, internalName: string) {
|
||||
|
||||
export function queriesFromFields(
|
||||
fields: {member: ClassMember, decorators: Decorator[]}[], reflector: ReflectionHost,
|
||||
checker: ts.TypeChecker): R3QueryMetadata[] {
|
||||
evaluator: PartialEvaluator): R3QueryMetadata[] {
|
||||
return fields.map(({member, decorators}) => {
|
||||
if (decorators.length !== 1) {
|
||||
throw new Error(`Cannot have multiple query decorators on the same class member`);
|
||||
@ -398,7 +398,7 @@ export function queriesFromFields(
|
||||
}
|
||||
const decorator = decorators[0];
|
||||
return extractQueryMetadata(
|
||||
decorator.node, decorator.name, decorator.args || [], member.name, reflector, checker);
|
||||
decorator.node, decorator.name, decorator.args || [], member.name, reflector, evaluator);
|
||||
});
|
||||
}
|
||||
|
||||
@ -412,8 +412,8 @@ type StringMap = {
|
||||
};
|
||||
|
||||
function extractHostBindings(
|
||||
metadata: Map<string, ts.Expression>, members: ClassMember[], reflector: ReflectionHost,
|
||||
checker: ts.TypeChecker, coreModule: string | undefined): {
|
||||
metadata: Map<string, ts.Expression>, members: ClassMember[], evaluator: PartialEvaluator,
|
||||
coreModule: string | undefined): {
|
||||
attributes: StringMap,
|
||||
listeners: StringMap,
|
||||
properties: StringMap,
|
||||
@ -421,7 +421,7 @@ function extractHostBindings(
|
||||
let hostMetadata: StringMap = {};
|
||||
if (metadata.has('host')) {
|
||||
const expr = metadata.get('host') !;
|
||||
const hostMetaMap = staticallyResolve(expr, reflector, checker);
|
||||
const hostMetaMap = evaluator.evaluate(expr);
|
||||
if (!(hostMetaMap instanceof Map)) {
|
||||
throw new FatalDiagnosticError(
|
||||
ErrorCode.DECORATOR_ARG_NOT_LITERAL, expr, `Decorator host metadata must be an object`);
|
||||
@ -445,7 +445,7 @@ function extractHostBindings(
|
||||
throw new Error(`@HostBinding() can have at most one argument`);
|
||||
}
|
||||
|
||||
const resolved = staticallyResolve(decorator.args[0], reflector, checker);
|
||||
const resolved = evaluator.evaluate(decorator.args[0]);
|
||||
if (typeof resolved !== 'string') {
|
||||
throw new Error(`@HostBinding()'s argument must be a string`);
|
||||
}
|
||||
@ -469,7 +469,7 @@ function extractHostBindings(
|
||||
`@HostListener() can have at most two arguments`);
|
||||
}
|
||||
|
||||
const resolved = staticallyResolve(decorator.args[0], reflector, checker);
|
||||
const resolved = evaluator.evaluate(decorator.args[0]);
|
||||
if (typeof resolved !== 'string') {
|
||||
throw new FatalDiagnosticError(
|
||||
ErrorCode.VALUE_HAS_WRONG_TYPE, decorator.args[0],
|
||||
@ -479,7 +479,7 @@ function extractHostBindings(
|
||||
eventName = resolved;
|
||||
|
||||
if (decorator.args.length === 2) {
|
||||
const resolvedArgs = staticallyResolve(decorator.args[1], reflector, checker);
|
||||
const resolvedArgs = evaluator.evaluate(decorator.args[1]);
|
||||
if (!isStringArrayOrDie(resolvedArgs, '@HostListener.args')) {
|
||||
throw new FatalDiagnosticError(
|
||||
ErrorCode.VALUE_HAS_WRONG_TYPE, decorator.args[1],
|
||||
|
@ -10,8 +10,7 @@ import {Expression, LiteralExpr, R3DependencyMetadata, R3InjectableMetadata, R3R
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
|
||||
import {Decorator, ReflectionHost} from '../../host';
|
||||
import {reflectObjectLiteral} from '../../metadata';
|
||||
import {Decorator, ReflectionHost, reflectObjectLiteral} from '../../reflection';
|
||||
import {AnalysisOutput, CompileResult, DecoratorHandler} from '../../transform';
|
||||
|
||||
import {generateSetClassMetadataCall} from './metadata';
|
||||
|
@ -9,7 +9,7 @@
|
||||
import {ExternalExpr, Identifiers, InvokeFunctionExpr, Statement, WrappedNodeExpr} from '@angular/compiler';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {CtorParameter, Decorator, ReflectionHost} from '../../host';
|
||||
import {CtorParameter, Decorator, ReflectionHost} from '../../reflection';
|
||||
|
||||
/**
|
||||
* Given a class declaration, generate a call to `setClassMetadata` with the Angular metadata
|
||||
|
@ -10,8 +10,9 @@ import {Expression, LiteralArrayExpr, R3InjectorMetadata, R3NgModuleMetadata, R3
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
|
||||
import {Decorator, ReflectionHost} from '../../host';
|
||||
import {Reference, ResolvedReference, ResolvedValue, reflectObjectLiteral, staticallyResolve, typeNodeToValueExpr} from '../../metadata';
|
||||
import {Reference, ResolvedReference} from '../../imports';
|
||||
import {PartialEvaluator, ResolvedValue} from '../../partial_evaluator';
|
||||
import {Decorator, ReflectionHost, reflectObjectLiteral, typeNodeToValueExpr} from '../../reflection';
|
||||
import {AnalysisOutput, CompileResult, DecoratorHandler} from '../../transform';
|
||||
|
||||
import {generateSetClassMetadataCall} from './metadata';
|
||||
@ -32,7 +33,7 @@ export interface NgModuleAnalysis {
|
||||
*/
|
||||
export class NgModuleDecoratorHandler implements DecoratorHandler<NgModuleAnalysis, Decorator> {
|
||||
constructor(
|
||||
private checker: ts.TypeChecker, private reflector: ReflectionHost,
|
||||
private reflector: ReflectionHost, private evaluator: PartialEvaluator,
|
||||
private scopeRegistry: SelectorScopeRegistry, private referencesRegistry: ReferencesRegistry,
|
||||
private isCore: boolean) {}
|
||||
|
||||
@ -72,32 +73,30 @@ export class NgModuleDecoratorHandler implements DecoratorHandler<NgModuleAnalys
|
||||
let declarations: Reference<ts.Declaration>[] = [];
|
||||
if (ngModule.has('declarations')) {
|
||||
const expr = ngModule.get('declarations') !;
|
||||
const declarationMeta = staticallyResolve(expr, this.reflector, this.checker);
|
||||
const declarationMeta = this.evaluator.evaluate(expr);
|
||||
declarations = this.resolveTypeList(expr, declarationMeta, 'declarations');
|
||||
this.referencesRegistry.add(...declarations);
|
||||
}
|
||||
let imports: Reference<ts.Declaration>[] = [];
|
||||
if (ngModule.has('imports')) {
|
||||
const expr = ngModule.get('imports') !;
|
||||
const importsMeta = staticallyResolve(
|
||||
expr, this.reflector, this.checker,
|
||||
ref => this._extractModuleFromModuleWithProvidersFn(ref.node));
|
||||
const importsMeta = this.evaluator.evaluate(
|
||||
expr, ref => this._extractModuleFromModuleWithProvidersFn(ref.node));
|
||||
imports = this.resolveTypeList(expr, importsMeta, 'imports');
|
||||
this.referencesRegistry.add(...imports);
|
||||
}
|
||||
let exports: Reference<ts.Declaration>[] = [];
|
||||
if (ngModule.has('exports')) {
|
||||
const expr = ngModule.get('exports') !;
|
||||
const exportsMeta = staticallyResolve(
|
||||
expr, this.reflector, this.checker,
|
||||
ref => this._extractModuleFromModuleWithProvidersFn(ref.node));
|
||||
const exportsMeta = this.evaluator.evaluate(
|
||||
expr, ref => this._extractModuleFromModuleWithProvidersFn(ref.node));
|
||||
exports = this.resolveTypeList(expr, exportsMeta, 'exports');
|
||||
this.referencesRegistry.add(...exports);
|
||||
}
|
||||
let bootstrap: Reference<ts.Declaration>[] = [];
|
||||
if (ngModule.has('bootstrap')) {
|
||||
const expr = ngModule.get('bootstrap') !;
|
||||
const bootstrapMeta = staticallyResolve(expr, this.reflector, this.checker);
|
||||
const bootstrapMeta = this.evaluator.evaluate(expr);
|
||||
bootstrap = this.resolveTypeList(expr, bootstrapMeta, 'bootstrap');
|
||||
this.referencesRegistry.add(...bootstrap);
|
||||
}
|
||||
|
@ -10,8 +10,8 @@ import {LiteralExpr, R3PipeMetadata, Statement, WrappedNodeExpr, compilePipeFrom
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
|
||||
import {Decorator, ReflectionHost} from '../../host';
|
||||
import {reflectObjectLiteral, staticallyResolve} from '../../metadata';
|
||||
import {PartialEvaluator} from '../../partial_evaluator';
|
||||
import {Decorator, ReflectionHost, reflectObjectLiteral} from '../../reflection';
|
||||
import {AnalysisOutput, CompileResult, DecoratorHandler} from '../../transform';
|
||||
|
||||
import {generateSetClassMetadataCall} from './metadata';
|
||||
@ -25,7 +25,7 @@ export interface PipeHandlerData {
|
||||
|
||||
export class PipeDecoratorHandler implements DecoratorHandler<PipeHandlerData, Decorator> {
|
||||
constructor(
|
||||
private checker: ts.TypeChecker, private reflector: ReflectionHost,
|
||||
private reflector: ReflectionHost, private evaluator: PartialEvaluator,
|
||||
private scopeRegistry: SelectorScopeRegistry, private isCore: boolean) {}
|
||||
|
||||
detect(node: ts.Declaration, decorators: Decorator[]|null): Decorator|undefined {
|
||||
@ -63,7 +63,7 @@ export class PipeDecoratorHandler implements DecoratorHandler<PipeHandlerData, D
|
||||
ErrorCode.PIPE_MISSING_NAME, meta, `@Pipe decorator is missing name field`);
|
||||
}
|
||||
const pipeNameExpr = pipe.get('name') !;
|
||||
const pipeName = staticallyResolve(pipeNameExpr, this.reflector, this.checker);
|
||||
const pipeName = this.evaluator.evaluate(pipeNameExpr);
|
||||
if (typeof pipeName !== 'string') {
|
||||
throw new FatalDiagnosticError(
|
||||
ErrorCode.VALUE_HAS_WRONG_TYPE, pipeNameExpr, `@Pipe.name must be a string`);
|
||||
@ -73,7 +73,7 @@ export class PipeDecoratorHandler implements DecoratorHandler<PipeHandlerData, D
|
||||
let pure = true;
|
||||
if (pipe.has('pure')) {
|
||||
const expr = pipe.get('pure') !;
|
||||
const pureValue = staticallyResolve(expr, this.reflector, this.checker);
|
||||
const pureValue = this.evaluator.evaluate(expr);
|
||||
if (typeof pureValue !== 'boolean') {
|
||||
throw new FatalDiagnosticError(
|
||||
ErrorCode.VALUE_HAS_WRONG_TYPE, expr, `@Pipe.pure must be a boolean`);
|
||||
|
@ -7,8 +7,8 @@
|
||||
*/
|
||||
|
||||
import * as ts from 'typescript';
|
||||
import {Declaration} from '../../host';
|
||||
import {Reference} from '../../metadata';
|
||||
import {Reference} from '../../imports';
|
||||
import {Declaration} from '../../reflection';
|
||||
|
||||
/**
|
||||
* Implement this interface if you want DecoratorHandlers to register
|
||||
|
@ -6,12 +6,11 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Expression, ExternalExpr, ExternalReference, WrappedNodeExpr} from '@angular/compiler';
|
||||
import {Expression, WrappedNodeExpr} from '@angular/compiler';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {ReflectionHost} from '../../host';
|
||||
import {AbsoluteReference, Reference, ResolvedReference, reflectTypeEntityToDeclaration} from '../../metadata';
|
||||
import {reflectIdentifierOfDeclaration, reflectNameOfDeclaration} from '../../metadata/src/reflector';
|
||||
import {AbsoluteReference, Reference, ResolvedReference} from '../../imports';
|
||||
import {ReflectionHost, reflectIdentifierOfDeclaration, reflectNameOfDeclaration, reflectTypeEntityToDeclaration} from '../../reflection';
|
||||
import {TypeCheckableDirectiveMeta} from '../../typecheck';
|
||||
|
||||
import {extractDirectiveGuards} from './util';
|
||||
|
@ -6,12 +6,12 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Expression, R3DependencyMetadata, R3Reference, R3ResolvedDependencyType, WrappedNodeExpr} from '@angular/compiler';
|
||||
import {R3DependencyMetadata, R3Reference, R3ResolvedDependencyType, WrappedNodeExpr} from '@angular/compiler';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
|
||||
import {ClassMemberKind, Decorator, ReflectionHost} from '../../host';
|
||||
import {AbsoluteReference, ImportMode, Reference} from '../../metadata';
|
||||
import {AbsoluteReference, ImportMode, Reference} from '../../imports';
|
||||
import {ClassMemberKind, Decorator, ReflectionHost} from '../../reflection';
|
||||
|
||||
export function getConstructorDependencies(
|
||||
clazz: ts.ClassDeclaration, reflector: ReflectionHost, isCore: boolean): R3DependencyMetadata[]|
|
||||
|
@ -13,7 +13,9 @@ ts_library(
|
||||
"//packages/compiler",
|
||||
"//packages/compiler-cli/src/ngtsc/annotations",
|
||||
"//packages/compiler-cli/src/ngtsc/diagnostics",
|
||||
"//packages/compiler-cli/src/ngtsc/metadata",
|
||||
"//packages/compiler-cli/src/ngtsc/imports",
|
||||
"//packages/compiler-cli/src/ngtsc/partial_evaluator",
|
||||
"//packages/compiler-cli/src/ngtsc/reflection",
|
||||
"//packages/compiler-cli/src/ngtsc/testing",
|
||||
"//packages/compiler-cli/src/ngtsc/translator",
|
||||
"@ngdeps//typescript",
|
||||
|
@ -9,7 +9,9 @@
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {ErrorCode, FatalDiagnosticError} from '../../diagnostics';
|
||||
import {TypeScriptReflectionHost} from '../../metadata';
|
||||
import {PartialEvaluator} from '../../partial_evaluator';
|
||||
import {TypeScriptReflectionHost} from '../../reflection';
|
||||
|
||||
import {getDeclaration, makeProgram} from '../../testing/in_memory_typescript';
|
||||
import {ResourceLoader} from '../src/api';
|
||||
import {ComponentDecoratorHandler} from '../src/component';
|
||||
@ -38,8 +40,9 @@ describe('ComponentDecoratorHandler', () => {
|
||||
]);
|
||||
const checker = program.getTypeChecker();
|
||||
const host = new TypeScriptReflectionHost(checker);
|
||||
const evaluator = new PartialEvaluator(host, checker);
|
||||
const handler = new ComponentDecoratorHandler(
|
||||
checker, host, new SelectorScopeRegistry(checker, host), false, new NoopResourceLoader(),
|
||||
host, evaluator, new SelectorScopeRegistry(checker, host), false, new NoopResourceLoader(),
|
||||
[''], false, true);
|
||||
const TestCmp = getDeclaration(program, 'entry.ts', 'TestCmp', ts.isClassDeclaration);
|
||||
const detected = handler.detect(TestCmp, host.getDecoratorsOfDeclaration(TestCmp));
|
||||
|
@ -6,12 +6,12 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Statement} from '@angular/compiler';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {TypeScriptReflectionHost} from '../../metadata';
|
||||
import {TypeScriptReflectionHost} from '../../reflection';
|
||||
import {getDeclaration, makeProgram} from '../../testing/in_memory_typescript';
|
||||
import {ImportManager, translateStatement} from '../../translator';
|
||||
|
||||
import {generateSetClassMetadataCall} from '../src/metadata';
|
||||
|
||||
const CORE = {
|
||||
|
@ -8,10 +8,10 @@
|
||||
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {TypeScriptReflectionHost} from '../../metadata';
|
||||
import {AbsoluteReference, ResolvedReference} from '../../metadata/src/resolver';
|
||||
import {AbsoluteReference, ResolvedReference} from '../../imports';
|
||||
import {TypeScriptReflectionHost} from '../../reflection';
|
||||
import {getDeclaration, makeProgram} from '../../testing/in_memory_typescript';
|
||||
import {NgModuleDecoratorHandler} from '../src/ng_module';
|
||||
|
||||
import {SelectorScopeRegistry} from '../src/selector_scope';
|
||||
|
||||
describe('SelectorScopeRegistry', () => {
|
||||
|
Reference in New Issue
Block a user