@@ -10,6 +10,7 @@ import {isSyntaxError, Position} from '@angular/compiler';
1010import * as ts from 'typescript' ;
1111
1212import { absoluteFrom , AbsoluteFsPath , getFileSystem , ReadonlyFileSystem , relative , resolve } from '../src/ngtsc/file_system' ;
13+ import { NgCompilerOptions } from './ngtsc/core/api' ;
1314
1415import { replaceTsWithNgInErrors } from './ngtsc/diagnostics' ;
1516import * as api from './transformers/api' ;
@@ -132,39 +133,28 @@ export function calcProjectFileAndBasePath(
132133 return { projectFile, basePath} ;
133134}
134135
135- export function createNgCompilerOptions (
136- basePath : string , config : any , tsOptions : ts . CompilerOptions ) : api . CompilerOptions {
137- // enableIvy `ngtsc` is an alias for `true`.
138- const { angularCompilerOptions = { } } = config ;
139- const { enableIvy} = angularCompilerOptions ;
140- angularCompilerOptions . enableIvy = enableIvy !== false && enableIvy !== 'tsc' ;
141-
142- return { ...tsOptions , ...angularCompilerOptions , genDir : basePath , basePath} ;
143- }
144-
145136export function readConfiguration (
146- project : string , existingOptions ?: ts . CompilerOptions ,
137+ project : string , existingOptions ?: api . CompilerOptions ,
147138 host : ConfigurationHost = getFileSystem ( ) ) : ParsedConfiguration {
148139 try {
149- const { projectFile, basePath} = calcProjectFileAndBasePath ( project , host ) ;
150-
151- const readExtendedConfigFile =
152- ( configFile : string , existingConfig ?: any ) : { config ?: any , error ?: ts . Diagnostic } => {
153- const { config, error} =
154- ts . readConfigFile ( configFile , file => host . readFile ( host . resolve ( file ) ) ) ;
140+ const readConfigFile = ( configFile : string ) =>
141+ ts . readConfigFile ( configFile , file => host . readFile ( host . resolve ( file ) ) ) ;
142+ const readAngularCompilerOptions =
143+ ( configFile : string , parentOptions : NgCompilerOptions = { } ) : NgCompilerOptions => {
144+ const { config, error} = readConfigFile ( configFile ) ;
155145
156146 if ( error ) {
157- return { error} ;
147+ // Errors are handled later on by 'parseJsonConfigFileContent'
148+ return parentOptions ;
158149 }
159150
160151 // we are only interested into merging 'angularCompilerOptions' as
161152 // other options like 'compilerOptions' are merged by TS
162- const baseConfig = existingConfig || config ;
163- if ( existingConfig ) {
164- baseConfig . angularCompilerOptions = {
165- ...config . angularCompilerOptions ,
166- ...baseConfig . angularCompilerOptions
167- } ;
153+ let existingNgCompilerOptions : NgCompilerOptions ;
154+ if ( parentOptions && config . angularCompilerOptions ) {
155+ existingNgCompilerOptions = { ...config . angularCompilerOptions , ...parentOptions } ;
156+ } else {
157+ existingNgCompilerOptions = parentOptions || config . angularCompilerOptions ;
168158 }
169159
170160 if ( config . extends ) {
@@ -174,16 +164,24 @@ export function readConfiguration(
174164 absoluteFrom ( `${ extendedConfigPath } .json` ) ;
175165
176166 if ( host . exists ( extendedConfigPath ) ) {
177- // Call read config recursively as TypeScript only merges CompilerOptions
178- return readExtendedConfigFile ( extendedConfigPath , baseConfig ) ;
167+ // Call readAngularCompilerOptions recursively to merge NG Compiler options
168+ return readAngularCompilerOptions ( extendedConfigPath , existingNgCompilerOptions ) ;
179169 }
180170 }
181171
182- return { config : baseConfig } ;
172+ return existingNgCompilerOptions ;
183173 } ;
184174
185- const { config, error} = readExtendedConfigFile ( projectFile ) ;
175+ const parseConfigHost = {
176+ useCaseSensitiveFileNames : true ,
177+ fileExists : host . exists . bind ( host ) ,
178+ readDirectory : ts . sys . readDirectory ,
179+ readFile : ts . sys . readFile
180+ } ;
186181
182+ const { projectFile, basePath} = calcProjectFileAndBasePath ( project , host ) ;
183+ const configFileName = host . resolve ( host . pwd ( ) , projectFile ) ;
184+ const { config, error} = readConfigFile ( projectFile ) ;
187185 if ( error ) {
188186 return {
189187 project,
@@ -193,34 +191,28 @@ export function readConfiguration(
193191 emitFlags : api . EmitFlags . Default
194192 } ;
195193 }
196- const parseConfigHost = {
197- useCaseSensitiveFileNames : true ,
198- fileExists : host . exists . bind ( host ) ,
199- readDirectory : ts . sys . readDirectory ,
200- readFile : ts . sys . readFile
194+ const existingCompilerOptions = {
195+ genDir : basePath ,
196+ basePath ,
197+ ... readAngularCompilerOptions ( configFileName ) ,
198+ ... existingOptions ,
201199 } ;
202- const configFileName = host . resolve ( host . pwd ( ) , projectFile ) ;
203- const parsed = ts . parseJsonConfigFileContent (
204- config , parseConfigHost , basePath , existingOptions , configFileName ) ;
205- const rootNames = parsed . fileNames ;
206- const projectReferences = parsed . projectReferences ;
207200
208- const options = createNgCompilerOptions ( basePath , config , parsed . options ) ;
201+ const { options, errors, fileNames : rootNames , projectReferences} =
202+ ts . parseJsonConfigFileContent (
203+ config , parseConfigHost , basePath , existingCompilerOptions , configFileName ) ;
204+
205+ // Coerce to boolean as `enableIvy` can be `ngtsc|true|false|undefined` here.
206+ options . enableIvy = ! ! ( options . enableIvy ?? true ) ;
207+
209208 let emitFlags = api . EmitFlags . Default ;
210209 if ( ! ( options . skipMetadataEmit || options . flatModuleOutFile ) ) {
211210 emitFlags |= api . EmitFlags . Metadata ;
212211 }
213212 if ( options . skipTemplateCodegen ) {
214213 emitFlags = emitFlags & ~ api . EmitFlags . Codegen ;
215214 }
216- return {
217- project : projectFile ,
218- rootNames,
219- projectReferences,
220- options,
221- errors : parsed . errors ,
222- emitFlags
223- } ;
215+ return { project : projectFile , rootNames, projectReferences, options, errors, emitFlags} ;
224216 } catch ( e ) {
225217 const errors : ts . Diagnostic [ ] = [ {
226218 category : ts . DiagnosticCategory . Error ,
0 commit comments