Skip to content

Commit

Permalink
refactor(compiler): don’t rely on global reflector
Browse files Browse the repository at this point in the history
Using the global reflector made it impossible
to compile multiple programs at the same time.
  • Loading branch information
tbosch committed May 19, 2017
1 parent 9ff389c commit 982e995
Show file tree
Hide file tree
Showing 52 changed files with 332 additions and 337 deletions.
6 changes: 4 additions & 2 deletions packages/common/test/pipes/date_pipe_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import {DatePipe} from '@angular/common';
import {JitReflector} from '@angular/compiler';
import {PipeResolver} from '@angular/compiler/src/pipe_resolver';
import {browserDetection} from '@angular/platform-browser/testing/src/browser_util';

Expand Down Expand Up @@ -34,8 +35,9 @@ export function main() {
pipe = new DatePipe('en-US');
});

it('should be marked as pure',
() => { expect(new PipeResolver().resolve(DatePipe) !.pure).toEqual(true); });
it('should be marked as pure', () => {
expect(new PipeResolver(new JitReflector()).resolve(DatePipe) !.pure).toEqual(true);
});

describe('supports', () => {
it('should support date', () => { expect(() => pipe.transform(date)).not.toThrow(); });
Expand Down
6 changes: 4 additions & 2 deletions packages/common/test/pipes/i18n_plural_pipe_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

import {I18nPluralPipe, NgLocalization} from '@angular/common';
import {JitReflector} from '@angular/compiler';
import {PipeResolver} from '@angular/compiler/src/pipe_resolver';
import {beforeEach, describe, expect, it} from '@angular/core/testing/src/testing_internal';

Expand All @@ -27,8 +28,9 @@ export function main() {
pipe = new I18nPluralPipe(localization);
});

it('should be marked as pure',
() => { expect(new PipeResolver().resolve(I18nPluralPipe) !.pure).toEqual(true); });
it('should be marked as pure', () => {
expect(new PipeResolver(new JitReflector()).resolve(I18nPluralPipe) !.pure).toEqual(true);
});

describe('transform', () => {
it('should return 0 text if value is 0', () => {
Expand Down
6 changes: 4 additions & 2 deletions packages/common/test/pipes/i18n_select_pipe_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,17 @@
*/

import {I18nSelectPipe} from '@angular/common';
import {JitReflector} from '@angular/compiler';
import {PipeResolver} from '@angular/compiler/src/pipe_resolver';

export function main() {
describe('I18nSelectPipe', () => {
const pipe: I18nSelectPipe = new I18nSelectPipe();
const mapping = {'male': 'Invite him.', 'female': 'Invite her.', 'other': 'Invite them.'};

it('should be marked as pure',
() => { expect(new PipeResolver().resolve(I18nSelectPipe) !.pure).toEqual(true); });
it('should be marked as pure', () => {
expect(new PipeResolver(new JitReflector()).resolve(I18nSelectPipe) !.pure).toEqual(true);
});

describe('transform', () => {
it('should return the "male" text if value is "male"', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {AotSummaryResolver, CompileMetadataResolver, CompilePipeSummary, CompilerConfig, DEFAULT_INTERPOLATION_CONFIG, DirectiveNormalizer, DirectiveResolver, DomElementSchemaRegistry, HtmlParser, InterpolationConfig, NgAnalyzedModules, NgModuleResolver, ParseTreeResult, PipeResolver, ResourceLoader, StaticAndDynamicReflectionCapabilities, StaticReflector, StaticSymbol, StaticSymbolCache, StaticSymbolResolver, SummaryResolver, analyzeNgModules, componentModuleUrl, createOfflineCompileUrlResolver, extractProgramSymbols} from '@angular/compiler';
import {AotSummaryResolver, CompileMetadataResolver, CompilePipeSummary, CompilerConfig, DEFAULT_INTERPOLATION_CONFIG, DirectiveNormalizer, DirectiveResolver, DomElementSchemaRegistry, HtmlParser, InterpolationConfig, NgAnalyzedModules, NgModuleResolver, ParseTreeResult, PipeResolver, ResourceLoader, StaticReflector, StaticSymbol, StaticSymbolCache, StaticSymbolResolver, SummaryResolver, analyzeNgModules, createOfflineCompileUrlResolver, extractProgramSymbols} from '@angular/compiler';
import {ViewEncapsulation, ɵConsole as Console} from '@angular/core';
import * as fs from 'fs';
import * as path from 'path';
Expand Down
6 changes: 3 additions & 3 deletions packages/compiler-cli/test/diagnostics/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import {AotCompilerHost, AotSummaryResolver, CompileMetadataResolver, CompilerConfig, DEFAULT_INTERPOLATION_CONFIG, DirectiveNormalizer, DirectiveResolver, DomElementSchemaRegistry, HtmlParser, I18NHtmlParser, InterpolationConfig, JitSummaryResolver, Lexer, NgAnalyzedModules, NgModuleResolver, ParseTreeResult, Parser, PipeResolver, ResourceLoader, StaticAndDynamicReflectionCapabilities, StaticReflector, StaticSymbol, StaticSymbolCache, StaticSymbolResolver, SummaryResolver, TemplateParser, analyzeNgModules, createOfflineCompileUrlResolver, extractProgramSymbols} from '@angular/compiler';
import {AotCompilerHost, AotSummaryResolver, CompileMetadataResolver, CompilerConfig, DEFAULT_INTERPOLATION_CONFIG, DirectiveNormalizer, DirectiveResolver, DomElementSchemaRegistry, HtmlParser, I18NHtmlParser, InterpolationConfig, JitSummaryResolver, Lexer, NgAnalyzedModules, NgModuleResolver, ParseTreeResult, Parser, PipeResolver, ResourceLoader, StaticReflector, StaticSymbol, StaticSymbolCache, StaticSymbolResolver, SummaryResolver, TemplateParser, analyzeNgModules, createOfflineCompileUrlResolver, extractProgramSymbols} from '@angular/compiler';
import {ViewEncapsulation, ɵConsole as Console} from '@angular/core';
import {CompilerHostContext} from 'compiler-cli';
import * as fs from 'fs';
Expand Down Expand Up @@ -134,7 +134,6 @@ export class DiagnosticContext {
const ssr = this.staticSymbolResolver;
const result = this._reflector = new StaticReflector(
summaryResolver, ssr, [], [], (e, filePath) => this.collectError(e, filePath !));
StaticAndDynamicReflectionCapabilities.install(result);
this._reflector = result;
return result;
}
Expand Down Expand Up @@ -205,7 +204,8 @@ function compileTemplate(context: DiagnosticContext, type: StaticSymbol, templat
const expressionParser = new Parser(new Lexer());
const config = new CompilerConfig();
const parser = new TemplateParser(
config, expressionParser, new DomElementSchemaRegistry(), htmlParser, null !, []);
config, context.reflector, expressionParser, new DomElementSchemaRegistry(), htmlParser,
null !, []);
const htmlResult = htmlParser.parse(template, '', true);
const analyzedModules = context.analyzedModules;
// let errors: Diagnostic[]|undefined = undefined;
Expand Down
4 changes: 0 additions & 4 deletions packages/compiler-cli/test/main_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
* found in the LICENSE file at https://angular.io/license
*/

import {ɵReflectionCapabilities, ɵreflector} from '@angular/core';
import {makeTempDir} from '@angular/tsc-wrapped/test/test_support';
import * as fs from 'fs';
import * as path from 'path';
Expand Down Expand Up @@ -42,9 +41,6 @@ describe('compiler-cli', () => {
fs.symlinkSync(path.resolve(__dirname, '..', '..'), path.resolve(nodeModulesPath, '@angular'));
});

// Restore reflector since AoT compiler will update it with a new static reflector
afterEach(() => { ɵreflector.updateCapabilities(new ɵReflectionCapabilities()); });

it('should compile without errors', (done) => {
write('test.ts', 'export const A = 1;');

Expand Down
14 changes: 8 additions & 6 deletions packages/compiler/src/aot/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import {CompileDirectiveMetadata, CompileDirectiveSummary, CompileIdentifierMetadata, CompileNgModuleMetadata, CompileNgModuleSummary, CompilePipeMetadata, CompileProviderMetadata, CompileStylesheetMetadata, CompileSummaryKind, CompileTypeMetadata, CompileTypeSummary, componentFactoryName, createHostComponentMeta, flatten, identifierName, sourceUrl, templateSourceUrl} from '../compile_metadata';
import {CompilerConfig} from '../config';
import {Identifiers, createIdentifier, createIdentifierToken} from '../identifiers';
import {Identifiers, createTokenForExternalReference} from '../identifiers';
import {CompileMetadataResolver} from '../metadata_resolver';
import {NgModuleCompiler} from '../ng_module_compiler';
import {OutputEmitter} from '../output/abstract_emitter';
Expand All @@ -21,6 +21,7 @@ import {ViewCompileResult, ViewCompiler} from '../view_compiler/view_compiler';

import {AotCompilerHost} from './compiler_host';
import {GeneratedFile} from './generated_file';
import {StaticReflector} from './static_reflector';
import {StaticSymbol} from './static_symbol';
import {ResolvedStaticSymbol, StaticSymbolResolver} from './static_symbol_resolver';
import {serializeSummaries} from './summary_serializer';
Expand All @@ -29,9 +30,10 @@ import {ngfactoryFilePath, splitTypescriptSuffix, summaryFileName, summaryForJit
export class AotCompiler {
constructor(
private _config: CompilerConfig, private _host: AotCompilerHost,
private _metadataResolver: CompileMetadataResolver, private _templateParser: TemplateParser,
private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler,
private _ngModuleCompiler: NgModuleCompiler, private _outputEmitter: OutputEmitter,
private _reflector: StaticReflector, private _metadataResolver: CompileMetadataResolver,
private _templateParser: TemplateParser, private _styleCompiler: StyleCompiler,
private _viewCompiler: ViewCompiler, private _ngModuleCompiler: NgModuleCompiler,
private _outputEmitter: OutputEmitter,
private _summaryResolver: SummaryResolver<StaticSymbol>, private _localeId: string|null,
private _translationFormat: string|null, private _symbolResolver: StaticSymbolResolver) {}

Expand Down Expand Up @@ -154,14 +156,14 @@ export class AotCompiler {

if (this._localeId) {
providers.push({
token: createIdentifierToken(Identifiers.LOCALE_ID),
token: createTokenForExternalReference(this._reflector, Identifiers.LOCALE_ID),
useValue: this._localeId,
});
}

if (this._translationFormat) {
providers.push({
token: createIdentifierToken(Identifiers.TRANSLATIONS_FORMAT),
token: createTokenForExternalReference(this._reflector, Identifiers.TRANSLATIONS_FORMAT),
useValue: this._translationFormat
});
}
Expand Down
14 changes: 6 additions & 8 deletions packages/compiler/src/aot/compiler_factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import {ViewCompiler} from '../view_compiler/view_compiler';
import {AotCompiler} from './compiler';
import {AotCompilerHost} from './compiler_host';
import {AotCompilerOptions} from './compiler_options';
import {StaticAndDynamicReflectionCapabilities} from './static_reflection_capabilities';
import {StaticReflector} from './static_reflector';
import {StaticSymbol, StaticSymbolCache} from './static_symbol';
import {StaticSymbolResolver} from './static_symbol_resolver';
Expand All @@ -47,7 +46,6 @@ export function createAotCompiler(compilerHost: AotCompilerHost, options: AotCom
const summaryResolver = new AotSummaryResolver(compilerHost, symbolCache);
const symbolResolver = new StaticSymbolResolver(compilerHost, symbolCache, summaryResolver);
const staticReflector = new StaticReflector(summaryResolver, symbolResolver);
StaticAndDynamicReflectionCapabilities.install(staticReflector);
const console = new Console();
const htmlParser = new I18NHtmlParser(
new HtmlParser(), translations, options.i18nFormat, options.missingTranslation, console);
Expand All @@ -61,17 +59,17 @@ export function createAotCompiler(compilerHost: AotCompilerHost, options: AotCom
{get: (url: string) => compilerHost.loadResource(url)}, urlResolver, htmlParser, config);
const expressionParser = new Parser(new Lexer());
const elementSchemaRegistry = new DomElementSchemaRegistry();
const tmplParser =
new TemplateParser(config, expressionParser, elementSchemaRegistry, htmlParser, console, []);
const tmplParser = new TemplateParser(
config, staticReflector, expressionParser, elementSchemaRegistry, htmlParser, console, []);
const resolver = new CompileMetadataResolver(
config, new NgModuleResolver(staticReflector), new DirectiveResolver(staticReflector),
new PipeResolver(staticReflector), summaryResolver, elementSchemaRegistry, normalizer,
console, symbolCache, staticReflector);
// TODO(vicb): do not pass options.i18nFormat here
const viewCompiler = new ViewCompiler(config, elementSchemaRegistry);
const viewCompiler = new ViewCompiler(config, staticReflector, elementSchemaRegistry);
const compiler = new AotCompiler(
config, compilerHost, resolver, tmplParser, new StyleCompiler(urlResolver), viewCompiler,
new NgModuleCompiler(), new TypeScriptEmitter(), summaryResolver, options.locale || null,
options.i18nFormat || null, symbolResolver);
config, compilerHost, staticReflector, resolver, tmplParser, new StyleCompiler(urlResolver),
viewCompiler, new NgModuleCompiler(staticReflector), new TypeScriptEmitter(), summaryResolver,
options.locale || null, options.i18nFormat || null, symbolResolver);
return {compiler, reflector: staticReflector};
}
60 changes: 0 additions & 60 deletions packages/compiler/src/aot/static_reflection_capabilities.ts

This file was deleted.

28 changes: 8 additions & 20 deletions packages/compiler/src/aot/static_reflector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
* found in the LICENSE file at https://angular.io/license
*/

import {Attribute, Component, ContentChild, ContentChildren, Directive, Host, HostBinding, HostListener, Inject, Injectable, Input, NgModule, Optional, Output, Pipe, Self, SkipSelf, ViewChild, ViewChildren, animate, group, keyframes, sequence, state, style, transition, trigger, ɵReflectorReader} from '@angular/core';
import {Attribute, Component, ContentChild, ContentChildren, Directive, Host, HostBinding, HostListener, Inject, Injectable, Input, NgModule, Optional, Output, Pipe, Self, SkipSelf, ViewChild, ViewChildren, animate, group, keyframes, sequence, state, style, transition, trigger} from '@angular/core';

import {CompileSummaryKind} from '../compile_metadata';
import {CompileReflector} from '../compile_reflector';
import * as o from '../output/output_ast';
import {SummaryResolver} from '../summary_resolver';
import {syntaxError} from '../util';

Expand All @@ -31,7 +33,7 @@ function shouldIgnore(value: any): boolean {
* A static reflector implements enough of the Reflector API that is necessary to compile
* templates statically.
*/
export class StaticReflector implements ɵReflectorReader {
export class StaticReflector implements CompileReflector {
private annotationCache = new Map<StaticSymbol, any[]>();
private propertyCache = new Map<StaticSymbol, {[key: string]: any[]}>();
private parameterCache = new Map<StaticSymbol, any[]>();
Expand Down Expand Up @@ -67,25 +69,17 @@ export class StaticReflector implements ɵReflectorReader {
this.annotationNames.set(Injectable, 'Injectable');
}

importUri(typeOrFunc: StaticSymbol): string|null {
const staticSymbol = this.findSymbolDeclaration(typeOrFunc);
return staticSymbol ? staticSymbol.filePath : null;
}

resourceUri(typeOrFunc: StaticSymbol): string {
componentModuleUrl(typeOrFunc: StaticSymbol): string {
const staticSymbol = this.findSymbolDeclaration(typeOrFunc);
return this.symbolResolver.getResourcePath(staticSymbol);
}

resolveIdentifier(name: string, moduleUrl: string, members: string[]): StaticSymbol {
const importSymbol = this.getStaticSymbol(moduleUrl, name);
const rootSymbol = this.findDeclaration(moduleUrl, name);
resolveExternalReference(ref: o.ExternalReference): StaticSymbol {
const importSymbol = this.getStaticSymbol(ref.moduleName !, ref.name !);
const rootSymbol = this.findDeclaration(ref.moduleName !, ref.name !);
if (importSymbol != rootSymbol) {
this.symbolResolver.recordImportAs(rootSymbol, importSymbol);
}
if (members && members.length) {
return this.getStaticSymbol(rootSymbol.filePath, rootSymbol.name, members);
}
return rootSymbol;
}

Expand All @@ -103,12 +97,6 @@ export class StaticReflector implements ɵReflectorReader {
}
}

resolveEnum(enumIdentifier: any, name: string): any {
const staticSymbol: StaticSymbol = enumIdentifier;
const members = (staticSymbol.members || []).concat(name);
return this.getStaticSymbol(staticSymbol.filePath, staticSymbol.name, members);
}

public annotations(type: StaticSymbol): any[] {
let annotations = this.annotationCache.get(type);
if (!annotations) {
Expand Down
8 changes: 5 additions & 3 deletions packages/compiler/src/compile_metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@
* found in the LICENSE file at https://angular.io/license
*/

import {ChangeDetectionStrategy, ComponentFactory, RendererType2, SchemaMetadata, Type, ViewEncapsulation, ɵLifecycleHooks, ɵreflector, ɵstringify as stringify} from '@angular/core';
import {ChangeDetectionStrategy, ComponentFactory, RendererType2, SchemaMetadata, Type, ViewEncapsulation, ɵstringify as stringify} from '@angular/core';

import {StaticSymbol} from './aot/static_symbol';
import {LifecycleHooks} from './lifecycle_reflector';
import {CssSelector} from './selector';
import {splitAtColon} from './util';

Expand Down Expand Up @@ -111,7 +112,8 @@ export function identifierModuleUrl(compileIdentifier: CompileIdentifierMetadata
if (ref instanceof StaticSymbol) {
return ref.filePath;
}
return ɵreflector.importUri(ref);
// Runtime type
return `./${stringify(ref)}`;
}

export function viewClassName(compType: any, embeddedTemplateIndex: number): string {
Expand Down Expand Up @@ -203,7 +205,7 @@ export interface CompileTokenMetadata {
*/
export interface CompileTypeMetadata extends CompileIdentifierMetadata {
diDeps: CompileDiDependencyMetadata[];
lifecycleHooks: ɵLifecycleHooks[];
lifecycleHooks: LifecycleHooks[];
reference: any;
}

Expand Down
22 changes: 22 additions & 0 deletions packages/compiler/src/compile_reflector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* @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 {Component} from '@angular/core';
import * as o from './output/output_ast';

/**
* Provides access to reflection data about symbols that the compiler needs.
*/
export abstract class CompileReflector {
abstract parameters(typeOrFunc: /*Type*/ any): any[][];
abstract annotations(typeOrFunc: /*Type*/ any): any[];
abstract propMetadata(typeOrFunc: /*Type*/ any): {[key: string]: any[]};
abstract hasLifecycleHook(type: any, lcProperty: string): boolean;
abstract componentModuleUrl(type: /*Type*/ any, cmpMetadata: Component): string;
abstract resolveExternalReference(ref: o.ExternalReference): any;
}

0 comments on commit 982e995

Please sign in to comment.