Skip to content

Commit

Permalink
refactor(ivy): remove ngBaseDef
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
crisbeto committed Oct 25, 2019
1 parent 8d15bfa commit e957e63
Show file tree
Hide file tree
Showing 29 changed files with 310 additions and 660 deletions.
10 changes: 5 additions & 5 deletions integration/ngcc/test.sh
Expand Up @@ -95,12 +95,12 @@ assertSucceeded "Expected 'ngcc' to log 'Compiling'."
assertSucceeded "Expected 'ngcc' to generate a base factory for 'MatTable' in '@angular/material' (esm5)."


# Did it generate a base definition for undecorated classes with inputs and view queries?
grep "_MatMenuBase.ngBaseDef = ɵngcc0.ɵɵdefineBase({ inputs: {" node_modules/@angular/material/esm2015/menu.js
assertSucceeded "Expected 'ngcc' to generate a base definition for 'MatMenuBase' in '@angular/material' (esm2015)."
# Did it generate an abstract directive definition for undecorated classes with inputs and view queries?
grep "_MatMenuBase.ɵdir = ɵngcc0.ɵɵdefineDirective({ type: _MatMenuBase" node_modules/@angular/material/esm2015/menu.js
assertSucceeded "Expected 'ngcc' to generate an abstract directive definition for 'MatMenuBase' in '@angular/material' (esm2015)."

grep "_MatMenuBase.ngBaseDef = ɵngcc0.ɵɵdefineBase({ inputs: {" node_modules/@angular/material/esm5/menu.es5.js
assertSucceeded "Expected 'ngcc' to generate a base definition for 'MatMenuBase' in '@angular/material' (esm5)."
grep "_MatMenuBase.ɵdir = ɵngcc0.ɵɵdefineDirective({ type: _MatMenuBase" node_modules/@angular/material/esm5/menu.es5.js
assertSucceeded "Expected 'ngcc' to generate an abstract directive definition for 'MatMenuBase' in '@angular/material' (esm5)."


# Did it handle namespace imported decorators in UMD using `__decorate` syntax?
Expand Down
Expand Up @@ -7,8 +7,7 @@
*/
import {ConstantPool} from '@angular/compiler';
import * as ts from 'typescript';

import {BaseDefDecoratorHandler, ComponentDecoratorHandler, DirectiveDecoratorHandler, InjectableDecoratorHandler, NgModuleDecoratorHandler, PipeDecoratorHandler, ReferencesRegistry, ResourceLoader} from '../../../src/ngtsc/annotations';
import {ComponentDecoratorHandler, DirectiveDecoratorHandler, InjectableDecoratorHandler, NgModuleDecoratorHandler, PipeDecoratorHandler, ReferencesRegistry, ResourceLoader} from '../../../src/ngtsc/annotations';
import {CycleAnalyzer, ImportGraph} from '../../../src/ngtsc/cycles';
import {isFatalDiagnosticError} from '../../../src/ngtsc/diagnostics';
import {FileSystem, LogicalFileSystem, absoluteFrom, dirname, resolve} from '../../../src/ngtsc/file_system';
Expand Down Expand Up @@ -85,7 +84,6 @@ export class DecorationAnalyzer {
importGraph = new ImportGraph(this.moduleResolver);
cycleAnalyzer = new CycleAnalyzer(this.importGraph);
handlers: DecoratorHandler<any, any>[] = [
new BaseDefDecoratorHandler(this.reflectionHost, this.evaluator, this.isCore),
new ComponentDecoratorHandler(
this.reflectionHost, this.evaluator, this.fullRegistry, this.fullMetaReader,
this.scopeRegistry, this.scopeRegistry, this.isCore, this.resourceManager, this.rootDirs,
Expand Down
5 changes: 3 additions & 2 deletions packages/compiler-cli/ngcc/test/rendering/renderer_spec.ts
Expand Up @@ -284,7 +284,7 @@ A.ɵdir = ɵngcc0.ɵɵdefineDirective({ type: A, selectors: [["", "a", ""]] });
.toBeGreaterThan(ngInjectorDef, 'setClassMetadata should follow ɵinj');
});

it('should render classes without decorators if handler matches', () => {
it('should render classes without decorators if class fields are decorated', () => {
const {renderer, decorationAnalyses, switchMarkerAnalyses, privateDeclarationsAnalyses,
testFormatter} =
createTestRenderer('test-package', [{
Expand All @@ -309,7 +309,8 @@ A.ɵdir = ɵngcc0.ɵɵdefineDirective({ type: A, selectors: [["", "a", ""]] });
const addDefinitionsSpy = testFormatter.addDefinitions as jasmine.Spy;
expect(addDefinitionsSpy.calls.first().args[2])
.toEqual(
`UndecoratedBase.ngBaseDef = ɵngcc0.ɵɵdefineBase({ viewQuery: function (rf, ctx) { if (rf & 1) {
`UndecoratedBase.ɵfac = function UndecoratedBase_Factory(t) { return new (t || UndecoratedBase)(); };
UndecoratedBase.ɵdir = ɵngcc0.ɵɵdefineDirective({ type: UndecoratedBase, selectors: [], viewQuery: function UndecoratedBase_Query(rf, ctx) { if (rf & 1) {
ɵngcc0.ɵɵstaticViewQuery(_c0, true);
} if (rf & 2) {
var _t;
Expand Down
1 change: 0 additions & 1 deletion packages/compiler-cli/src/ngtsc/annotations/index.ts
Expand Up @@ -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';
Expand Down
173 changes: 0 additions & 173 deletions packages/compiler-cli/src/ngtsc/annotations/src/base_def.ts

This file was deleted.

53 changes: 37 additions & 16 deletions packages/compiler-cli/src/ngtsc/annotations/src/directive.ts
Expand Up @@ -19,44 +19,66 @@ 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,
private isCore: boolean) {}

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 {};
}
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down
2 changes: 0 additions & 2 deletions packages/compiler-cli/src/ngtsc/program.ts
Expand Up @@ -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';
Expand Down Expand Up @@ -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,
Expand Down
1 change: 0 additions & 1 deletion packages/compiler-cli/src/transformers/nocollapse_hack.ts
Expand Up @@ -19,7 +19,6 @@

// Pattern matching all Render3 property names.
const R3_DEF_NAME_PATTERN = [
'ngBaseDef',
'ɵcmp',
'ɵdir',
'ɵprov',
Expand Down

0 comments on commit e957e63

Please sign in to comment.