diff --git a/packages/compiler-cli/src/main.ts b/packages/compiler-cli/src/main.ts index 0801be6106..27880ceb02 100644 --- a/packages/compiler-cli/src/main.ts +++ b/packages/compiler-cli/src/main.ts @@ -22,7 +22,7 @@ import {performWatchCompilation, createPerformWatchHost} from './perform_watch' export function main( args: string[], consoleError: (s: string) => void = console.error, - config?: NgcParsedConfiguration): number { + config?: NgcParsedConfiguration, customTransformers?: api.CustomTransformers): number { let {project, rootNames, options, errors: configErrors, watch, emitFlags} = config || readNgcCommandLineAndConfiguration(args); if (configErrors.length) { @@ -32,8 +32,12 @@ export function main( const result = watchMode(project, options, consoleError); return reportErrorsAndExit(result.firstCompileResult, options, consoleError); } - const {diagnostics: compileDiags} = performCompilation( - {rootNames, options, emitFlags, emitCallback: createEmitCallback(options)}); + const {diagnostics: compileDiags} = performCompilation({ + rootNames, + options, + emitFlags, + emitCallback: createEmitCallback(options), customTransformers + }); return reportErrorsAndExit(compileDiags, options, consoleError); } diff --git a/packages/compiler-cli/src/ngtsc/program.ts b/packages/compiler-cli/src/ngtsc/program.ts index fe17878985..293fdb8d5f 100644 --- a/packages/compiler-cli/src/ngtsc/program.ts +++ b/packages/compiler-cli/src/ngtsc/program.ts @@ -208,14 +208,21 @@ export class NgtscProgram implements api.Program { this.host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles); }; - const transforms = + const customTransforms = opts && opts.customTransformers; + const beforeTransforms = [ivyTransformFactory(this.compilation !, this.reflector, this.coreImportsFrom)]; + if (this.factoryToSourceInfo !== null) { - transforms.push(generatedFactoryTransform(this.factoryToSourceInfo, this.coreImportsFrom)); + beforeTransforms.push( + generatedFactoryTransform(this.factoryToSourceInfo, this.coreImportsFrom)); } if (this.isCore) { - transforms.push(ivySwitchTransform); + beforeTransforms.push(ivySwitchTransform); } + if (customTransforms && customTransforms.beforeTs) { + beforeTransforms.push(...customTransforms.beforeTs); + } + // Run the emit, including a custom transformer that will downlevel the Ivy decorators in code. const emitResult = emitCallback({ program: this.tsProgram, @@ -223,7 +230,8 @@ export class NgtscProgram implements api.Program { options: this.options, emitOnlyDtsFiles: false, writeFile, customTransformers: { - before: transforms, + before: beforeTransforms, + after: customTransforms && customTransforms.afterTs, }, }); return emitResult; diff --git a/packages/compiler-cli/test/ngtsc/env.ts b/packages/compiler-cli/test/ngtsc/env.ts index 6fbf828c73..4f63b32655 100644 --- a/packages/compiler-cli/test/ngtsc/env.ts +++ b/packages/compiler-cli/test/ngtsc/env.ts @@ -6,6 +6,7 @@ * found in the LICENSE file at https://angular.io/license */ +import {CustomTransformers} from '@angular/compiler-cli'; import * as fs from 'fs'; import * as path from 'path'; import * as ts from 'typescript'; @@ -111,9 +112,9 @@ export class NgtscTestEnvironment { /** * Run the compiler to completion, and assert that no errors occurred. */ - driveMain(): void { + driveMain(customTransformers?: CustomTransformers): void { const errorSpy = jasmine.createSpy('consoleError').and.callFake(console.error); - const exitCode = main(['-p', this.basePath], errorSpy); + const exitCode = main(['-p', this.basePath], errorSpy, undefined, customTransformers); expect(errorSpy).not.toHaveBeenCalled(); expect(exitCode).toBe(0); } diff --git a/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts b/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts index 93677ad278..db29fd0d0b 100644 --- a/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts +++ b/packages/compiler-cli/test/ngtsc/ngtsc_spec.ts @@ -1227,4 +1227,32 @@ describe('ngtsc behavioral tests', () => { expect(dtsContents).toContain('/// '); }); }); + + it('should execute custom transformers', () => { + let beforeCount = 0; + let afterCount = 0; + + env.tsconfig(); + env.write('test.ts', ` + import {NgModule} from '@angular/core'; + + @NgModule({}) + class Module {} + `); + + env.driveMain({ + beforeTs: [() => sourceFile => { + beforeCount++; + return sourceFile; + }], + afterTs: [() => sourceFile => { + afterCount++; + return sourceFile; + }], + }); + + expect(beforeCount).toBe(1); + expect(afterCount).toBe(1); + }); + });