Revert "feat(compiler): allow selector-less directives as base classes (#31379)" (#32089)

This reverts commit f90c7a9df0 due to breakages in G3.

PR Close #32089
This commit is contained in:
Kara Erickson 2019-08-09 18:17:09 -07:00
parent 753080133b
commit 37de490e23
5 changed files with 12 additions and 71 deletions

View File

@ -2283,28 +2283,4 @@ describe('ngc transformer command-line', () => {
let exitCode = main(['-p', path.join(basePath, 'tsconfig.json')], errorSpy); let exitCode = main(['-p', path.join(basePath, 'tsconfig.json')], errorSpy);
expect(exitCode).toEqual(0); expect(exitCode).toEqual(0);
}); });
describe('base directives', () => {
it('should allow directives with no selector that are not in NgModules', () => {
// first only generate .d.ts / .js / .metadata.json files
writeConfig(`{
"extends": "./tsconfig-base.json",
"files": ["main.ts"]
}`);
write('main.ts', `
import {Directive} from '@angular/core';
@Directive({})
export class BaseDir {}
@Directive({})
export abstract class AbstractBaseDir {}
@Directive()
export abstract class EmptyDir {}
`);
let exitCode = main(['-p', path.join(basePath, 'tsconfig.json')], errorSpy);
expect(exitCode).toEqual(0);
});
});
}); });

View File

@ -797,7 +797,6 @@ export interface NgAnalyzedFileWithInjectables {
export interface NgAnalyzedFile { export interface NgAnalyzedFile {
fileName: string; fileName: string;
directives: StaticSymbol[]; directives: StaticSymbol[];
abstractDirectives: StaticSymbol[];
pipes: StaticSymbol[]; pipes: StaticSymbol[];
ngModules: CompileNgModuleMetadata[]; ngModules: CompileNgModuleMetadata[];
injectables: CompileInjectableMetadata[]; injectables: CompileInjectableMetadata[];
@ -858,20 +857,18 @@ function _analyzeFilesIncludingNonProgramFiles(
export function analyzeFile( export function analyzeFile(
host: NgAnalyzeModulesHost, staticSymbolResolver: StaticSymbolResolver, host: NgAnalyzeModulesHost, staticSymbolResolver: StaticSymbolResolver,
metadataResolver: CompileMetadataResolver, fileName: string): NgAnalyzedFile { metadataResolver: CompileMetadataResolver, fileName: string): NgAnalyzedFile {
const abstractDirectives: StaticSymbol[] = [];
const directives: StaticSymbol[] = []; const directives: StaticSymbol[] = [];
const pipes: StaticSymbol[] = []; const pipes: StaticSymbol[] = [];
const injectables: CompileInjectableMetadata[] = []; const injectables: CompileInjectableMetadata[] = [];
const ngModules: CompileNgModuleMetadata[] = []; const ngModules: CompileNgModuleMetadata[] = [];
const hasDecorators = staticSymbolResolver.hasDecorators(fileName); const hasDecorators = staticSymbolResolver.hasDecorators(fileName);
let exportsNonSourceFiles = false; let exportsNonSourceFiles = false;
const isDeclarationFile = fileName.endsWith('.d.ts');
// Don't analyze .d.ts files that have no decorators as a shortcut // Don't analyze .d.ts files that have no decorators as a shortcut
// to speed up the analysis. This prevents us from // to speed up the analysis. This prevents us from
// resolving the references in these files. // resolving the references in these files.
// Note: exportsNonSourceFiles is only needed when compiling with summaries, // Note: exportsNonSourceFiles is only needed when compiling with summaries,
// which is not the case when .d.ts files are treated as input files. // which is not the case when .d.ts files are treated as input files.
if (!isDeclarationFile || hasDecorators) { if (!fileName.endsWith('.d.ts') || hasDecorators) {
staticSymbolResolver.getSymbolsOf(fileName).forEach((symbol) => { staticSymbolResolver.getSymbolsOf(fileName).forEach((symbol) => {
const resolvedSymbol = staticSymbolResolver.resolveSymbol(symbol); const resolvedSymbol = staticSymbolResolver.resolveSymbol(symbol);
const symbolMeta = resolvedSymbol.metadata; const symbolMeta = resolvedSymbol.metadata;
@ -882,23 +879,7 @@ export function analyzeFile(
if (symbolMeta.__symbolic === 'class') { if (symbolMeta.__symbolic === 'class') {
if (metadataResolver.isDirective(symbol)) { if (metadataResolver.isDirective(symbol)) {
isNgSymbol = true; isNgSymbol = true;
if (!isDeclarationFile) {
// This directive either has a selector or doesn't. Selector-less directives get tracked
// in abstractDirectives, not directives. The compiler doesn't deal with selector-less
// directives at all, really, other than to persist their metadata. This is done so that
// apps will have an easier time migrating to Ivy, which requires the selector-less
// annotations to be applied.
if (!metadataResolver.isAbstractDirective(symbol)) {
// The directive is an ordinary directive.
directives.push(symbol); directives.push(symbol);
} else {
// The directive has no selector and is an "abstract" directive, so track it
// accordingly.
abstractDirectives.push(symbol);
}
} else {
directives.push(symbol);
}
} else if (metadataResolver.isPipe(symbol)) { } else if (metadataResolver.isPipe(symbol)) {
isNgSymbol = true; isNgSymbol = true;
pipes.push(symbol); pipes.push(symbol);
@ -923,8 +904,7 @@ export function analyzeFile(
}); });
} }
return { return {
fileName, directives, abstractDirectives, pipes, fileName, directives, pipes, ngModules, injectables, exportsNonSourceFiles,
ngModules, injectables, exportsNonSourceFiles,
}; };
} }

View File

@ -348,7 +348,11 @@ export class CompileMetadataResolver {
} else { } else {
// Directive // Directive
if (!selector) { if (!selector) {
selector = null !; this._reportError(
syntaxError(
`Directive ${stringifyType(directiveType)} has no selector, please add it!`),
directiveType);
selector = 'error';
} }
} }
@ -428,19 +432,6 @@ export class CompileMetadataResolver {
this._directiveResolver.isDirective(type); this._directiveResolver.isDirective(type);
} }
isAbstractDirective(type: any): boolean {
const summary =
this._loadSummary(type, cpl.CompileSummaryKind.Directive) as cpl.CompileDirectiveSummary;
if (summary) {
return !summary.selector;
}
const meta = this.getNonNormalizedDirectiveMetadata(type);
if (!meta) {
return false;
}
return !meta.metadata.selector;
}
isPipe(type: any) { isPipe(type: any) {
return !!this._loadSummary(type, cpl.CompileSummaryKind.Pipe) || return !!this._loadSummary(type, cpl.CompileSummaryKind.Pipe) ||
this._pipeResolver.isPipe(type); this._pipeResolver.isPipe(type);
@ -616,12 +607,6 @@ export class CompileMetadataResolver {
} }
const declaredIdentifier = this._getIdentifierMetadata(declaredType); const declaredIdentifier = this._getIdentifierMetadata(declaredType);
if (this.isDirective(declaredType)) { if (this.isDirective(declaredType)) {
if (this.isAbstractDirective(declaredType)) {
this._reportError(
syntaxError(
`Directive ${stringifyType(declaredType)} has no selector, please add it!`),
declaredType);
}
transitiveModule.addDirective(declaredIdentifier); transitiveModule.addDirective(declaredIdentifier);
declaredDirectives.push(declaredIdentifier); declaredDirectives.push(declaredIdentifier);
this._addTypeToModule(declaredType, moduleType); this._addTypeToModule(declaredType, moduleType);

View File

@ -68,12 +68,12 @@ export interface DirectiveDecorator {
* *
* @Annotation * @Annotation
*/ */
(obj?: Directive): TypeDecorator; (obj: Directive): TypeDecorator;
/** /**
* See the `Directive` decorator. * See the `Directive` decorator.
*/ */
new (obj?: Directive): Directive; new (obj: Directive): Directive;
} }
/** /**

View File

@ -297,8 +297,8 @@ export interface Directive {
export declare const Directive: DirectiveDecorator; export declare const Directive: DirectiveDecorator;
export interface DirectiveDecorator { export interface DirectiveDecorator {
(obj?: Directive): TypeDecorator; (obj: Directive): TypeDecorator;
new (obj?: Directive): Directive; new (obj: Directive): Directive;
} }
export interface DoBootstrap { export interface DoBootstrap {