refactor(compiler): Reintroduce ReflectorHost and move Extractor into @angular/compiler

This commit is contained in:
Tobias Bosch
2016-11-18 08:40:41 -08:00
committed by Chuck Jazdzewski
parent 3c06a5dc25
commit 2a5bd2f345
9 changed files with 173 additions and 130 deletions

View File

@ -36,8 +36,8 @@ const PREAMBLE = `/**
export class CodeGenerator {
constructor(
private options: AngularCompilerOptions, private program: ts.Program,
public host: ts.CompilerHost, private staticReflector: compiler.StaticReflector,
private compiler: compiler.AotCompiler, private ngCompilerHost: CompilerHost) {}
public host: ts.CompilerHost, private compiler: compiler.AotCompiler,
private ngCompilerHost: CompilerHost) {}
// Write codegen in a directory structure matching the sources.
private calculateEmitPath(filePath: string): string {
@ -96,7 +96,7 @@ export class CodeGenerator {
}
transContent = readFileSync(transFile, 'utf8');
}
const {compiler: aotCompiler, reflector} = compiler.createAotCompiler(ngCompilerHost, {
const {compiler: aotCompiler} = compiler.createAotCompiler(ngCompilerHost, {
debug: options.debug === true,
translations: transContent,
i18nFormat: cliOptions.i18nFormat,
@ -104,18 +104,10 @@ export class CodeGenerator {
excludeFilePattern: options.generateCodeForLibraries === false ? GENERATED_OR_DTS_FILES :
GENERATED_FILES
});
return new CodeGenerator(
options, program, tsCompilerHost, reflector, aotCompiler, ngCompilerHost);
return new CodeGenerator(options, program, tsCompilerHost, aotCompiler, ngCompilerHost);
}
}
export function extractProgramSymbols(
program: ts.Program, staticReflector: compiler.StaticReflector, compilerHost: CompilerHost,
options: AngularCompilerOptions): compiler.StaticSymbol[] {
return compiler.extractProgramSymbols(
staticReflector,
program.getSourceFiles().map(sf => compilerHost.getCanonicalFileName(sf.fileName)), {
excludeFilePattern: options.generateCodeForLibraries === false ? GENERATED_OR_DTS_FILES :
GENERATED_FILES
});
export function excludeFilePattern(options: AngularCompilerOptions): RegExp {
return options.generateCodeForLibraries === false ? GENERATED_OR_DTS_FILES : GENERATED_FILES;
}

View File

@ -24,17 +24,7 @@ import {Extractor} from './extractor';
function extract(
ngOptions: tsc.AngularCompilerOptions, cliOptions: tsc.I18nExtractionCliOptions,
program: ts.Program, host: ts.CompilerHost) {
const resourceLoader: compiler.ResourceLoader = {
get: (s: string) => {
if (!host.fileExists(s)) {
// TODO: We should really have a test for error cases like this!
throw new Error(`Compilation failed. Resource file not found: ${s}`);
}
return Promise.resolve(host.readFile(s));
}
};
const extractor =
Extractor.create(ngOptions, cliOptions.i18nFormat, program, host, resourceLoader);
const extractor = Extractor.create(ngOptions, cliOptions.i18nFormat, program, host);
const bundlePromise: Promise<compiler.MessageBundle> = extractor.extract();

View File

@ -14,84 +14,28 @@
import 'reflect-metadata';
import * as compiler from '@angular/compiler';
import {ViewEncapsulation} from '@angular/core';
import * as tsc from '@angular/tsc-wrapped';
import * as ts from 'typescript';
import {extractProgramSymbols} from './codegen';
import {excludeFilePattern} from './codegen';
import {CompilerHost} from './compiler_host';
export class Extractor {
constructor(
private options: tsc.AngularCompilerOptions, private program: ts.Program,
public host: ts.CompilerHost, private staticReflector: compiler.StaticReflector,
private messageBundle: compiler.MessageBundle, private compilerHost: CompilerHost,
private metadataResolver: compiler.CompileMetadataResolver) {}
private ngExtractor: compiler.Extractor, private ngCompilerHost: CompilerHost,
private program: ts.Program) {}
extract(): Promise<compiler.MessageBundle> {
const programSymbols: compiler.StaticSymbol[] =
extractProgramSymbols(this.program, this.staticReflector, this.compilerHost, this.options);
const {ngModules, files} =
compiler.analyzeAndValidateNgModules(programSymbols, {}, this.metadataResolver);
return compiler.loadNgModuleDirectives(ngModules).then(() => {
const errors: compiler.ParseError[] = [];
files.forEach(file => {
const compMetas: compiler.CompileDirectiveMetadata[] = [];
file.directives.forEach(directiveType => {
const dirMeta = this.metadataResolver.getDirectiveMetadata(directiveType);
if (dirMeta && dirMeta.isComponent) {
compMetas.push(dirMeta);
}
});
compMetas.forEach(compMeta => {
const html = compMeta.template.template;
const interpolationConfig =
compiler.InterpolationConfig.fromArray(compMeta.template.interpolation);
errors.push(
...this.messageBundle.updateFromTemplate(html, file.srcUrl, interpolationConfig));
});
});
if (errors.length) {
throw new Error(errors.map(e => e.toString()).join('\n'));
}
return this.messageBundle;
});
return this.ngExtractor.extract(this.program.getSourceFiles().map(
sf => this.ngCompilerHost.getCanonicalFileName(sf.fileName)))
}
static create(
options: tsc.AngularCompilerOptions, translationsFormat: string, program: ts.Program,
tsCompilerHost: ts.CompilerHost, resourceLoader: compiler.ResourceLoader,
ngCompilerHost?: CompilerHost): Extractor {
const htmlParser = new compiler.I18NHtmlParser(new compiler.HtmlParser());
const urlResolver: compiler.UrlResolver = compiler.createOfflineCompileUrlResolver();
tsCompilerHost: ts.CompilerHost, ngCompilerHost?: CompilerHost): Extractor {
if (!ngCompilerHost) ngCompilerHost = new CompilerHost(program, tsCompilerHost, options);
const staticReflector = new compiler.StaticReflector(ngCompilerHost);
compiler.StaticAndDynamicReflectionCapabilities.install(staticReflector);
const config = new compiler.CompilerConfig({
genDebugInfo: options.debug === true,
defaultEncapsulation: ViewEncapsulation.Emulated,
logBindingUpdate: false,
useJit: false
});
const normalizer =
new compiler.DirectiveNormalizer(resourceLoader, urlResolver, htmlParser, config);
const elementSchemaRegistry = new compiler.DomElementSchemaRegistry();
const resolver = new compiler.CompileMetadataResolver(
new compiler.NgModuleResolver(staticReflector),
new compiler.DirectiveResolver(staticReflector), new compiler.PipeResolver(staticReflector),
elementSchemaRegistry, normalizer, staticReflector);
// TODO(vicb): implicit tags & attributes
const messageBundle = new compiler.MessageBundle(htmlParser, [], {});
return new Extractor(
options, program, tsCompilerHost, staticReflector, messageBundle, ngCompilerHost, resolver);
const {extractor: ngExtractor} = compiler.Extractor.create(
ngCompilerHost, {excludeFilePattern: excludeFilePattern(options)});
return new Extractor(ngExtractor, ngCompilerHost, program);
}
}
}