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} = {}; 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( constructor(
private checker: ts.TypeChecker, private reflector: ReflectionHost, private checker: ts.TypeChecker, private reflector: ReflectionHost,
private scopeRegistry: SelectorScopeRegistry, private isCore: boolean) {} private scopeRegistry: SelectorScopeRegistry, private isCore: boolean) {}
@ -32,7 +34,7 @@ export class DirectiveDecoratorHandler implements DecoratorHandler<R3DirectiveMe
decorator => decorator.name === 'Directive' && (this.isCore || isAngularCore(decorator))); 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 = const directiveResult =
extractDirectiveMetadata(node, decorator, this.checker, this.reflector, this.isCore); extractDirectiveMetadata(node, decorator, this.checker, this.reflector, this.isCore);
const analysis = directiveResult && directiveResult.metadata; 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 { CompileResult {
const res = compileDirectiveFromMetadata(analysis, pool, makeBindingParser()); const res = compileDirectiveFromMetadata(analysis.meta, pool, makeBindingParser());
return { return {
name: 'ngDirectiveDef', name: 'ngDirectiveDef',
initializer: res.expression, initializer: res.expression,

View File

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

View File

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