refactor(compiler): add createAotCompiler
factory
Also adds 2 more methods to the `AotCompilerHost`: - `loadResource` - `resolveFileToImport`
This commit is contained in:

committed by
Chuck Jazdzewski

parent
484119e59f
commit
2235048432
@ -78,17 +78,7 @@ export class CodeGenerator {
|
||||
|
||||
static create(
|
||||
options: AngularCompilerOptions, cliOptions: NgcCliOptions, program: ts.Program,
|
||||
compilerHost: ts.CompilerHost, ngHostContext?: NgHostContext,
|
||||
resourceLoader?: compiler.ResourceLoader, ngHost?: NgHost): CodeGenerator {
|
||||
resourceLoader = resourceLoader || {
|
||||
get: (s: string) => {
|
||||
if (!compilerHost.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(compilerHost.readFile(s));
|
||||
}
|
||||
};
|
||||
compilerHost: ts.CompilerHost, ngHost?: NgHost): CodeGenerator {
|
||||
const transFile = cliOptions.i18nFile;
|
||||
const locale = cliOptions.locale;
|
||||
let transContent: string = '';
|
||||
@ -99,45 +89,13 @@ export class CodeGenerator {
|
||||
}
|
||||
transContent = readFileSync(transFile, 'utf8');
|
||||
}
|
||||
|
||||
const urlResolver: compiler.UrlResolver = compiler.createOfflineCompileUrlResolver();
|
||||
if (!ngHost) {
|
||||
const usePathMapping = !!options.rootDirs && options.rootDirs.length > 0;
|
||||
ngHost = usePathMapping ?
|
||||
new PathMappedNgHost(program, compilerHost, options, ngHostContext) :
|
||||
new NgHost(program, compilerHost, options, ngHostContext);
|
||||
}
|
||||
const staticReflector = new compiler.StaticReflector(ngHost);
|
||||
compiler.StaticAndDynamicReflectionCapabilities.install(staticReflector);
|
||||
const htmlParser =
|
||||
new compiler.I18NHtmlParser(new compiler.HtmlParser(), transContent, cliOptions.i18nFormat);
|
||||
const config = new compiler.CompilerConfig({
|
||||
genDebugInfo: options.debug === true,
|
||||
defaultEncapsulation: ViewEncapsulation.Emulated,
|
||||
logBindingUpdate: false,
|
||||
useJit: false
|
||||
const {compiler: aotCompiler, reflector} = compiler.createAotCompiler(ngHost, {
|
||||
debug: options.debug === true,
|
||||
translations: transContent,
|
||||
i18nFormat: cliOptions.i18nFormat,
|
||||
locale: cliOptions.locale
|
||||
});
|
||||
const normalizer =
|
||||
new compiler.DirectiveNormalizer(resourceLoader, urlResolver, htmlParser, config);
|
||||
const expressionParser = new compiler.Parser(new compiler.Lexer());
|
||||
const elementSchemaRegistry = new compiler.DomElementSchemaRegistry();
|
||||
const console = new Console();
|
||||
const tmplParser = new compiler.TemplateParser(
|
||||
expressionParser, elementSchemaRegistry, htmlParser, console, []);
|
||||
const resolver = new compiler.CompileMetadataResolver(
|
||||
new compiler.NgModuleResolver(staticReflector),
|
||||
new compiler.DirectiveResolver(staticReflector), new compiler.PipeResolver(staticReflector),
|
||||
elementSchemaRegistry, normalizer, staticReflector);
|
||||
// TODO(vicb): do not pass cliOptions.i18nFormat here
|
||||
const aotCompiler = new compiler.AotCompiler(
|
||||
resolver, tmplParser, new compiler.StyleCompiler(urlResolver),
|
||||
new compiler.ViewCompiler(config, elementSchemaRegistry),
|
||||
new compiler.DirectiveWrapperCompiler(
|
||||
config, expressionParser, elementSchemaRegistry, console),
|
||||
new compiler.NgModuleCompiler(), new compiler.TypeScriptEmitter(ngHost), cliOptions.locale,
|
||||
cliOptions.i18nFormat, new compiler.AnimationParser(elementSchemaRegistry));
|
||||
|
||||
return new CodeGenerator(options, program, compilerHost, staticReflector, aotCompiler, ngHost);
|
||||
return new CodeGenerator(options, program, compilerHost, reflector, aotCompiler, ngHost);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ export interface NgHostContext {
|
||||
fileExists(fileName: string): boolean;
|
||||
directoryExists(directoryName: string): boolean;
|
||||
readFile(fileName: string): string;
|
||||
readResource(fileName: string): Promise<string>;
|
||||
assumeFileExists(fileName: string): void;
|
||||
}
|
||||
|
||||
@ -75,7 +76,7 @@ export class NgHost implements AotCompilerHost {
|
||||
*
|
||||
* NOTE: (*) the relative path is computed depending on `isGenDirChildOfRootDir`.
|
||||
*/
|
||||
getImportPath(containingFile: string, importedFile: string): string {
|
||||
resolveFileToImport(importedFile: string, containingFile: string): string {
|
||||
// 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!
|
||||
if (!this.compilerHost.fileExists(importedFile)) {
|
||||
@ -176,6 +177,8 @@ export class NgHost implements AotCompilerHost {
|
||||
}
|
||||
}
|
||||
|
||||
loadResource(filePath: string): Promise<string> { return this.context.readResource(filePath); }
|
||||
|
||||
private getResolverMetadata(filePath: string): ModuleMetadata {
|
||||
let metadata = this.resolverCache.get(filePath);
|
||||
if (!metadata) {
|
||||
@ -205,5 +208,13 @@ export class NodeNgHostContext implements NgHostContext {
|
||||
|
||||
readFile(fileName: string): string { return fs.readFileSync(fileName, 'utf8'); }
|
||||
|
||||
readResource(s: string) {
|
||||
if (!this.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(this.host.readFile(s));
|
||||
}
|
||||
|
||||
assumeFileExists(fileName: string): void { this.assumedExists[fileName] = true; }
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ export class PathMappedNgHost extends NgHost {
|
||||
* Relativize the paths by checking candidate prefixes of the absolute path, to see if
|
||||
* they are resolvable by the moduleResolution strategy from the CompilerHost.
|
||||
*/
|
||||
getImportPath(containingFile: string, importedFile: string): string {
|
||||
resolveFileToImport(importedFile: string, containingFile: string): string {
|
||||
if (this.options.traceResolution) {
|
||||
console.log(
|
||||
'getImportPath from containingFile', containingFile, 'to importedFile', importedFile);
|
||||
|
@ -28,6 +28,14 @@ export class MockContext implements NgHostContext {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
readResource(fileName: string): Promise<string> {
|
||||
const result = this.readFile(fileName);
|
||||
if (result == null) {
|
||||
return Promise.reject(new Error(`Resource not found: ${fileName}`));
|
||||
}
|
||||
return Promise.resolve(result);
|
||||
}
|
||||
|
||||
writeFile(fileName: string, data: string): void {
|
||||
const parts = fileName.split('/');
|
||||
const name = parts.pop();
|
||||
|
@ -6,7 +6,6 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {beforeEach, describe, expect, it} from '@angular/core/testing/testing_internal';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {NgHost} from '../src/ng_host';
|
||||
@ -57,87 +56,87 @@ describe('NgHost', () => {
|
||||
|
||||
describe('nestedGenDir', () => {
|
||||
it('should import node_module from factory', () => {
|
||||
expect(hostNestedGenDir.getImportPath(
|
||||
'/tmp/project/src/gen/my.ngfactory.ts',
|
||||
'/tmp/project/node_modules/@angular/core.d.ts'))
|
||||
expect(hostNestedGenDir.resolveFileToImport(
|
||||
'/tmp/project/node_modules/@angular/core.d.ts',
|
||||
'/tmp/project/src/gen/my.ngfactory.ts', ))
|
||||
.toEqual('@angular/core');
|
||||
});
|
||||
|
||||
it('should import factory from factory', () => {
|
||||
expect(hostNestedGenDir.getImportPath(
|
||||
'/tmp/project/src/my.ngfactory.ts', '/tmp/project/src/my.other.ngfactory.ts'))
|
||||
expect(hostNestedGenDir.resolveFileToImport(
|
||||
'/tmp/project/src/my.other.ngfactory.ts', '/tmp/project/src/my.ngfactory.ts'))
|
||||
.toEqual('./my.other.ngfactory');
|
||||
expect(hostNestedGenDir.getImportPath(
|
||||
'/tmp/project/src/a/my.ngfactory.ts', '/tmp/project/src/my.other.css.ts'))
|
||||
expect(hostNestedGenDir.resolveFileToImport(
|
||||
'/tmp/project/src/my.other.css.ts', '/tmp/project/src/a/my.ngfactory.ts'))
|
||||
.toEqual('../my.other.css');
|
||||
expect(hostNestedGenDir.getImportPath(
|
||||
'/tmp/project/src/my.ngfactory.ts', '/tmp/project/src/a/my.other.css.shim.ts'))
|
||||
expect(hostNestedGenDir.resolveFileToImport(
|
||||
'/tmp/project/src/a/my.other.css.shim.ts', '/tmp/project/src/my.ngfactory.ts'))
|
||||
.toEqual('./a/my.other.css.shim');
|
||||
});
|
||||
|
||||
it('should import application from factory', () => {
|
||||
expect(hostNestedGenDir.getImportPath(
|
||||
'/tmp/project/src/my.ngfactory.ts', '/tmp/project/src/my.other.ts'))
|
||||
expect(hostNestedGenDir.resolveFileToImport(
|
||||
'/tmp/project/src/my.other.ts', '/tmp/project/src/my.ngfactory.ts'))
|
||||
.toEqual('../my.other');
|
||||
expect(hostNestedGenDir.getImportPath(
|
||||
'/tmp/project/src/a/my.ngfactory.ts', '/tmp/project/src/my.other.ts'))
|
||||
expect(hostNestedGenDir.resolveFileToImport(
|
||||
'/tmp/project/src/my.other.ts', '/tmp/project/src/a/my.ngfactory.ts'))
|
||||
.toEqual('../../my.other');
|
||||
expect(hostNestedGenDir.getImportPath(
|
||||
'/tmp/project/src/my.ngfactory.ts', '/tmp/project/src/a/my.other.ts'))
|
||||
expect(hostNestedGenDir.resolveFileToImport(
|
||||
'/tmp/project/src/a/my.other.ts', '/tmp/project/src/my.ngfactory.ts'))
|
||||
.toEqual('../a/my.other');
|
||||
});
|
||||
});
|
||||
|
||||
describe('nestedGenDir', () => {
|
||||
describe('siblingGenDir', () => {
|
||||
it('should import node_module from factory', () => {
|
||||
expect(hostSiblingGenDir.getImportPath(
|
||||
'/tmp/project/src/gen/my.ngfactory.ts',
|
||||
'/tmp/project/node_modules/@angular/core.d.ts'))
|
||||
expect(hostSiblingGenDir.resolveFileToImport(
|
||||
'/tmp/project/node_modules/@angular/core.d.ts',
|
||||
'/tmp/project/src/gen/my.ngfactory.ts'))
|
||||
.toEqual('@angular/core');
|
||||
});
|
||||
|
||||
it('should import factory from factory', () => {
|
||||
expect(hostSiblingGenDir.getImportPath(
|
||||
'/tmp/project/src/my.ngfactory.ts', '/tmp/project/src/my.other.ngfactory.ts'))
|
||||
expect(hostSiblingGenDir.resolveFileToImport(
|
||||
'/tmp/project/src/my.other.ngfactory.ts', '/tmp/project/src/my.ngfactory.ts'))
|
||||
.toEqual('./my.other.ngfactory');
|
||||
expect(hostSiblingGenDir.getImportPath(
|
||||
'/tmp/project/src/a/my.ngfactory.ts', '/tmp/project/src/my.other.css.ts'))
|
||||
expect(hostSiblingGenDir.resolveFileToImport(
|
||||
'/tmp/project/src/my.other.css.ts', '/tmp/project/src/a/my.ngfactory.ts'))
|
||||
.toEqual('../my.other.css');
|
||||
expect(hostSiblingGenDir.getImportPath(
|
||||
'/tmp/project/src/my.ngfactory.ts', '/tmp/project/src/a/my.other.css.shim.ts'))
|
||||
expect(hostSiblingGenDir.resolveFileToImport(
|
||||
'/tmp/project/src/a/my.other.css.shim.ts', '/tmp/project/src/my.ngfactory.ts'))
|
||||
.toEqual('./a/my.other.css.shim');
|
||||
});
|
||||
|
||||
it('should import application from factory', () => {
|
||||
expect(hostSiblingGenDir.getImportPath(
|
||||
'/tmp/project/src/my.ngfactory.ts', '/tmp/project/src/my.other.ts'))
|
||||
expect(hostSiblingGenDir.resolveFileToImport(
|
||||
'/tmp/project/src/my.other.ts', '/tmp/project/src/my.ngfactory.ts'))
|
||||
.toEqual('./my.other');
|
||||
expect(hostSiblingGenDir.getImportPath(
|
||||
'/tmp/project/src/a/my.ngfactory.ts', '/tmp/project/src/my.other.ts'))
|
||||
expect(hostSiblingGenDir.resolveFileToImport(
|
||||
'/tmp/project/src/my.other.ts', '/tmp/project/src/a/my.ngfactory.ts'))
|
||||
.toEqual('../my.other');
|
||||
expect(hostSiblingGenDir.getImportPath(
|
||||
'/tmp/project/src/my.ngfactory.ts', '/tmp/project/src/a/my.other.ts'))
|
||||
expect(hostSiblingGenDir.resolveFileToImport(
|
||||
'/tmp/project/src/a/my.other.ts', '/tmp/project/src/my.ngfactory.ts'))
|
||||
.toEqual('./a/my.other');
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to produce an import from main @angular/core', () => {
|
||||
expect(hostNestedGenDir.getImportPath(
|
||||
'/tmp/project/src/main.ts', '/tmp/project/node_modules/@angular/core.d.ts'))
|
||||
expect(hostNestedGenDir.resolveFileToImport(
|
||||
'/tmp/project/node_modules/@angular/core.d.ts', '/tmp/project/src/main.ts'))
|
||||
.toEqual('@angular/core');
|
||||
});
|
||||
|
||||
it('should be able to produce an import from main to a sub-directory', () => {
|
||||
expect(hostNestedGenDir.getImportPath('main.ts', 'lib/utils.ts')).toEqual('./lib/utils');
|
||||
expect(hostNestedGenDir.resolveFileToImport('lib/utils.ts', 'main.ts')).toEqual('./lib/utils');
|
||||
});
|
||||
|
||||
it('should be able to produce an import from to a peer file', () => {
|
||||
expect(hostNestedGenDir.getImportPath('lib/utils.ts', 'lib/collections.ts'))
|
||||
expect(hostNestedGenDir.resolveFileToImport('lib/collections.ts', 'lib/utils.ts'))
|
||||
.toEqual('./collections');
|
||||
});
|
||||
|
||||
it('should be able to produce an import from to a sibling directory', () => {
|
||||
expect(hostNestedGenDir.getImportPath('lib2/utils2.ts', 'lib/utils.ts'))
|
||||
expect(hostNestedGenDir.resolveFileToImport('lib/utils.ts', 'lib2/utils2.ts'))
|
||||
.toEqual('../lib/utils');
|
||||
});
|
||||
|
||||
|
Reference in New Issue
Block a user