refactor(compiler): renames
- `NgHost` to `CompilerHost` - `AotCompilerHost.resolveFileToImport` to `AotCompilerHost.fileNameToModuleName` - `AotCompilerHoset.resolveImportToFile` to `AotCompilerHost.moduleNameToFileName`
This commit is contained in:
parent
dddbb1c1cb
commit
adeea5d86a
|
@ -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';
|
||||||
|
|
|
@ -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
|
||||||
});
|
});
|
||||||
|
|
|
@ -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} = {};
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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, '');
|
||||||
};
|
};
|
||||||
|
|
|
@ -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');
|
||||||
});
|
});
|
||||||
|
|
|
@ -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); }
|
||||||
|
|
||||||
|
|
|
@ -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};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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');
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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');
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue