refactor(ivy): use wrapped metadata in all DecoratorHandlers (#26860)

Previously, the Directive, Injectable, and Pipe DecoratorHandlers were
directly returning @angular/compiler metadata from their analyze() steps.
This precludes returning any additional information along with that
metadata. This commit introduces a wrapper interface for these handlers,
opening the door for additional information to be returned from analyze().

Testing strategy: this is a refactor commit, existing test coverage is
sufficient.

PR Close #26860
This commit is contained in:
Alex Rickabaugh 2018-10-30 10:04:10 -07:00 committed by Matias Niemelä
parent 84e311038d
commit afbee736ea
3 changed files with 36 additions and 19 deletions

View File

@ -19,7 +19,9 @@ import {extractDirectiveGuards, getConstructorDependencies, isAngularCore, unwra
const EMPTY_OBJECT: {[key: string]: string} = {};
export class DirectiveDecoratorHandler implements DecoratorHandler<R3DirectiveMetadata, Decorator> {
export interface DirectiveHandlerData { meta: R3DirectiveMetadata; }
export class DirectiveDecoratorHandler implements
DecoratorHandler<DirectiveHandlerData, Decorator> {
constructor(
private checker: ts.TypeChecker, private reflector: ReflectionHost,
private scopeRegistry: SelectorScopeRegistry, private isCore: boolean) {}
@ -32,7 +34,7 @@ export class DirectiveDecoratorHandler implements DecoratorHandler<R3DirectiveMe
decorator => decorator.name === 'Directive' && (this.isCore || isAngularCore(decorator)));
}
analyze(node: ts.ClassDeclaration, decorator: Decorator): AnalysisOutput<R3DirectiveMetadata> {
analyze(node: ts.ClassDeclaration, decorator: Decorator): AnalysisOutput<DirectiveHandlerData> {
const directiveResult =
extractDirectiveMetadata(node, decorator, this.checker, this.reflector, this.isCore);
const analysis = directiveResult && directiveResult.metadata;
@ -54,12 +56,20 @@ export class DirectiveDecoratorHandler implements DecoratorHandler<R3DirectiveMe
});
}
return {analysis};
if (analysis === undefined) {
return {};
}
return {
analysis: {
meta: analysis,
}
};
}
compile(node: ts.ClassDeclaration, analysis: R3DirectiveMetadata, pool: ConstantPool):
compile(node: ts.ClassDeclaration, analysis: DirectiveHandlerData, pool: ConstantPool):
CompileResult {
const res = compileDirectiveFromMetadata(analysis, pool, makeBindingParser());
const res = compileDirectiveFromMetadata(analysis.meta, pool, makeBindingParser());
return {
name: 'ngDirectiveDef',
initializer: res.expression,

View File

@ -16,12 +16,13 @@ import {AnalysisOutput, CompileResult, DecoratorHandler} from '../../transform';
import {getConstructorDependencies, isAngularCore} from './util';
export interface InjectableHandlerData { meta: R3InjectableMetadata; }
/**
* Adapts the `compileIvyInjectable` compiler for `@Injectable` decorators to the Ivy compiler.
*/
export class InjectableDecoratorHandler implements
DecoratorHandler<R3InjectableMetadata, Decorator> {
DecoratorHandler<InjectableHandlerData, Decorator> {
constructor(private reflector: ReflectionHost, private isCore: boolean) {}
detect(node: ts.Declaration, decorators: Decorator[]|null): Decorator|undefined {
@ -32,14 +33,16 @@ export class InjectableDecoratorHandler implements
decorator => decorator.name === 'Injectable' && (this.isCore || isAngularCore(decorator)));
}
analyze(node: ts.ClassDeclaration, decorator: Decorator): AnalysisOutput<R3InjectableMetadata> {
analyze(node: ts.ClassDeclaration, decorator: Decorator): AnalysisOutput<InjectableHandlerData> {
return {
analysis: extractInjectableMetadata(node, decorator, this.reflector, this.isCore),
analysis: {
meta: extractInjectableMetadata(node, decorator, this.reflector, this.isCore),
},
};
}
compile(node: ts.ClassDeclaration, analysis: R3InjectableMetadata): CompileResult {
const res = compileIvyInjectable(analysis);
compile(node: ts.ClassDeclaration, analysis: InjectableHandlerData): CompileResult {
const res = compileIvyInjectable(analysis.meta);
return {
name: 'ngInjectableDef',
initializer: res.expression,

View File

@ -17,7 +17,9 @@ import {AnalysisOutput, CompileResult, DecoratorHandler} from '../../transform';
import {SelectorScopeRegistry} from './selector_scope';
import {getConstructorDependencies, isAngularCore, unwrapExpression} from './util';
export class PipeDecoratorHandler implements DecoratorHandler<R3PipeMetadata, Decorator> {
export interface PipeHandlerData { meta: R3PipeMetadata; }
export class PipeDecoratorHandler implements DecoratorHandler<PipeHandlerData, Decorator> {
constructor(
private checker: ts.TypeChecker, private reflector: ReflectionHost,
private scopeRegistry: SelectorScopeRegistry, private isCore: boolean) {}
@ -30,7 +32,7 @@ export class PipeDecoratorHandler implements DecoratorHandler<R3PipeMetadata, De
decorator => decorator.name === 'Pipe' && (this.isCore || isAngularCore(decorator)));
}
analyze(clazz: ts.ClassDeclaration, decorator: Decorator): AnalysisOutput<R3PipeMetadata> {
analyze(clazz: ts.ClassDeclaration, decorator: Decorator): AnalysisOutput<PipeHandlerData> {
if (clazz.name === undefined) {
throw new FatalDiagnosticError(
ErrorCode.DECORATOR_ON_ANONYMOUS_CLASS, clazz, `@Pipes must have names`);
@ -77,16 +79,18 @@ export class PipeDecoratorHandler implements DecoratorHandler<R3PipeMetadata, De
return {
analysis: {
name,
type,
pipeName,
deps: getConstructorDependencies(clazz, this.reflector, this.isCore), pure,
}
meta: {
name,
type,
pipeName,
deps: getConstructorDependencies(clazz, this.reflector, this.isCore), pure,
},
},
};
}
compile(node: ts.ClassDeclaration, analysis: R3PipeMetadata): CompileResult {
const res = compilePipeFromMetadata(analysis);
compile(node: ts.ClassDeclaration, analysis: PipeHandlerData): CompileResult {
const res = compilePipeFromMetadata(analysis.meta);
return {
name: 'ngPipeDef',
initializer: res.expression,