From 13e930afff183c2716a14290d5883476b71f31eb Mon Sep 17 00:00:00 2001 From: Dan Bucholtz Date: Fri, 27 Jan 2017 16:42:10 -0600 Subject: [PATCH] fix(angular): support angular 2.3+ ngc api --- package.json | 18 +++++++++--------- src/aot/aot-compiler.ts | 28 +++++++++------------------- src/aot/codegen.ts | 13 +++++++++++++ src/aot/codegen/codegen-ng22.ts | 23 +++++++++++++++++++++++ src/aot/codegen/codegen-ng23plus.ts | 22 ++++++++++++++++++++++ src/aot/reflector-host.ts | 25 ------------------------- src/util/interfaces.ts | 13 ++++++++++++- 7 files changed, 88 insertions(+), 54 deletions(-) create mode 100644 src/aot/codegen.ts create mode 100644 src/aot/codegen/codegen-ng22.ts create mode 100644 src/aot/codegen/codegen-ng23plus.ts delete mode 100644 src/aot/reflector-host.ts diff --git a/package.json b/package.json index ce174a04..de9761a8 100644 --- a/package.json +++ b/package.json @@ -60,15 +60,15 @@ "xml2js": "^0.4.17" }, "devDependencies": { - "@angular/common": "2.2.1", - "@angular/compiler": "2.2.1", - "@angular/compiler-cli": "2.2.1", - "@angular/core": "2.2.1", - "@angular/forms": "2.2.1", - "@angular/http": "2.2.1", - "@angular/platform-browser": "2.2.1", - "@angular/platform-browser-dynamic": "2.2.1", - "@angular/platform-server": "2.2.1", + "@angular/common": "4.0.0-beta.5", + "@angular/compiler": "4.0.0-beta.5", + "@angular/compiler-cli": "4.0.0-beta.5", + "@angular/core": "4.0.0-beta.5", + "@angular/forms": "4.0.0-beta.5", + "@angular/http": "4.0.0-beta.5", + "@angular/platform-browser": "4.0.0-beta.5", + "@angular/platform-browser-dynamic": "4.0.0-beta.5", + "@angular/platform-server": "4.0.0-beta.5", "@types/chalk": "^0.4.30", "@types/chokidar": "1.4.29", "@types/clean-css": "^3.4.29", diff --git a/src/aot/aot-compiler.ts b/src/aot/aot-compiler.ts index 5573291e..11adf74e 100644 --- a/src/aot/aot-compiler.ts +++ b/src/aot/aot-compiler.ts @@ -3,7 +3,7 @@ import { basename, dirname, extname, join, normalize, relative, resolve } from ' import 'reflect-metadata'; import { CompilerOptions, createProgram, ParsedCommandLine, Program, transpileModule, TranspileOptions, TranspileOutput } from 'typescript'; -import { CodeGenerator, NgcCliOptions, NodeReflectorHostContext, ReflectorHost, StaticReflector }from '@angular/compiler-cli'; +import { NgcCliOptions }from '@angular/compiler-cli'; import { tsc } from '@angular/tsc-wrapped/src/tsc'; import AngularCompilerOptions from '@angular/tsc-wrapped/src/options'; @@ -11,7 +11,6 @@ import { HybridFileSystem } from '../util/hybrid-file-system'; import { getInstance as getHybridFileSystem } from '../util/hybrid-file-system-factory'; import { getInstance } from './compiler-host-factory'; import { NgcCompilerHost } from './compiler-host'; -import { patchReflectorHost } from './reflector-host'; import { getFallbackMainContent, replaceBootstrap } from './utils'; import { Logger } from '../logger/logger'; import { printDiagnostics, clearDiagnostics, DiagnosticsType } from '../logger/logger-diagnostics'; @@ -21,13 +20,13 @@ import { BuildError } from '../util/errors'; import { changeExtension } from '../util/helpers'; import { BuildContext } from '../util/interfaces'; +import { doCodegen } from './codegen'; + export class AotCompiler { private tsConfig: ParsedTsConfig; private angularCompilerOptions: AngularCompilerOptions; private program: Program; - private reflector: StaticReflector; - private reflectorHost: ReflectorHost; private compilerHost: NgcCompilerHost; private fileSystem: HybridFileSystem; private lazyLoadedModuleDictionary: any; @@ -43,8 +42,6 @@ export class AotCompiler { this.fileSystem = getHybridFileSystem(); this.compilerHost = getInstance(this.tsConfig.parsed.options); this.program = createProgram(this.tsConfig.parsed.fileNames, this.tsConfig.parsed.options, this.compilerHost); - this.reflectorHost = new ReflectorHost(this.program, this.compilerHost, this.angularCompilerOptions); - this.reflector = new StaticReflector(this.reflectorHost); } compile(): Promise { @@ -58,20 +55,13 @@ export class AotCompiler { basePath: this.options.rootDir }; - // Create the Code Generator. - const codeGenerator = CodeGenerator.create( - this.angularCompilerOptions, - i18nOptions, - this.program, - this.compilerHost, - new NodeReflectorHostContext(this.compilerHost) - ); - - // We need to temporarily patch the CodeGenerator until either it's patched or allows us - // to pass in our own ReflectorHost. - patchReflectorHost(codeGenerator); Logger.debug('[AotCompiler] compile: starting codegen ... '); - return codeGenerator.codegen({transitiveModules: true}); + return doCodegen({ + angularCompilerOptions: this.angularCompilerOptions, + cliOptions: i18nOptions, + program: this.program, + compilerHost: this.compilerHost + }); }).then(() => { Logger.debug('[AotCompiler] compile: starting codegen ... DONE'); Logger.debug('[AotCompiler] compile: Creating and validating new TypeScript Program ...'); diff --git a/src/aot/codegen.ts b/src/aot/codegen.ts new file mode 100644 index 00000000..478c74f4 --- /dev/null +++ b/src/aot/codegen.ts @@ -0,0 +1,13 @@ +import { CodegenOptions } from '../util/interfaces'; +import { runCodegen, isAngular22 } from './codegen/codegen-ng22'; +import { runCodegen as runCodegen23 } from './codegen/codegen-ng23plus'; + + +export function doCodegen(options: CodegenOptions) { + if (isAngular22()) { + return runCodegen(options); + } + return runCodegen23(options); +} + + diff --git a/src/aot/codegen/codegen-ng22.ts b/src/aot/codegen/codegen-ng22.ts new file mode 100644 index 00000000..54c64c0c --- /dev/null +++ b/src/aot/codegen/codegen-ng22.ts @@ -0,0 +1,23 @@ +import * as CompilerCLI from '@angular/compiler-cli'; +import { CodegenOptions } from '../../util/interfaces'; + +export function isAngular22() { + if ((CompilerCLI as any).NodeReflectorHostContext) { + return true; + } + return false; +} + +export function runCodegen(options: CodegenOptions) { + const NodeReflectorHostContextConstructor = (CompilerCLI as any).NodeReflectorHostContext; + const instance = new NodeReflectorHostContextConstructor(options.compilerHost); + const codeGenerator = CompilerCLI.CodeGenerator.create(options.angularCompilerOptions, + options.cliOptions, + options.program, + options.compilerHost, + instance); + + // angular 2.2 api to codegen + return (codeGenerator.codegen as any)({transitiveModules: true}); +} + diff --git a/src/aot/codegen/codegen-ng23plus.ts b/src/aot/codegen/codegen-ng23plus.ts new file mode 100644 index 00000000..39e3ef0c --- /dev/null +++ b/src/aot/codegen/codegen-ng23plus.ts @@ -0,0 +1,22 @@ +import * as CompilerCLI from '@angular/compiler-cli'; +import { CodegenOptions } from '../../util/interfaces'; + +export function isAngular23Plus() { + if ((CompilerCLI as any).NodeCompilerHostContext) { + return true; + } + return false; +} + +export function runCodegen(options: CodegenOptions) { + const NodeCompilerHostContext = (CompilerCLI as any).NodeCompilerHostContext; + const instance = new NodeCompilerHostContext(); + const codeGenerator = CompilerCLI.CodeGenerator.create(options.angularCompilerOptions, + options.cliOptions, + options.program, + options.compilerHost, + instance); + + // angular 2.3+ api for codegen does not take any options + return (codeGenerator.codegen as any)(); +} diff --git a/src/aot/reflector-host.ts b/src/aot/reflector-host.ts deleted file mode 100644 index 6db2e693..00000000 --- a/src/aot/reflector-host.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { CodeGenerator } from '@angular/compiler-cli'; - -/** - * Patch the CodeGenerator instance to use a custom reflector host. - */ -export function patchReflectorHost(codeGenerator: CodeGenerator) { - const reflectorHost = (codeGenerator as any).reflectorHost; - const oldGIP = reflectorHost.getImportPath; - - reflectorHost.getImportPath = function(containingFile: string, importedFile: string): string { - // Hack together SCSS and LESS files URLs so that they match what the default ReflectorHost - // is expected. We only do that for shimmed styles. - const m = importedFile.match(/(.*)(\..+)(\.shim)(\..+)/); - if (!m) { - return oldGIP.call(this, containingFile, importedFile); - } - - // We call the original, with `css` in its name instead of the extension, and replace the - // extension from the result. - const [, baseDirAndName, styleExt, shim, ext] = m; - const result = oldGIP.call(this, containingFile, baseDirAndName + '.css' + shim + ext); - - return result.replace(/\.css\./, styleExt + '.'); - }; -} diff --git a/src/util/interfaces.ts b/src/util/interfaces.ts index 865fd424..5999bfc5 100644 --- a/src/util/interfaces.ts +++ b/src/util/interfaces.ts @@ -1,3 +1,7 @@ +import * as CompilerCLI from '@angular/compiler-cli'; +import AngularCompilerOptions from '@angular/tsc-wrapped/src/options'; +import { CompilerHost, Program } from 'typescript'; + import { FileCache } from './file-cache'; import { VirtualDirStats, VirtualFileStats } from './virtual-file-utils'; @@ -147,4 +151,11 @@ export interface HydratedDeepLinkConfigEntry extends DeepLinkConfigEntry { export interface AppNgModuleInfo { absolutePath: string; className: string; -}; \ No newline at end of file +}; + +export interface CodegenOptions { + angularCompilerOptions: AngularCompilerOptions; + cliOptions: CompilerCLI.NgcCliOptions; + program: Program; + compilerHost: CompilerHost; +};