diff --git a/packages/compiler-cli/src/transformers/compiler_host.ts b/packages/compiler-cli/src/transformers/compiler_host.ts index 7d766fce8a..2796f7a214 100644 --- a/packages/compiler-cli/src/transformers/compiler_host.ts +++ b/packages/compiler-cli/src/transformers/compiler_host.ts @@ -426,6 +426,12 @@ export class TsCompilerAotCompilerTypeCheckHostAdapter implements ts.CompilerHos } isSourceFile(filePath: string): boolean { + // Don't generate any files nor typecheck them + // if skipTemplateCodegen is set and fullTemplateTypeCheck is not yet set, + // for backwards compatibility. + if (this.options.skipTemplateCodegen && !this.options.fullTemplateTypeCheck) { + return false; + } // If we have a summary from a previous compilation, // treat the file never as a source file. if (this.librarySummaries.has(filePath)) { diff --git a/packages/compiler-cli/src/transformers/lower_expressions.ts b/packages/compiler-cli/src/transformers/lower_expressions.ts index 5e6baafff6..0e7ecc3d16 100644 --- a/packages/compiler-cli/src/transformers/lower_expressions.ts +++ b/packages/compiler-cli/src/transformers/lower_expressions.ts @@ -181,11 +181,13 @@ function createVariableStatementForDeclarations(declarations: Declaration[]): ts /* modifiers */ undefined, ts.createVariableDeclarationList(varDecls, ts.NodeFlags.Const)); } -export function getExpressionLoweringTransformFactory(requestsMap: RequestsMap): - (context: ts.TransformationContext) => (sourceFile: ts.SourceFile) => ts.SourceFile { +export function getExpressionLoweringTransformFactory( + requestsMap: RequestsMap, program: ts.Program): (context: ts.TransformationContext) => + (sourceFile: ts.SourceFile) => ts.SourceFile { // Return the factory return (context: ts.TransformationContext) => (sourceFile: ts.SourceFile): ts.SourceFile => { - const requests = requestsMap.getRequests(sourceFile); + // We need to use the original SourceFile for reading metadata, and not the transformed one. + const requests = requestsMap.getRequests(program.getSourceFile(sourceFile.fileName)); if (requests && requests.size) { return transformSourceFile(sourceFile, requests, context); } diff --git a/packages/compiler-cli/src/transformers/program.ts b/packages/compiler-cli/src/transformers/program.ts index 6940a65e7c..ae253b2876 100644 --- a/packages/compiler-cli/src/transformers/program.ts +++ b/packages/compiler-cli/src/transformers/program.ts @@ -386,7 +386,7 @@ class AngularCompilerProgram implements Program { customTransformers?: CustomTransformers): ts.CustomTransformers { const beforeTs: ts.TransformerFactory[] = []; if (!this.options.disableExpressionLowering) { - beforeTs.push(getExpressionLoweringTransformFactory(this.metadataCache)); + beforeTs.push(getExpressionLoweringTransformFactory(this.metadataCache, this.tsProgram)); } beforeTs.push(getAngularEmitterTransformFactory(genFiles)); if (customTransformers && customTransformers.beforeTs) { @@ -754,7 +754,7 @@ export function createSrcToOutPathMapper( export function i18nExtract( formatName: string | null, outFile: string | null, host: ts.CompilerHost, options: CompilerOptions, bundle: MessageBundle): string[] { - formatName = formatName || 'null'; + formatName = formatName || 'xlf'; // Checks the format and returns the extension const ext = i18nGetExtension(formatName); const content = i18nSerialize(bundle, formatName, options); @@ -788,7 +788,7 @@ export function i18nSerialize( } export function i18nGetExtension(formatName: string): string { - const format = (formatName || 'xlf').toLowerCase(); + const format = formatName.toLowerCase(); switch (format) { case 'xmb': diff --git a/packages/compiler-cli/test/transformers/lower_expressions_spec.ts b/packages/compiler-cli/test/transformers/lower_expressions_spec.ts index abbbc6db55..d76d5571ee 100644 --- a/packages/compiler-cli/test/transformers/lower_expressions_spec.ts +++ b/packages/compiler-cli/test/transformers/lower_expressions_spec.ts @@ -181,13 +181,15 @@ function convert(annotatedSource: string) { [fileName], {module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2017}, host); const moduleSourceFile = program.getSourceFile(fileName); const transformers: ts.CustomTransformers = { - before: [getExpressionLoweringTransformFactory({ - getRequests(sourceFile: ts.SourceFile): RequestLocationMap{ - if (sourceFile.fileName == moduleSourceFile.fileName) { - return requests; - } else {return new Map();} - } - })] + before: [getExpressionLoweringTransformFactory( + { + getRequests(sourceFile: ts.SourceFile): RequestLocationMap{ + if (sourceFile.fileName == moduleSourceFile.fileName) { + return requests; + } else {return new Map();} + } + }, + program)] }; let result: string = ''; const emitResult = program.emit( diff --git a/packages/compiler-cli/test/transformers/program_spec.ts b/packages/compiler-cli/test/transformers/program_spec.ts index beeeed5362..3a9f314840 100644 --- a/packages/compiler-cli/test/transformers/program_spec.ts +++ b/packages/compiler-cli/test/transformers/program_spec.ts @@ -11,7 +11,7 @@ import * as fs from 'fs'; import * as path from 'path'; import * as ts from 'typescript'; -import {CompilerHost, LazyRoute} from '../../src/transformers/api'; +import {CompilerHost, EmitFlags, LazyRoute} from '../../src/transformers/api'; import {createSrcToOutPathMapper} from '../../src/transformers/program'; import {GENERATED_FILES, StructureIsReused, tsStructureIsReused} from '../../src/transformers/util'; import {TestSupport, expectNoDiagnosticsInProgram, setup} from '../test_support'; @@ -309,11 +309,35 @@ describe('ng program', () => { }); }); - it('should typecheck templates even if skipTemplateCodegen is set', () => { + it('should not typecheck templates if skipTemplateCodegen is set but fullTemplateTypeCheck is not', + () => { + testSupport.writeFiles({ + 'src/main.ts': ` + import {NgModule} from '@angular/core'; + + @NgModule(() => {if (1==1) return null as any;}) + export class SomeClassWithInvalidMetadata {} + `, + }); + const options = testSupport.createCompilerOptions({skipTemplateCodegen: true}); + const host = ng.createCompilerHost({options}); + const program = ng.createProgram( + {rootNames: [path.resolve(testSupport.basePath, 'src/main.ts')], options, host}); + expectNoDiagnosticsInProgram(options, program); + const emitResult = program.emit({emitFlags: EmitFlags.All}); + expect(emitResult.diagnostics.length).toBe(0); + + testSupport.shouldExist('built/src/main.metadata.json'); + }); + + it('should typecheck templates if skipTemplateCodegen and fullTemplateTypeCheck is set', () => { testSupport.writeFiles({ 'src/main.ts': createModuleAndCompSource('main', `{{nonExistent}}`), }); - const options = testSupport.createCompilerOptions({skipTemplateCodegen: true}); + const options = testSupport.createCompilerOptions({ + skipTemplateCodegen: true, + fullTemplateTypeCheck: true, + }); const host = ng.createCompilerHost({options}); const program = ng.createProgram( {rootNames: [path.resolve(testSupport.basePath, 'src/main.ts')], options, host});