refactor(compiler): renames

- `NgHost` to `CompilerHost`
- `AotCompilerHost.resolveFileToImport` to `AotCompilerHost.fileNameToModuleName`
- `AotCompilerHoset.resolveImportToFile` to `AotCompilerHost.moduleNameToFileName`
This commit is contained in:
Tobias Bosch 2016-11-17 12:24:33 -08:00 committed by Chuck Jazdzewski
parent dddbb1c1cb
commit adeea5d86a
15 changed files with 92 additions and 86 deletions

View File

@ -8,7 +8,7 @@
export {AotCompilerHost, AotCompilerHost as StaticReflectorHost, StaticReflector, StaticSymbol} from '@angular/compiler'; export {AotCompilerHost, AotCompilerHost as StaticReflectorHost, StaticReflector, StaticSymbol} from '@angular/compiler';
export {CodeGenerator} from './src/codegen'; export {CodeGenerator} from './src/codegen';
export {CompilerHost, CompilerHostContext, NodeCompilerHostContext} from './src/compiler_host';
export {Extractor} from './src/extractor'; export {Extractor} from './src/extractor';
export {NgHost, NgHostContext, NodeNgHostContext} from './src/ng_host';
export * from '@angular/tsc-wrapped'; export * from '@angular/tsc-wrapped';

View File

@ -17,8 +17,8 @@ import {readFileSync} from 'fs';
import * as path from 'path'; import * as path from 'path';
import * as ts from 'typescript'; import * as ts from 'typescript';
import {NgHost, NgHostContext} from './ng_host'; import {CompilerHost, CompilerHostContext} from './compiler_host';
import {PathMappedNgHost} from './path_mapped_ng_host'; import {PathMappedCompilerHost} from './path_mapped_compiler_host';
import {Console} from './private_import_core'; import {Console} from './private_import_core';
const GENERATED_FILES = /\.ngfactory\.ts$|\.css\.ts$|\.css\.shim\.ts$/; const GENERATED_FILES = /\.ngfactory\.ts$|\.css\.ts$|\.css\.shim\.ts$/;
@ -37,7 +37,7 @@ export class CodeGenerator {
constructor( constructor(
private options: AngularCompilerOptions, private program: ts.Program, private options: AngularCompilerOptions, private program: ts.Program,
public host: ts.CompilerHost, private staticReflector: compiler.StaticReflector, public host: ts.CompilerHost, private staticReflector: compiler.StaticReflector,
private compiler: compiler.AotCompiler, private ngHost: NgHost) {} private compiler: compiler.AotCompiler, private ngCompilerHost: CompilerHost) {}
// Write codegen in a directory structure matching the sources. // Write codegen in a directory structure matching the sources.
private calculateEmitPath(filePath: string): string { private calculateEmitPath(filePath: string): string {
@ -64,8 +64,8 @@ export class CodeGenerator {
codegen(): Promise<any> { codegen(): Promise<any> {
return this.compiler return this.compiler
.compileAll( .compileAll(this.program.getSourceFiles().map(
this.program.getSourceFiles().map(sf => this.ngHost.getCanonicalFileName(sf.fileName))) sf => this.ngCompilerHost.getCanonicalFileName(sf.fileName)))
.then(generatedModules => { .then(generatedModules => {
generatedModules.forEach(generatedModule => { generatedModules.forEach(generatedModule => {
const sourceFile = this.program.getSourceFile(generatedModule.fileUrl); const sourceFile = this.program.getSourceFile(generatedModule.fileUrl);
@ -78,13 +78,13 @@ export class CodeGenerator {
static create( static create(
options: AngularCompilerOptions, cliOptions: NgcCliOptions, program: ts.Program, options: AngularCompilerOptions, cliOptions: NgcCliOptions, program: ts.Program,
compilerHost: ts.CompilerHost, ngHostContext?: NgHostContext, tsCompilerHost: ts.CompilerHost, compilerHostContext?: CompilerHostContext,
ngHost?: NgHost): CodeGenerator { ngCompilerHost?: CompilerHost): CodeGenerator {
if (!ngHost) { if (!ngCompilerHost) {
const usePathMapping = !!options.rootDirs && options.rootDirs.length > 0; const usePathMapping = !!options.rootDirs && options.rootDirs.length > 0;
ngHost = usePathMapping ? ngCompilerHost = usePathMapping ?
new PathMappedNgHost(program, compilerHost, options, ngHostContext) : new PathMappedCompilerHost(program, tsCompilerHost, options, compilerHostContext) :
new NgHost(program, compilerHost, options, ngHostContext); new CompilerHost(program, tsCompilerHost, options, compilerHostContext);
} }
const transFile = cliOptions.i18nFile; const transFile = cliOptions.i18nFile;
const locale = cliOptions.locale; const locale = cliOptions.locale;
@ -96,7 +96,7 @@ export class CodeGenerator {
} }
transContent = readFileSync(transFile, 'utf8'); transContent = readFileSync(transFile, 'utf8');
} }
const {compiler: aotCompiler, reflector} = compiler.createAotCompiler(ngHost, { const {compiler: aotCompiler, reflector} = compiler.createAotCompiler(ngCompilerHost, {
debug: options.debug === true, debug: options.debug === true,
translations: transContent, translations: transContent,
i18nFormat: cliOptions.i18nFormat, i18nFormat: cliOptions.i18nFormat,
@ -104,16 +104,17 @@ export class CodeGenerator {
excludeFilePattern: options.generateCodeForLibraries === false ? GENERATED_OR_DTS_FILES : excludeFilePattern: options.generateCodeForLibraries === false ? GENERATED_OR_DTS_FILES :
GENERATED_FILES GENERATED_FILES
}); });
return new CodeGenerator(options, program, compilerHost, reflector, aotCompiler, ngHost); return new CodeGenerator(
options, program, tsCompilerHost, reflector, aotCompiler, ngCompilerHost);
} }
} }
export function extractProgramSymbols( export function extractProgramSymbols(
program: ts.Program, staticReflector: compiler.StaticReflector, ngHost: NgHost, program: ts.Program, staticReflector: compiler.StaticReflector, compilerHost: CompilerHost,
options: AngularCompilerOptions): compiler.StaticSymbol[] { options: AngularCompilerOptions): compiler.StaticSymbol[] {
return compiler.extractProgramSymbols( return compiler.extractProgramSymbols(
staticReflector, program.getSourceFiles().map(sf => ngHost.getCanonicalFileName(sf.fileName)), staticReflector,
{ program.getSourceFiles().map(sf => compilerHost.getCanonicalFileName(sf.fileName)), {
excludeFilePattern: options.generateCodeForLibraries === false ? GENERATED_OR_DTS_FILES : excludeFilePattern: options.generateCodeForLibraries === false ? GENERATED_OR_DTS_FILES :
GENERATED_FILES GENERATED_FILES
}); });

View File

@ -17,7 +17,7 @@ const DTS = /\.d\.ts$/;
const NODE_MODULES = '/node_modules/'; const NODE_MODULES = '/node_modules/';
const IS_GENERATED = /\.(ngfactory|css(\.shim)?)$/; const IS_GENERATED = /\.(ngfactory|css(\.shim)?)$/;
export interface NgHostContext { export interface CompilerHostContext {
fileExists(fileName: string): boolean; fileExists(fileName: string): boolean;
directoryExists(directoryName: string): boolean; directoryExists(directoryName: string): boolean;
readFile(fileName: string): string; readFile(fileName: string): string;
@ -25,9 +25,9 @@ export interface NgHostContext {
assumeFileExists(fileName: string): void; assumeFileExists(fileName: string): void;
} }
export class NgHost implements AotCompilerHost { export class CompilerHost implements AotCompilerHost {
protected metadataCollector = new MetadataCollector(); protected metadataCollector = new MetadataCollector();
protected context: NgHostContext; protected context: CompilerHostContext;
private isGenDirChildOfRootDir: boolean; private isGenDirChildOfRootDir: boolean;
protected basePath: string; protected basePath: string;
private genDir: string; private genDir: string;
@ -35,12 +35,12 @@ export class NgHost implements AotCompilerHost {
constructor( constructor(
protected program: ts.Program, protected compilerHost: ts.CompilerHost, protected program: ts.Program, protected compilerHost: ts.CompilerHost,
protected options: AngularCompilerOptions, context?: NgHostContext) { protected options: AngularCompilerOptions, context?: CompilerHostContext) {
// normalize the path so that it never ends with '/'. // normalize the path so that it never ends with '/'.
this.basePath = path.normalize(path.join(this.options.basePath, '.')).replace(/\\/g, '/'); this.basePath = path.normalize(path.join(this.options.basePath, '.')).replace(/\\/g, '/');
this.genDir = path.normalize(path.join(this.options.genDir, '.')).replace(/\\/g, '/'); this.genDir = path.normalize(path.join(this.options.genDir, '.')).replace(/\\/g, '/');
this.context = context || new NodeNgHostContext(compilerHost); this.context = context || new NodeCompilerHostContext(compilerHost);
const genPath: string = path.relative(this.basePath, this.genDir); const genPath: string = path.relative(this.basePath, this.genDir);
this.isGenDirChildOfRootDir = genPath === '' || !genPath.startsWith('..'); this.isGenDirChildOfRootDir = genPath === '' || !genPath.startsWith('..');
} }
@ -48,7 +48,7 @@ export class NgHost implements AotCompilerHost {
// We use absolute paths on disk as canonical. // We use absolute paths on disk as canonical.
getCanonicalFileName(fileName: string): string { return fileName; } getCanonicalFileName(fileName: string): string { return fileName; }
resolveImportToFile(m: string, containingFile: string) { moduleNameToFileName(m: string, containingFile: string) {
if (!containingFile || !containingFile.length) { if (!containingFile || !containingFile.length) {
if (m.indexOf('.') === 0) { if (m.indexOf('.') === 0) {
throw new Error('Resolution of relative paths requires a containing file.'); throw new Error('Resolution of relative paths requires a containing file.');
@ -78,7 +78,7 @@ export class NgHost implements AotCompilerHost {
* *
* NOTE: (*) the relative path is computed depending on `isGenDirChildOfRootDir`. * NOTE: (*) the relative path is computed depending on `isGenDirChildOfRootDir`.
*/ */
resolveFileToImport(importedFile: string, containingFile: string): string { fileNameToModuleName(importedFile: string, containingFile: string): string {
// If a file does not yet exist (because we compile it later), we still need to // If a file does not yet exist (because we compile it later), we still need to
// assume it exists it so that the `resolve` method works! // assume it exists it so that the `resolve` method works!
if (!this.compilerHost.fileExists(importedFile)) { if (!this.compilerHost.fileExists(importedFile)) {
@ -149,6 +149,7 @@ export class NgHost implements AotCompilerHost {
} }
throw new Error(`Source file ${filePath} not present in program.`); throw new Error(`Source file ${filePath} not present in program.`);
} }
return sf;
} }
getMetadataFor(filePath: string): ModuleMetadata[] { getMetadataFor(filePath: string): ModuleMetadata[] {
@ -215,7 +216,7 @@ export class NgHost implements AotCompilerHost {
loadResource(filePath: string): Promise<string> { return this.context.readResource(filePath); } loadResource(filePath: string): Promise<string> { return this.context.readResource(filePath); }
} }
export class NodeNgHostContext implements NgHostContext { export class NodeCompilerHostContext implements CompilerHostContext {
constructor(private host: ts.CompilerHost) {} constructor(private host: ts.CompilerHost) {}
private assumedExists: {[fileName: string]: boolean} = {}; private assumedExists: {[fileName: string]: boolean} = {};

View File

@ -19,18 +19,18 @@ import * as tsc from '@angular/tsc-wrapped';
import * as ts from 'typescript'; import * as ts from 'typescript';
import {extractProgramSymbols} from './codegen'; import {extractProgramSymbols} from './codegen';
import {NgHost} from './ng_host'; import {CompilerHost} from './compiler_host';
export class Extractor { export class Extractor {
constructor( constructor(
private options: tsc.AngularCompilerOptions, private program: ts.Program, private options: tsc.AngularCompilerOptions, private program: ts.Program,
public host: ts.CompilerHost, private staticReflector: compiler.StaticReflector, public host: ts.CompilerHost, private staticReflector: compiler.StaticReflector,
private messageBundle: compiler.MessageBundle, private ngHost: NgHost, private messageBundle: compiler.MessageBundle, private compilerHost: CompilerHost,
private metadataResolver: compiler.CompileMetadataResolver) {} private metadataResolver: compiler.CompileMetadataResolver) {}
extract(): Promise<compiler.MessageBundle> { extract(): Promise<compiler.MessageBundle> {
const programSymbols: compiler.StaticSymbol[] = const programSymbols: compiler.StaticSymbol[] =
extractProgramSymbols(this.program, this.staticReflector, this.ngHost, this.options); extractProgramSymbols(this.program, this.staticReflector, this.compilerHost, this.options);
const {ngModules, files} = compiler.analyzeAndValidateNgModules( const {ngModules, files} = compiler.analyzeAndValidateNgModules(
programSymbols, {transitiveModules: true}, this.metadataResolver); programSymbols, {transitiveModules: true}, this.metadataResolver);
@ -64,13 +64,13 @@ export class Extractor {
static create( static create(
options: tsc.AngularCompilerOptions, translationsFormat: string, program: ts.Program, options: tsc.AngularCompilerOptions, translationsFormat: string, program: ts.Program,
compilerHost: ts.CompilerHost, resourceLoader: compiler.ResourceLoader, tsCompilerHost: ts.CompilerHost, resourceLoader: compiler.ResourceLoader,
ngHost?: NgHost): Extractor { ngCompilerHost?: CompilerHost): Extractor {
const htmlParser = new compiler.I18NHtmlParser(new compiler.HtmlParser()); const htmlParser = new compiler.I18NHtmlParser(new compiler.HtmlParser());
const urlResolver: compiler.UrlResolver = compiler.createOfflineCompileUrlResolver(); const urlResolver: compiler.UrlResolver = compiler.createOfflineCompileUrlResolver();
if (!ngHost) ngHost = new NgHost(program, compilerHost, options); if (!ngCompilerHost) ngCompilerHost = new CompilerHost(program, tsCompilerHost, options);
const staticReflector = new compiler.StaticReflector(ngHost); const staticReflector = new compiler.StaticReflector(ngCompilerHost);
compiler.StaticAndDynamicReflectionCapabilities.install(staticReflector); compiler.StaticAndDynamicReflectionCapabilities.install(staticReflector);
const config = new compiler.CompilerConfig({ const config = new compiler.CompilerConfig({
@ -92,6 +92,6 @@ export class Extractor {
const messageBundle = new compiler.MessageBundle(htmlParser, [], {}); const messageBundle = new compiler.MessageBundle(htmlParser, [], {});
return new Extractor( return new Extractor(
options, program, compilerHost, staticReflector, messageBundle, ngHost, resolver); options, program, tsCompilerHost, staticReflector, messageBundle, ngCompilerHost, resolver);
} }
} }

View File

@ -12,7 +12,7 @@ import * as fs from 'fs';
import * as path from 'path'; import * as path from 'path';
import * as ts from 'typescript'; import * as ts from 'typescript';
import {NgHost, NgHostContext} from './ng_host'; import {CompilerHost, CompilerHostContext} from './compiler_host';
const EXT = /(\.ts|\.d\.ts|\.js|\.jsx|\.tsx)$/; const EXT = /(\.ts|\.d\.ts|\.js|\.jsx|\.tsx)$/;
const DTS = /\.d\.ts$/; const DTS = /\.d\.ts$/;
@ -24,10 +24,10 @@ const DTS = /\.d\.ts$/;
* import. This requires using TS `rootDirs` option and also teaching the module * import. This requires using TS `rootDirs` option and also teaching the module
* loader what to do. * loader what to do.
*/ */
export class PathMappedNgHost extends NgHost { export class PathMappedCompilerHost extends CompilerHost {
constructor( constructor(
program: ts.Program, compilerHost: ts.CompilerHost, options: AngularCompilerOptions, program: ts.Program, compilerHost: ts.CompilerHost, options: AngularCompilerOptions,
context?: NgHostContext) { context?: CompilerHostContext) {
super(program, compilerHost, options, context); super(program, compilerHost, options, context);
} }
@ -42,7 +42,7 @@ export class PathMappedNgHost extends NgHost {
return fileName; return fileName;
} }
resolveImportToFile(m: string, containingFile: string) { moduleNameToFileName(m: string, containingFile: string) {
if (!containingFile || !containingFile.length) { if (!containingFile || !containingFile.length) {
if (m.indexOf('.') === 0) { if (m.indexOf('.') === 0) {
throw new Error('Resolution of relative paths requires a containing file.'); throw new Error('Resolution of relative paths requires a containing file.');
@ -69,7 +69,7 @@ export class PathMappedNgHost extends NgHost {
* Relativize the paths by checking candidate prefixes of the absolute path, to see if * Relativize the paths by checking candidate prefixes of the absolute path, to see if
* they are resolvable by the moduleResolution strategy from the CompilerHost. * they are resolvable by the moduleResolution strategy from the CompilerHost.
*/ */
resolveFileToImport(importedFile: string, containingFile: string): string { fileNameToModuleName(importedFile: string, containingFile: string): string {
if (this.options.traceResolution) { if (this.options.traceResolution) {
console.log( console.log(
'getImportPath from containingFile', containingFile, 'to importedFile', importedFile); 'getImportPath from containingFile', containingFile, 'to importedFile', importedFile);
@ -86,7 +86,8 @@ export class PathMappedNgHost extends NgHost {
} }
const resolvable = (candidate: string) => { const resolvable = (candidate: string) => {
const resolved = this.getCanonicalFileName(this.resolveImportToFile(candidate, importedFile)); const resolved =
this.getCanonicalFileName(this.moduleNameToFileName(candidate, importedFile));
return resolved && resolved.replace(EXT, '') === importedFile.replace(EXT, ''); return resolved && resolved.replace(EXT, '') === importedFile.replace(EXT, '');
}; };

View File

@ -8,19 +8,19 @@
import * as ts from 'typescript'; import * as ts from 'typescript';
import {NgHost} from '../src/ng_host'; import {CompilerHost} from '../src/compiler_host';
import {Directory, Entry, MockCompilerHost, MockContext} from './mocks'; import {Directory, Entry, MockAotContext, MockCompilerHost} from './mocks';
describe('NgHost', () => { describe('CompilerHost', () => {
let context: MockContext; let context: MockAotContext;
let host: ts.CompilerHost; let host: ts.CompilerHost;
let program: ts.Program; let program: ts.Program;
let hostNestedGenDir: NgHost; let hostNestedGenDir: CompilerHost;
let hostSiblingGenDir: NgHost; let hostSiblingGenDir: CompilerHost;
beforeEach(() => { beforeEach(() => {
context = new MockContext('/tmp/src', clone(FILES)); context = new MockAotContext('/tmp/src', clone(FILES));
host = new MockCompilerHost(context); host = new MockCompilerHost(context);
program = ts.createProgram( program = ts.createProgram(
['main.ts'], { ['main.ts'], {
@ -32,7 +32,7 @@ describe('NgHost', () => {
if (errors && errors.length) { if (errors && errors.length) {
throw new Error('Expected no errors'); throw new Error('Expected no errors');
} }
hostNestedGenDir = new NgHost( hostNestedGenDir = new CompilerHost(
program, host, { program, host, {
genDir: '/tmp/project/src/gen/', genDir: '/tmp/project/src/gen/',
basePath: '/tmp/project/src', basePath: '/tmp/project/src',
@ -42,7 +42,7 @@ describe('NgHost', () => {
trace: false trace: false
}, },
context); context);
hostSiblingGenDir = new NgHost( hostSiblingGenDir = new CompilerHost(
program, host, { program, host, {
genDir: '/tmp/project/gen', genDir: '/tmp/project/gen',
basePath: '/tmp/project/src/', basePath: '/tmp/project/src/',
@ -56,32 +56,32 @@ describe('NgHost', () => {
describe('nestedGenDir', () => { describe('nestedGenDir', () => {
it('should import node_module from factory', () => { it('should import node_module from factory', () => {
expect(hostNestedGenDir.resolveFileToImport( expect(hostNestedGenDir.fileNameToModuleName(
'/tmp/project/node_modules/@angular/core.d.ts', '/tmp/project/node_modules/@angular/core.d.ts',
'/tmp/project/src/gen/my.ngfactory.ts', )) '/tmp/project/src/gen/my.ngfactory.ts', ))
.toEqual('@angular/core'); .toEqual('@angular/core');
}); });
it('should import factory from factory', () => { it('should import factory from factory', () => {
expect(hostNestedGenDir.resolveFileToImport( expect(hostNestedGenDir.fileNameToModuleName(
'/tmp/project/src/my.other.ngfactory.ts', '/tmp/project/src/my.ngfactory.ts')) '/tmp/project/src/my.other.ngfactory.ts', '/tmp/project/src/my.ngfactory.ts'))
.toEqual('./my.other.ngfactory'); .toEqual('./my.other.ngfactory');
expect(hostNestedGenDir.resolveFileToImport( expect(hostNestedGenDir.fileNameToModuleName(
'/tmp/project/src/my.other.css.ts', '/tmp/project/src/a/my.ngfactory.ts')) '/tmp/project/src/my.other.css.ts', '/tmp/project/src/a/my.ngfactory.ts'))
.toEqual('../my.other.css'); .toEqual('../my.other.css');
expect(hostNestedGenDir.resolveFileToImport( expect(hostNestedGenDir.fileNameToModuleName(
'/tmp/project/src/a/my.other.css.shim.ts', '/tmp/project/src/my.ngfactory.ts')) '/tmp/project/src/a/my.other.css.shim.ts', '/tmp/project/src/my.ngfactory.ts'))
.toEqual('./a/my.other.css.shim'); .toEqual('./a/my.other.css.shim');
}); });
it('should import application from factory', () => { it('should import application from factory', () => {
expect(hostNestedGenDir.resolveFileToImport( expect(hostNestedGenDir.fileNameToModuleName(
'/tmp/project/src/my.other.ts', '/tmp/project/src/my.ngfactory.ts')) '/tmp/project/src/my.other.ts', '/tmp/project/src/my.ngfactory.ts'))
.toEqual('../my.other'); .toEqual('../my.other');
expect(hostNestedGenDir.resolveFileToImport( expect(hostNestedGenDir.fileNameToModuleName(
'/tmp/project/src/my.other.ts', '/tmp/project/src/a/my.ngfactory.ts')) '/tmp/project/src/my.other.ts', '/tmp/project/src/a/my.ngfactory.ts'))
.toEqual('../../my.other'); .toEqual('../../my.other');
expect(hostNestedGenDir.resolveFileToImport( expect(hostNestedGenDir.fileNameToModuleName(
'/tmp/project/src/a/my.other.ts', '/tmp/project/src/my.ngfactory.ts')) '/tmp/project/src/a/my.other.ts', '/tmp/project/src/my.ngfactory.ts'))
.toEqual('../a/my.other'); .toEqual('../a/my.other');
}); });
@ -89,54 +89,54 @@ describe('NgHost', () => {
describe('siblingGenDir', () => { describe('siblingGenDir', () => {
it('should import node_module from factory', () => { it('should import node_module from factory', () => {
expect(hostSiblingGenDir.resolveFileToImport( expect(hostSiblingGenDir.fileNameToModuleName(
'/tmp/project/node_modules/@angular/core.d.ts', '/tmp/project/node_modules/@angular/core.d.ts',
'/tmp/project/src/gen/my.ngfactory.ts')) '/tmp/project/src/gen/my.ngfactory.ts'))
.toEqual('@angular/core'); .toEqual('@angular/core');
}); });
it('should import factory from factory', () => { it('should import factory from factory', () => {
expect(hostSiblingGenDir.resolveFileToImport( expect(hostSiblingGenDir.fileNameToModuleName(
'/tmp/project/src/my.other.ngfactory.ts', '/tmp/project/src/my.ngfactory.ts')) '/tmp/project/src/my.other.ngfactory.ts', '/tmp/project/src/my.ngfactory.ts'))
.toEqual('./my.other.ngfactory'); .toEqual('./my.other.ngfactory');
expect(hostSiblingGenDir.resolveFileToImport( expect(hostSiblingGenDir.fileNameToModuleName(
'/tmp/project/src/my.other.css.ts', '/tmp/project/src/a/my.ngfactory.ts')) '/tmp/project/src/my.other.css.ts', '/tmp/project/src/a/my.ngfactory.ts'))
.toEqual('../my.other.css'); .toEqual('../my.other.css');
expect(hostSiblingGenDir.resolveFileToImport( expect(hostSiblingGenDir.fileNameToModuleName(
'/tmp/project/src/a/my.other.css.shim.ts', '/tmp/project/src/my.ngfactory.ts')) '/tmp/project/src/a/my.other.css.shim.ts', '/tmp/project/src/my.ngfactory.ts'))
.toEqual('./a/my.other.css.shim'); .toEqual('./a/my.other.css.shim');
}); });
it('should import application from factory', () => { it('should import application from factory', () => {
expect(hostSiblingGenDir.resolveFileToImport( expect(hostSiblingGenDir.fileNameToModuleName(
'/tmp/project/src/my.other.ts', '/tmp/project/src/my.ngfactory.ts')) '/tmp/project/src/my.other.ts', '/tmp/project/src/my.ngfactory.ts'))
.toEqual('./my.other'); .toEqual('./my.other');
expect(hostSiblingGenDir.resolveFileToImport( expect(hostSiblingGenDir.fileNameToModuleName(
'/tmp/project/src/my.other.ts', '/tmp/project/src/a/my.ngfactory.ts')) '/tmp/project/src/my.other.ts', '/tmp/project/src/a/my.ngfactory.ts'))
.toEqual('../my.other'); .toEqual('../my.other');
expect(hostSiblingGenDir.resolveFileToImport( expect(hostSiblingGenDir.fileNameToModuleName(
'/tmp/project/src/a/my.other.ts', '/tmp/project/src/my.ngfactory.ts')) '/tmp/project/src/a/my.other.ts', '/tmp/project/src/my.ngfactory.ts'))
.toEqual('./a/my.other'); .toEqual('./a/my.other');
}); });
}); });
it('should be able to produce an import from main @angular/core', () => { it('should be able to produce an import from main @angular/core', () => {
expect(hostNestedGenDir.resolveFileToImport( expect(hostNestedGenDir.fileNameToModuleName(
'/tmp/project/node_modules/@angular/core.d.ts', '/tmp/project/src/main.ts')) '/tmp/project/node_modules/@angular/core.d.ts', '/tmp/project/src/main.ts'))
.toEqual('@angular/core'); .toEqual('@angular/core');
}); });
it('should be able to produce an import from main to a sub-directory', () => { it('should be able to produce an import from main to a sub-directory', () => {
expect(hostNestedGenDir.resolveFileToImport('lib/utils.ts', 'main.ts')).toEqual('./lib/utils'); expect(hostNestedGenDir.fileNameToModuleName('lib/utils.ts', 'main.ts')).toEqual('./lib/utils');
}); });
it('should be able to produce an import from to a peer file', () => { it('should be able to produce an import from to a peer file', () => {
expect(hostNestedGenDir.resolveFileToImport('lib/collections.ts', 'lib/utils.ts')) expect(hostNestedGenDir.fileNameToModuleName('lib/collections.ts', 'lib/utils.ts'))
.toEqual('./collections'); .toEqual('./collections');
}); });
it('should be able to produce an import from to a sibling directory', () => { it('should be able to produce an import from to a sibling directory', () => {
expect(hostNestedGenDir.resolveFileToImport('lib/utils.ts', 'lib2/utils2.ts')) expect(hostNestedGenDir.fileNameToModuleName('lib/utils.ts', 'lib2/utils2.ts'))
.toEqual('../lib/utils'); .toEqual('../lib/utils');
}); });

View File

@ -6,14 +6,14 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {NgHostContext} from '@angular/compiler-cli/src/ng_host'; import {CompilerHostContext} from '@angular/compiler-cli/src/compiler_host';
import * as ts from 'typescript'; import * as ts from 'typescript';
export type Entry = string | Directory; export type Entry = string | Directory;
export interface Directory { [name: string]: Entry; } export interface Directory { [name: string]: Entry; }
export class MockContext implements NgHostContext { export class MockAotContext implements CompilerHostContext {
constructor(public currentDirectory: string, private files: Entry) {} constructor(public currentDirectory: string, private files: Entry) {}
fileExists(fileName: string): boolean { return typeof this.getEntry(fileName) === 'string'; } fileExists(fileName: string): boolean { return typeof this.getEntry(fileName) === 'string'; }
@ -97,7 +97,7 @@ function normalize(parts: string[]): string[] {
} }
export class MockCompilerHost implements ts.CompilerHost { export class MockCompilerHost implements ts.CompilerHost {
constructor(private context: MockContext) {} constructor(private context: MockAotContext) {}
fileExists(fileName: string): boolean { return this.context.fileExists(fileName); } fileExists(fileName: string): boolean { return this.context.fileExists(fileName); }

View File

@ -40,12 +40,12 @@ import {StaticReflector} from './static_reflector';
/** /**
* Creates a new AotCompiler based on options and a host. * Creates a new AotCompiler based on options and a host.
*/ */
export function createAotCompiler(ngHost: AotCompilerHost, options: AotCompilerOptions): export function createAotCompiler(compilerHost: AotCompilerHost, options: AotCompilerOptions):
{compiler: AotCompiler, reflector: StaticReflector} { {compiler: AotCompiler, reflector: StaticReflector} {
let translations: string = options.translations || ''; let translations: string = options.translations || '';
const urlResolver = createOfflineCompileUrlResolver(); const urlResolver = createOfflineCompileUrlResolver();
const staticReflector = new StaticReflector(ngHost); const staticReflector = new StaticReflector(compilerHost);
StaticAndDynamicReflectionCapabilities.install(staticReflector); StaticAndDynamicReflectionCapabilities.install(staticReflector);
const htmlParser = new I18NHtmlParser(new HtmlParser(), translations, options.i18nFormat); const htmlParser = new I18NHtmlParser(new HtmlParser(), translations, options.i18nFormat);
const config = new CompilerConfig({ const config = new CompilerConfig({
@ -55,7 +55,7 @@ export function createAotCompiler(ngHost: AotCompilerHost, options: AotCompilerO
useJit: false useJit: false
}); });
const normalizer = new DirectiveNormalizer( const normalizer = new DirectiveNormalizer(
{get: (url: string) => ngHost.loadResource(url)}, urlResolver, htmlParser, config); {get: (url: string) => compilerHost.loadResource(url)}, urlResolver, htmlParser, config);
const expressionParser = new Parser(new Lexer()); const expressionParser = new Parser(new Lexer());
const elementSchemaRegistry = new DomElementSchemaRegistry(); const elementSchemaRegistry = new DomElementSchemaRegistry();
const console = new Console(); const console = new Console();
@ -69,7 +69,7 @@ export function createAotCompiler(ngHost: AotCompilerHost, options: AotCompilerO
resolver, tmplParser, new StyleCompiler(urlResolver), resolver, tmplParser, new StyleCompiler(urlResolver),
new ViewCompiler(config, elementSchemaRegistry), new ViewCompiler(config, elementSchemaRegistry),
new DirectiveWrapperCompiler(config, expressionParser, elementSchemaRegistry, console), new DirectiveWrapperCompiler(config, expressionParser, elementSchemaRegistry, console),
new NgModuleCompiler(), new TypeScriptEmitter(ngHost), options.locale, options.i18nFormat, new NgModuleCompiler(), new TypeScriptEmitter(compilerHost), options.locale,
new AnimationParser(elementSchemaRegistry), staticReflector, options); options.i18nFormat, new AnimationParser(elementSchemaRegistry), staticReflector, options);
return {compiler, reflector: staticReflector}; return {compiler, reflector: staticReflector};
} }

View File

@ -25,14 +25,17 @@ export interface AotCompilerHost {
getMetadataFor(modulePath: string): {[key: string]: any}[]; getMetadataFor(modulePath: string): {[key: string]: any}[];
/** /**
* Converts an import into a file path. * Converts a module name that is used in an `import` to a file path.
* I.e.
* `path/to/containingFile.ts` containing `import {...} from 'module-name'`.
*/ */
resolveImportToFile(moduleName: string, containingFile: string): string; moduleNameToFileName(moduleName: string, containingFile: string): string;
/** /**
* Converts a file path to an import * Converts a file path to a module name that can be used as an `import.
* I.e. `path/to/importedFile.ts` should be imported by `path/to/containingFile.ts`.
*/ */
resolveFileToImport(importedFilePath: string, containingFilePath: string): string; fileNameToModuleName(importedFile: string, containingFile: string): string;
/** /**
* Loads a resource (e.g. html / css) * Loads a resource (e.g. html / css)

View File

@ -214,7 +214,7 @@ export class StaticReflector implements ReflectorReader {
private resolveExportedSymbol(filePath: string, symbolName: string): StaticSymbol { private resolveExportedSymbol(filePath: string, symbolName: string): StaticSymbol {
const resolveModule = (moduleName: string): string => { const resolveModule = (moduleName: string): string => {
const resolvedModulePath = this.host.resolveImportToFile(moduleName, filePath); const resolvedModulePath = this.host.moduleNameToFileName(moduleName, filePath);
if (!resolvedModulePath) { if (!resolvedModulePath) {
throw new Error(`Could not resolve module '${moduleName}' relative to file ${filePath}`); throw new Error(`Could not resolve module '${moduleName}' relative to file ${filePath}`);
} }
@ -269,7 +269,7 @@ export class StaticReflector implements ReflectorReader {
return symbol; return symbol;
} }
try { try {
const filePath = this.host.resolveImportToFile(module, containingFile); const filePath = this.host.moduleNameToFileName(module, containingFile);
if (!filePath) { if (!filePath) {
// If the file cannot be found the module is probably referencing a declared module // If the file cannot be found the module is probably referencing a declared module

View File

@ -25,7 +25,7 @@ export class JavaScriptEmitter implements OutputEmitter {
// Note: can't write the real word for import as it screws up system.js auto detection... // Note: can't write the real word for import as it screws up system.js auto detection...
srcParts.push( srcParts.push(
`var ${prefix} = req` + `var ${prefix} = req` +
`uire('${this._importGenerator.resolveFileToImport(importedModuleUrl, moduleUrl)}');`); `uire('${this._importGenerator.fileNameToModuleName(importedModuleUrl, moduleUrl)}');`);
}); });
srcParts.push(ctx.toSource()); srcParts.push(ctx.toSource());
return srcParts.join('\n'); return srcParts.join('\n');

View File

@ -10,5 +10,5 @@
* Interface that defines how import statements should be generated. * Interface that defines how import statements should be generated.
*/ */
export abstract class ImportResolver { export abstract class ImportResolver {
abstract resolveFileToImport(importedFilePath: string, containingFilePath: string): string; abstract fileNameToModuleName(importedFilePath: string, containingFilePath: string): string;
} }

View File

@ -47,7 +47,7 @@ export class TypeScriptEmitter implements OutputEmitter {
// Note: can't write the real word for import as it screws up system.js auto detection... // Note: can't write the real word for import as it screws up system.js auto detection...
srcParts.push( srcParts.push(
`imp` + `imp` +
`ort * as ${prefix} from '${this._importGenerator.resolveFileToImport(importedModuleUrl, moduleUrl)}';`); `ort * as ${prefix} from '${this._importGenerator.fileNameToModuleName(importedModuleUrl, moduleUrl)}';`);
}); });
srcParts.push(ctx.toSource()); srcParts.push(ctx.toSource());
return srcParts.join('\n'); return srcParts.join('\n');

View File

@ -511,12 +511,12 @@ class MockAotCompilerHost implements AotCompilerHost {
loadResource(filePath: string): Promise<string> { throw new Error('Should not be called!'); } loadResource(filePath: string): Promise<string> { throw new Error('Should not be called!'); }
resolveFileToImport(importedFilePath: string, containingFilePath: string): string { fileNameToModuleName(importedFilePath: string, containingFilePath: string): string {
throw new Error('Should not be called!'); throw new Error('Should not be called!');
} }
// In tests, assume that symbols are not re-exported // In tests, assume that symbols are not re-exported
resolveImportToFile(modulePath: string, containingFile?: string): string { moduleNameToFileName(modulePath: string, containingFile?: string): string {
function splitPath(path: string): string[] { return path.split(/\/|\\/g); } function splitPath(path: string): string[] { return path.split(/\/|\\/g); }
function resolvePath(pathParts: string[]): string { function resolvePath(pathParts: string[]): string {

View File

@ -253,7 +253,7 @@ function createOperatorFn(op: o.BinaryOperator) {
} }
export class SimpleJsImportGenerator implements ImportResolver { export class SimpleJsImportGenerator implements ImportResolver {
resolveFileToImport(importedUrlStr: string, moduleUrlStr: string): string { fileNameToModuleName(importedUrlStr: string, moduleUrlStr: string): string {
return importedUrlStr; return importedUrlStr;
} }
} }