refactor(ivy): remove ngBaseDef (#33264)
Removes `ngBaseDef` from the compiler and any runtime code that was still referring to it. In the cases where we'd previously generate a base def we now generate a definition for an abstract directive. PR Close #33264
This commit is contained in:
@ -9,7 +9,6 @@
|
||||
/// <reference types="node" />
|
||||
|
||||
export {ResourceLoader} from './src/api';
|
||||
export {BaseDefDecoratorHandler} from './src/base_def';
|
||||
export {ComponentDecoratorHandler} from './src/component';
|
||||
export {DirectiveDecoratorHandler} from './src/directive';
|
||||
export {InjectableDecoratorHandler} from './src/injectable';
|
||||
|
@ -1,173 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ConstantPool, EMPTY_SOURCE_SPAN, R3BaseRefMetaData, WrappedNodeExpr, compileBaseDefFromMetadata, makeBindingParser} from '@angular/compiler';
|
||||
|
||||
import {PartialEvaluator} from '../../partial_evaluator';
|
||||
import {ClassDeclaration, ClassMember, Decorator, ReflectionHost} from '../../reflection';
|
||||
import {AnalysisOutput, CompileResult, DecoratorHandler, DetectResult, HandlerPrecedence} from '../../transform';
|
||||
|
||||
import {extractHostBindings, queriesFromFields} from './directive';
|
||||
import {isAngularDecorator} from './util';
|
||||
|
||||
function containsNgTopLevelDecorator(decorators: Decorator[] | null, isCore: boolean): boolean {
|
||||
if (!decorators) {
|
||||
return false;
|
||||
}
|
||||
return decorators.some(
|
||||
decorator => isAngularDecorator(decorator, 'Component', isCore) ||
|
||||
isAngularDecorator(decorator, 'Directive', isCore) ||
|
||||
isAngularDecorator(decorator, 'NgModule', isCore));
|
||||
}
|
||||
|
||||
export class BaseDefDecoratorHandler implements
|
||||
DecoratorHandler<R3BaseRefMetaData, R3BaseRefDecoratorDetection> {
|
||||
constructor(
|
||||
private reflector: ReflectionHost, private evaluator: PartialEvaluator,
|
||||
private isCore: boolean) {}
|
||||
|
||||
readonly precedence = HandlerPrecedence.WEAK;
|
||||
|
||||
detect(node: ClassDeclaration, decorators: Decorator[]|null):
|
||||
DetectResult<R3BaseRefDecoratorDetection>|undefined {
|
||||
if (containsNgTopLevelDecorator(decorators, this.isCore)) {
|
||||
// If the class is already decorated by @Component or @Directive let that
|
||||
// DecoratorHandler handle this. BaseDef is unnecessary.
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let result: R3BaseRefDecoratorDetection|undefined = undefined;
|
||||
|
||||
this.reflector.getMembersOfClass(node).forEach(property => {
|
||||
const {decorators} = property;
|
||||
if (!decorators) {
|
||||
return;
|
||||
}
|
||||
for (const decorator of decorators) {
|
||||
if (isAngularDecorator(decorator, 'Input', this.isCore)) {
|
||||
result = result || {};
|
||||
const inputs = result.inputs = result.inputs || [];
|
||||
inputs.push({decorator, property});
|
||||
} else if (isAngularDecorator(decorator, 'Output', this.isCore)) {
|
||||
result = result || {};
|
||||
const outputs = result.outputs = result.outputs || [];
|
||||
outputs.push({decorator, property});
|
||||
} else if (
|
||||
isAngularDecorator(decorator, 'ViewChild', this.isCore) ||
|
||||
isAngularDecorator(decorator, 'ViewChildren', this.isCore)) {
|
||||
result = result || {};
|
||||
const viewQueries = result.viewQueries = result.viewQueries || [];
|
||||
viewQueries.push({member: property, decorators});
|
||||
} else if (
|
||||
isAngularDecorator(decorator, 'ContentChild', this.isCore) ||
|
||||
isAngularDecorator(decorator, 'ContentChildren', this.isCore)) {
|
||||
result = result || {};
|
||||
const queries = result.queries = result.queries || [];
|
||||
queries.push({member: property, decorators});
|
||||
} else if (
|
||||
isAngularDecorator(decorator, 'HostBinding', this.isCore) ||
|
||||
isAngularDecorator(decorator, 'HostListener', this.isCore)) {
|
||||
result = result || {};
|
||||
const host = result.host = result.host || [];
|
||||
host.push(property);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (result !== undefined) {
|
||||
return {
|
||||
metadata: result,
|
||||
trigger: null,
|
||||
};
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
analyze(node: ClassDeclaration, metadata: R3BaseRefDecoratorDetection):
|
||||
AnalysisOutput<R3BaseRefMetaData> {
|
||||
const analysis: R3BaseRefMetaData = {
|
||||
name: node.name.text,
|
||||
type: new WrappedNodeExpr(node.name),
|
||||
typeSourceSpan: EMPTY_SOURCE_SPAN,
|
||||
};
|
||||
|
||||
if (metadata.inputs) {
|
||||
const inputs = analysis.inputs = {} as{[key: string]: string | [string, string]};
|
||||
metadata.inputs.forEach(({decorator, property}) => {
|
||||
const propName = property.name;
|
||||
const args = decorator.args;
|
||||
let value: string|[string, string];
|
||||
if (args && args.length > 0) {
|
||||
const resolvedValue = this.evaluator.evaluate(args[0]);
|
||||
if (typeof resolvedValue !== 'string') {
|
||||
throw new TypeError('Input alias does not resolve to a string value');
|
||||
}
|
||||
value = [resolvedValue, propName];
|
||||
} else {
|
||||
value = propName;
|
||||
}
|
||||
inputs[propName] = value;
|
||||
});
|
||||
}
|
||||
|
||||
if (metadata.outputs) {
|
||||
const outputs = analysis.outputs = {} as{[key: string]: string};
|
||||
metadata.outputs.forEach(({decorator, property}) => {
|
||||
const propName = property.name;
|
||||
const args = decorator.args;
|
||||
let value: string;
|
||||
if (args && args.length > 0) {
|
||||
const resolvedValue = this.evaluator.evaluate(args[0]);
|
||||
if (typeof resolvedValue !== 'string') {
|
||||
throw new TypeError('Output alias does not resolve to a string value');
|
||||
}
|
||||
value = resolvedValue;
|
||||
} else {
|
||||
value = propName;
|
||||
}
|
||||
outputs[propName] = value;
|
||||
});
|
||||
}
|
||||
|
||||
if (metadata.viewQueries) {
|
||||
analysis.viewQueries =
|
||||
queriesFromFields(metadata.viewQueries, this.reflector, this.evaluator);
|
||||
}
|
||||
|
||||
if (metadata.queries) {
|
||||
analysis.queries = queriesFromFields(metadata.queries, this.reflector, this.evaluator);
|
||||
}
|
||||
|
||||
if (metadata.host) {
|
||||
analysis.host = extractHostBindings(
|
||||
metadata.host, this.evaluator, this.isCore ? undefined : '@angular/core');
|
||||
}
|
||||
|
||||
return {analysis};
|
||||
}
|
||||
|
||||
compile(node: ClassDeclaration, analysis: R3BaseRefMetaData, pool: ConstantPool):
|
||||
CompileResult[]|CompileResult {
|
||||
const {expression, type} = compileBaseDefFromMetadata(analysis, pool, makeBindingParser());
|
||||
|
||||
return {
|
||||
name: 'ngBaseDef',
|
||||
initializer: expression, type,
|
||||
statements: [],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export interface R3BaseRefDecoratorDetection {
|
||||
inputs?: {property: ClassMember, decorator: Decorator}[];
|
||||
outputs?: {property: ClassMember, decorator: Decorator}[];
|
||||
viewQueries?: {member: ClassMember, decorators: Decorator[]}[];
|
||||
queries?: {member: ClassMember, decorators: Decorator[]}[];
|
||||
host?: ClassMember[];
|
||||
}
|
@ -19,16 +19,24 @@ import {AnalysisOutput, CompileResult, DecoratorHandler, DetectResult, HandlerFl
|
||||
|
||||
import {compileNgFactoryDefField} from './factory';
|
||||
import {generateSetClassMetadataCall} from './metadata';
|
||||
import {findAngularDecorator, getConstructorDependencies, readBaseClass, unwrapConstructorDependencies, unwrapExpression, unwrapForwardRef, validateConstructorDependencies} from './util';
|
||||
import {findAngularDecorator, getConstructorDependencies, isAngularDecorator, readBaseClass, unwrapConstructorDependencies, unwrapExpression, unwrapForwardRef, validateConstructorDependencies} from './util';
|
||||
|
||||
const EMPTY_OBJECT: {[key: string]: string} = {};
|
||||
const FIELD_DECORATORS = [
|
||||
'Input', 'Output', 'ViewChild', 'ViewChildren', 'ContentChild', 'ContentChildren', 'HostBinding',
|
||||
'HostListener'
|
||||
];
|
||||
const LIFECYCLE_HOOKS = new Set([
|
||||
'ngOnChanges', 'ngOnInit', 'ngOnDestroy', 'ngDoCheck', 'ngAfterViewInit', 'ngAfterViewChecked',
|
||||
'ngAfterContentInit', 'ngAfterContentChecked'
|
||||
]);
|
||||
|
||||
export interface DirectiveHandlerData {
|
||||
meta: R3DirectiveMetadata;
|
||||
metadataStmt: Statement|null;
|
||||
}
|
||||
export class DirectiveDecoratorHandler implements
|
||||
DecoratorHandler<DirectiveHandlerData, Decorator> {
|
||||
DecoratorHandler<DirectiveHandlerData, Decorator|null> {
|
||||
constructor(
|
||||
private reflector: ReflectionHost, private evaluator: PartialEvaluator,
|
||||
private metaRegistry: MetadataRegistry, private defaultImportRecorder: DefaultImportRecorder,
|
||||
@ -36,27 +44,41 @@ export class DirectiveDecoratorHandler implements
|
||||
|
||||
readonly precedence = HandlerPrecedence.PRIMARY;
|
||||
|
||||
detect(node: ClassDeclaration, decorators: Decorator[]|null): DetectResult<Decorator>|undefined {
|
||||
if (!decorators) {
|
||||
detect(node: ClassDeclaration, decorators: Decorator[]|null):
|
||||
DetectResult<Decorator|null>|undefined {
|
||||
// Compiling declaration files is invalid.
|
||||
if (node.getSourceFile().isDeclarationFile) {
|
||||
return undefined;
|
||||
}
|
||||
const decorator = findAngularDecorator(decorators, 'Directive', this.isCore);
|
||||
if (decorator !== undefined) {
|
||||
return {
|
||||
trigger: decorator.node,
|
||||
metadata: decorator,
|
||||
};
|
||||
// If the class is undecorated, check if any of the fields have Angular decorators or lifecycle
|
||||
// hooks, and if they do, label the class as an abstract directive.
|
||||
if (!decorators) {
|
||||
const angularField = this.reflector.getMembersOfClass(node).find(member => {
|
||||
if (!member.isStatic && member.kind === ClassMemberKind.Method &&
|
||||
LIFECYCLE_HOOKS.has(member.name)) {
|
||||
return true;
|
||||
}
|
||||
if (member.decorators) {
|
||||
return member.decorators.some(
|
||||
decorator => FIELD_DECORATORS.some(
|
||||
decoratorName => isAngularDecorator(decorator, decoratorName, this.isCore)));
|
||||
}
|
||||
return false;
|
||||
});
|
||||
return angularField ? {trigger: angularField.node, metadata: null} : undefined;
|
||||
} else {
|
||||
return undefined;
|
||||
const decorator = findAngularDecorator(decorators, 'Directive', this.isCore);
|
||||
return decorator ? {trigger: decorator.node, metadata: decorator} : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
analyze(node: ClassDeclaration, decorator: Decorator, flags = HandlerFlags.NONE):
|
||||
analyze(node: ClassDeclaration, decorator: Decorator|null, flags = HandlerFlags.NONE):
|
||||
AnalysisOutput<DirectiveHandlerData> {
|
||||
const directiveResult = extractDirectiveMetadata(
|
||||
node, decorator, this.reflector, this.evaluator, this.defaultImportRecorder, this.isCore,
|
||||
flags);
|
||||
const analysis = directiveResult && directiveResult.metadata;
|
||||
|
||||
if (analysis === undefined) {
|
||||
return {};
|
||||
}
|
||||
@ -112,15 +134,14 @@ export class DirectiveDecoratorHandler implements
|
||||
* the module.
|
||||
*/
|
||||
export function extractDirectiveMetadata(
|
||||
clazz: ClassDeclaration, decorator: Decorator, reflector: ReflectionHost,
|
||||
clazz: ClassDeclaration, decorator: Decorator | null, reflector: ReflectionHost,
|
||||
evaluator: PartialEvaluator, defaultImportRecorder: DefaultImportRecorder, isCore: boolean,
|
||||
flags: HandlerFlags, defaultSelector: string | null = null): {
|
||||
decorator: Map<string, ts.Expression>,
|
||||
metadata: R3DirectiveMetadata,
|
||||
decoratedElements: ClassMember[],
|
||||
}|undefined {
|
||||
let directive: Map<string, ts.Expression>;
|
||||
if (decorator.args === null || decorator.args.length === 0) {
|
||||
if (decorator === null || decorator.args === null || decorator.args.length === 0) {
|
||||
directive = new Map<string, ts.Expression>();
|
||||
} else if (decorator.args.length !== 1) {
|
||||
throw new FatalDiagnosticError(
|
||||
@ -256,7 +277,7 @@ export function extractDirectiveMetadata(
|
||||
typeArgumentCount: reflector.getGenericArityOfClass(clazz) || 0,
|
||||
typeSourceSpan: EMPTY_SOURCE_SPAN, usesInheritance, exportAs, providers
|
||||
};
|
||||
return {decoratedElements, decorator: directive, metadata};
|
||||
return {decorator: directive, metadata};
|
||||
}
|
||||
|
||||
export function extractQueryMetadata(
|
||||
|
@ -14,7 +14,6 @@ import {nocollapseHack} from '../transformers/nocollapse_hack';
|
||||
import {verifySupportedTypeScriptVersion} from '../typescript_support';
|
||||
|
||||
import {ComponentDecoratorHandler, DirectiveDecoratorHandler, InjectableDecoratorHandler, NgModuleDecoratorHandler, NoopReferencesRegistry, PipeDecoratorHandler, ReferencesRegistry} from './annotations';
|
||||
import {BaseDefDecoratorHandler} from './annotations/src/base_def';
|
||||
import {CycleAnalyzer, ImportGraph} from './cycles';
|
||||
import {ErrorCode, ngErrorCode} from './diagnostics';
|
||||
import {FlatIndexGenerator, ReferenceGraph, checkForPrivateExports, findFlatIndexEntryPoint} from './entry_point';
|
||||
@ -587,7 +586,6 @@ export class NgtscProgram implements api.Program {
|
||||
|
||||
// Set up the IvyCompilation, which manages state for the Ivy transformer.
|
||||
const handlers = [
|
||||
new BaseDefDecoratorHandler(this.reflector, evaluator, this.isCore),
|
||||
new ComponentDecoratorHandler(
|
||||
this.reflector, evaluator, metaRegistry, this.metaReader !, scopeReader, scopeRegistry,
|
||||
this.isCore, this.resourceManager, this.rootDirs,
|
||||
|
@ -19,7 +19,6 @@
|
||||
|
||||
// Pattern matching all Render3 property names.
|
||||
const R3_DEF_NAME_PATTERN = [
|
||||
'ngBaseDef',
|
||||
'ɵcmp',
|
||||
'ɵdir',
|
||||
'ɵprov',
|
||||
|
Reference in New Issue
Block a user