• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1namespace ts {
2    /* @internal */
3    export const compileOnSaveCommandLineOption: CommandLineOption = {
4        name: "compileOnSave",
5        type: "boolean",
6        defaultValueDescription: false,
7    };
8
9    const jsxOptionMap = new Map(getEntries({
10        "preserve": JsxEmit.Preserve,
11        "react-native": JsxEmit.ReactNative,
12        "react": JsxEmit.React,
13        "react-jsx": JsxEmit.ReactJSX,
14        "react-jsxdev": JsxEmit.ReactJSXDev,
15    }));
16
17    /* @internal */
18    export const inverseJsxOptionMap = new Map(arrayFrom(mapIterator(jsxOptionMap.entries(), ([key, value]: [string, JsxEmit]) => ["" + value, key] as const)));
19
20    // NOTE: The order here is important to default lib ordering as entries will have the same
21    //       order in the generated program (see `getDefaultLibPriority` in program.ts). This
22    //       order also affects overload resolution when a type declared in one lib is
23    //       augmented in another lib.
24    const libEntries: [string, string][] = [
25        // JavaScript only
26        ["es5", "lib.es5.d.ts"],
27        ["es6", "lib.es2015.d.ts"],
28        ["es2015", "lib.es2015.d.ts"],
29        ["es7", "lib.es2016.d.ts"],
30        ["es2016", "lib.es2016.d.ts"],
31        ["es2017", "lib.es2017.d.ts"],
32        ["es2018", "lib.es2018.d.ts"],
33        ["es2019", "lib.es2019.d.ts"],
34        ["es2020", "lib.es2020.d.ts"],
35        ["es2021", "lib.es2021.d.ts"],
36        ["es2022", "lib.es2022.d.ts"],
37        ["esnext", "lib.esnext.d.ts"],
38        // Host only
39        ["dom", "lib.dom.d.ts"],
40        ["dom.iterable", "lib.dom.iterable.d.ts"],
41        ["webworker", "lib.webworker.d.ts"],
42        ["webworker.importscripts", "lib.webworker.importscripts.d.ts"],
43        ["webworker.iterable", "lib.webworker.iterable.d.ts"],
44        ["scripthost", "lib.scripthost.d.ts"],
45        // ES2015 Or ESNext By-feature options
46        ["es2015.core", "lib.es2015.core.d.ts"],
47        ["es2015.collection", "lib.es2015.collection.d.ts"],
48        ["es2015.generator", "lib.es2015.generator.d.ts"],
49        ["es2015.iterable", "lib.es2015.iterable.d.ts"],
50        ["es2015.promise", "lib.es2015.promise.d.ts"],
51        ["es2015.proxy", "lib.es2015.proxy.d.ts"],
52        ["es2015.reflect", "lib.es2015.reflect.d.ts"],
53        ["es2015.symbol", "lib.es2015.symbol.d.ts"],
54        ["es2015.symbol.wellknown", "lib.es2015.symbol.wellknown.d.ts"],
55        ["es2016.array.include", "lib.es2016.array.include.d.ts"],
56        ["es2017.object", "lib.es2017.object.d.ts"],
57        ["es2017.sharedmemory", "lib.es2017.sharedmemory.d.ts"],
58        ["es2017.string", "lib.es2017.string.d.ts"],
59        ["es2017.intl", "lib.es2017.intl.d.ts"],
60        ["es2017.typedarrays", "lib.es2017.typedarrays.d.ts"],
61        ["es2018.asyncgenerator", "lib.es2018.asyncgenerator.d.ts"],
62        ["es2018.asynciterable", "lib.es2018.asynciterable.d.ts"],
63        ["es2018.intl", "lib.es2018.intl.d.ts"],
64        ["es2018.promise", "lib.es2018.promise.d.ts"],
65        ["es2018.regexp", "lib.es2018.regexp.d.ts"],
66        ["es2019.array", "lib.es2019.array.d.ts"],
67        ["es2019.object", "lib.es2019.object.d.ts"],
68        ["es2019.string", "lib.es2019.string.d.ts"],
69        ["es2019.symbol", "lib.es2019.symbol.d.ts"],
70        ["es2019.intl", "lib.es2019.intl.d.ts"],
71        ["es2020.bigint", "lib.es2020.bigint.d.ts"],
72        ["es2020.date", "lib.es2020.date.d.ts"],
73        ["es2020.promise", "lib.es2020.promise.d.ts"],
74        ["es2020.sharedmemory", "lib.es2020.sharedmemory.d.ts"],
75        ["es2020.string", "lib.es2020.string.d.ts"],
76        ["es2020.symbol.wellknown", "lib.es2020.symbol.wellknown.d.ts"],
77        ["es2020.intl", "lib.es2020.intl.d.ts"],
78        ["es2020.number", "lib.es2020.number.d.ts"],
79        ["es2021.promise", "lib.es2021.promise.d.ts"],
80        ["es2021.string", "lib.es2021.string.d.ts"],
81        ["es2021.weakref", "lib.es2021.weakref.d.ts"],
82        ["es2021.intl", "lib.es2021.intl.d.ts"],
83        ["es2022.array", "lib.es2022.array.d.ts"],
84        ["es2022.error", "lib.es2022.error.d.ts"],
85        ["es2022.intl", "lib.es2022.intl.d.ts"],
86        ["es2022.object", "lib.es2022.object.d.ts"],
87        ["es2022.sharedmemory", "lib.es2022.sharedmemory.d.ts"],
88        ["es2022.string", "lib.es2022.string.d.ts"],
89        ["esnext.array", "lib.es2022.array.d.ts"],
90        ["esnext.symbol", "lib.es2019.symbol.d.ts"],
91        ["esnext.asynciterable", "lib.es2018.asynciterable.d.ts"],
92        ["esnext.intl", "lib.esnext.intl.d.ts"],
93        ["esnext.bigint", "lib.es2020.bigint.d.ts"],
94        ["esnext.string", "lib.es2022.string.d.ts"],
95        ["esnext.promise", "lib.es2021.promise.d.ts"],
96        ["esnext.weakref", "lib.es2021.weakref.d.ts"]
97    ];
98
99    /**
100     * An array of supported "lib" reference file names used to determine the order for inclusion
101     * when referenced, as well as for spelling suggestions. This ensures the correct ordering for
102     * overload resolution when a type declared in one lib is extended by another.
103     */
104    /* @internal */
105    export const libs = libEntries.map(entry => entry[0]);
106
107    /**
108     * A map of lib names to lib files. This map is used both for parsing the "lib" command line
109     * option as well as for resolving lib reference directives.
110     */
111    /* @internal */
112    export const libMap = new Map(libEntries);
113
114    // Watch related options
115    /* @internal */
116    export const optionsForWatch: CommandLineOption[] = [
117        {
118            name: "watchFile",
119            type: new Map(getEntries({
120                fixedpollinginterval: WatchFileKind.FixedPollingInterval,
121                prioritypollinginterval: WatchFileKind.PriorityPollingInterval,
122                dynamicprioritypolling: WatchFileKind.DynamicPriorityPolling,
123                fixedchunksizepolling: WatchFileKind.FixedChunkSizePolling,
124                usefsevents: WatchFileKind.UseFsEvents,
125                usefseventsonparentdirectory: WatchFileKind.UseFsEventsOnParentDirectory,
126            })),
127            category: Diagnostics.Watch_and_Build_Modes,
128            description: Diagnostics.Specify_how_the_TypeScript_watch_mode_works,
129            defaultValueDescription: WatchFileKind.UseFsEvents,
130        },
131        {
132            name: "watchDirectory",
133            type: new Map(getEntries({
134                usefsevents: WatchDirectoryKind.UseFsEvents,
135                fixedpollinginterval: WatchDirectoryKind.FixedPollingInterval,
136                dynamicprioritypolling: WatchDirectoryKind.DynamicPriorityPolling,
137                fixedchunksizepolling: WatchDirectoryKind.FixedChunkSizePolling,
138            })),
139            category: Diagnostics.Watch_and_Build_Modes,
140            description: Diagnostics.Specify_how_directories_are_watched_on_systems_that_lack_recursive_file_watching_functionality,
141            defaultValueDescription: WatchDirectoryKind.UseFsEvents,
142        },
143        {
144            name: "fallbackPolling",
145            type: new Map(getEntries({
146                fixedinterval: PollingWatchKind.FixedInterval,
147                priorityinterval: PollingWatchKind.PriorityInterval,
148                dynamicpriority: PollingWatchKind.DynamicPriority,
149                fixedchunksize: PollingWatchKind.FixedChunkSize,
150            })),
151            category: Diagnostics.Watch_and_Build_Modes,
152            description: Diagnostics.Specify_what_approach_the_watcher_should_use_if_the_system_runs_out_of_native_file_watchers,
153            defaultValueDescription: PollingWatchKind.PriorityInterval,
154        },
155        {
156            name: "synchronousWatchDirectory",
157            type: "boolean",
158            category: Diagnostics.Watch_and_Build_Modes,
159            description: Diagnostics.Synchronously_call_callbacks_and_update_the_state_of_directory_watchers_on_platforms_that_don_t_support_recursive_watching_natively,
160            defaultValueDescription: false,
161        },
162        {
163            name: "excludeDirectories",
164            type: "list",
165            element: {
166                name: "excludeDirectory",
167                type: "string",
168                isFilePath: true,
169                extraValidation: specToDiagnostic
170            },
171            category: Diagnostics.Watch_and_Build_Modes,
172            description: Diagnostics.Remove_a_list_of_directories_from_the_watch_process,
173        },
174        {
175            name: "excludeFiles",
176            type: "list",
177            element: {
178                name: "excludeFile",
179                type: "string",
180                isFilePath: true,
181                extraValidation: specToDiagnostic
182            },
183            category: Diagnostics.Watch_and_Build_Modes,
184            description: Diagnostics.Remove_a_list_of_files_from_the_watch_mode_s_processing,
185        },
186    ];
187
188    /* @internal */
189    export const commonOptionsWithBuild: CommandLineOption[] = [
190        {
191            name: "help",
192            shortName: "h",
193            type: "boolean",
194            showInSimplifiedHelpView: true,
195            isCommandLineOnly: true,
196            category: Diagnostics.Command_line_Options,
197            description: Diagnostics.Print_this_message,
198            defaultValueDescription: false,
199        },
200        {
201            name: "help",
202            shortName: "?",
203            type: "boolean",
204            isCommandLineOnly: true,
205            category: Diagnostics.Command_line_Options,
206            defaultValueDescription: false,
207        },
208        {
209            name: "watch",
210            shortName: "w",
211            type: "boolean",
212            showInSimplifiedHelpView: true,
213            isCommandLineOnly: true,
214            category: Diagnostics.Command_line_Options,
215            description: Diagnostics.Watch_input_files,
216            defaultValueDescription: false,
217        },
218        {
219            name: "preserveWatchOutput",
220            type: "boolean",
221            showInSimplifiedHelpView: false,
222            category: Diagnostics.Output_Formatting,
223            description: Diagnostics.Disable_wiping_the_console_in_watch_mode,
224            defaultValueDescription: false,
225        },
226        {
227            name: "listFiles",
228            type: "boolean",
229            category: Diagnostics.Compiler_Diagnostics,
230            description: Diagnostics.Print_all_of_the_files_read_during_the_compilation,
231            defaultValueDescription: false,
232        },
233        {
234            name: "explainFiles",
235            type: "boolean",
236            category: Diagnostics.Compiler_Diagnostics,
237            description: Diagnostics.Print_files_read_during_the_compilation_including_why_it_was_included,
238            defaultValueDescription: false,
239        },
240        {
241            name: "listEmittedFiles",
242            type: "boolean",
243            category: Diagnostics.Compiler_Diagnostics,
244            description: Diagnostics.Print_the_names_of_emitted_files_after_a_compilation,
245            defaultValueDescription: false,
246        },
247        {
248            name: "pretty",
249            type: "boolean",
250            showInSimplifiedHelpView: true,
251            category: Diagnostics.Output_Formatting,
252            description: Diagnostics.Enable_color_and_formatting_in_TypeScript_s_output_to_make_compiler_errors_easier_to_read,
253            defaultValueDescription: true,
254        },
255        {
256            name: "traceResolution",
257            type: "boolean",
258            category: Diagnostics.Compiler_Diagnostics,
259            description: Diagnostics.Log_paths_used_during_the_moduleResolution_process,
260            defaultValueDescription: false,
261        },
262        {
263            name: "diagnostics",
264            type: "boolean",
265            category: Diagnostics.Compiler_Diagnostics,
266            description: Diagnostics.Output_compiler_performance_information_after_building,
267            defaultValueDescription: false,
268        },
269        {
270            name: "extendedDiagnostics",
271            type: "boolean",
272            category: Diagnostics.Compiler_Diagnostics,
273            description: Diagnostics.Output_more_detailed_compiler_performance_information_after_building,
274            defaultValueDescription: false,
275        },
276        {
277            name: "generateCpuProfile",
278            type: "string",
279            isFilePath: true,
280            paramType: Diagnostics.FILE_OR_DIRECTORY,
281            category: Diagnostics.Compiler_Diagnostics,
282            description: Diagnostics.Emit_a_v8_CPU_profile_of_the_compiler_run_for_debugging,
283            defaultValueDescription: "profile.cpuprofile"
284        },
285        {
286            name: "generateTrace",
287            type: "string",
288            isFilePath: true,
289            isCommandLineOnly: true,
290            paramType: Diagnostics.DIRECTORY,
291            category: Diagnostics.Compiler_Diagnostics,
292            description: Diagnostics.Generates_an_event_trace_and_a_list_of_types
293        },
294        {
295            name: "incremental",
296            shortName: "i",
297            type: "boolean",
298            category: Diagnostics.Projects,
299            description: Diagnostics.Save_tsbuildinfo_files_to_allow_for_incremental_compilation_of_projects,
300            transpileOptionValue: undefined,
301            defaultValueDescription: Diagnostics.false_unless_composite_is_set
302        },
303        {
304            name: "assumeChangesOnlyAffectDirectDependencies",
305            type: "boolean",
306            affectsSemanticDiagnostics: true,
307            affectsEmit: true,
308            affectsMultiFileEmitBuildInfo: true,
309            category: Diagnostics.Watch_and_Build_Modes,
310            description: Diagnostics.Have_recompiles_in_projects_that_use_incremental_and_watch_mode_assume_that_changes_within_a_file_will_only_affect_files_directly_depending_on_it,
311            defaultValueDescription: false,
312        },
313        {
314            name: "locale",
315            type: "string",
316            category: Diagnostics.Command_line_Options,
317            isCommandLineOnly: true,
318            description: Diagnostics.Set_the_language_of_the_messaging_from_TypeScript_This_does_not_affect_emit,
319            defaultValueDescription: Diagnostics.Platform_specific
320        },
321    ];
322
323    /* @internal */
324    export const targetOptionDeclaration: CommandLineOptionOfCustomType = {
325        name: "target",
326        shortName: "t",
327        type: new Map(getEntries({
328            es3: ScriptTarget.ES3,
329            es5: ScriptTarget.ES5,
330            es6: ScriptTarget.ES2015,
331            es2015: ScriptTarget.ES2015,
332            es2016: ScriptTarget.ES2016,
333            es2017: ScriptTarget.ES2017,
334            es2018: ScriptTarget.ES2018,
335            es2019: ScriptTarget.ES2019,
336            es2020: ScriptTarget.ES2020,
337            es2021: ScriptTarget.ES2021,
338            es2022: ScriptTarget.ES2022,
339            esnext: ScriptTarget.ESNext,
340        })),
341        affectsSourceFile: true,
342        affectsModuleResolution: true,
343        affectsEmit: true,
344        affectsMultiFileEmitBuildInfo: true,
345        paramType: Diagnostics.VERSION,
346        showInSimplifiedHelpView: true,
347        category: Diagnostics.Language_and_Environment,
348        description: Diagnostics.Set_the_JavaScript_language_version_for_emitted_JavaScript_and_include_compatible_library_declarations,
349        defaultValueDescription: ScriptTarget.ES3,
350    };
351
352    /*@internal*/
353    export const moduleOptionDeclaration: CommandLineOptionOfCustomType = {
354        name: "module",
355        shortName: "m",
356        type: new Map(getEntries({
357            none: ModuleKind.None,
358            commonjs: ModuleKind.CommonJS,
359            amd: ModuleKind.AMD,
360            system: ModuleKind.System,
361            umd: ModuleKind.UMD,
362            es6: ModuleKind.ES2015,
363            es2015: ModuleKind.ES2015,
364            es2020: ModuleKind.ES2020,
365            es2022: ModuleKind.ES2022,
366            esnext: ModuleKind.ESNext,
367            node16: ModuleKind.Node16,
368            nodenext: ModuleKind.NodeNext,
369        })),
370        affectsModuleResolution: true,
371        affectsEmit: true,
372        affectsMultiFileEmitBuildInfo: true,
373        paramType: Diagnostics.KIND,
374        showInSimplifiedHelpView: true,
375        category: Diagnostics.Modules,
376        description: Diagnostics.Specify_what_module_code_is_generated,
377        defaultValueDescription: undefined,
378    };
379
380    const commandOptionsWithoutBuild: CommandLineOption[] = [
381        // CommandLine only options
382        {
383            name: "all",
384            type: "boolean",
385            showInSimplifiedHelpView: true,
386            category: Diagnostics.Command_line_Options,
387            description: Diagnostics.Show_all_compiler_options,
388            defaultValueDescription: false,
389        },
390        {
391            name: "version",
392            shortName: "v",
393            type: "boolean",
394            showInSimplifiedHelpView: true,
395            category: Diagnostics.Command_line_Options,
396            description: Diagnostics.Print_the_compiler_s_version,
397            defaultValueDescription: false,
398        },
399        {
400            name: "init",
401            type: "boolean",
402            showInSimplifiedHelpView: true,
403            category: Diagnostics.Command_line_Options,
404            description: Diagnostics.Initializes_a_TypeScript_project_and_creates_a_tsconfig_json_file,
405            defaultValueDescription: false,
406        },
407        {
408            name: "project",
409            shortName: "p",
410            type: "string",
411            isFilePath: true,
412            showInSimplifiedHelpView: true,
413            category: Diagnostics.Command_line_Options,
414            paramType: Diagnostics.FILE_OR_DIRECTORY,
415            description: Diagnostics.Compile_the_project_given_the_path_to_its_configuration_file_or_to_a_folder_with_a_tsconfig_json,
416        },
417        {
418            name: "build",
419            type: "boolean",
420            shortName: "b",
421            showInSimplifiedHelpView: true,
422            category: Diagnostics.Command_line_Options,
423            description: Diagnostics.Build_one_or_more_projects_and_their_dependencies_if_out_of_date,
424            defaultValueDescription: false,
425        },
426        {
427            name: "showConfig",
428            type: "boolean",
429            showInSimplifiedHelpView: true,
430            category: Diagnostics.Command_line_Options,
431            isCommandLineOnly: true,
432            description: Diagnostics.Print_the_final_configuration_instead_of_building,
433            defaultValueDescription: false,
434        },
435        {
436            name: "listFilesOnly",
437            type: "boolean",
438            category: Diagnostics.Command_line_Options,
439            affectsSemanticDiagnostics: true,
440            affectsEmit: true,
441            affectsMultiFileEmitBuildInfo: true,
442            isCommandLineOnly: true,
443            description: Diagnostics.Print_names_of_files_that_are_part_of_the_compilation_and_then_stop_processing,
444            defaultValueDescription: false,
445        },
446
447        // Basic
448        targetOptionDeclaration,
449        moduleOptionDeclaration,
450        {
451            name: "lib",
452            type: "list",
453            element: {
454                name: "lib",
455                type: libMap,
456                defaultValueDescription: undefined,
457            },
458            affectsProgramStructure: true,
459            showInSimplifiedHelpView: true,
460            category: Diagnostics.Language_and_Environment,
461            description: Diagnostics.Specify_a_set_of_bundled_library_declaration_files_that_describe_the_target_runtime_environment,
462            transpileOptionValue: undefined
463        },
464        {
465            name: "allowJs",
466            type: "boolean",
467            affectsModuleResolution: true,
468            showInSimplifiedHelpView: true,
469            category: Diagnostics.JavaScript_Support,
470            description: Diagnostics.Allow_JavaScript_files_to_be_a_part_of_your_program_Use_the_checkJS_option_to_get_errors_from_these_files,
471            defaultValueDescription: false,
472        },
473        {
474            name: "checkJs",
475            type: "boolean",
476            showInSimplifiedHelpView: true,
477            category: Diagnostics.JavaScript_Support,
478            description: Diagnostics.Enable_error_reporting_in_type_checked_JavaScript_files,
479            defaultValueDescription: false,
480        },
481        {
482            name: "jsx",
483            type: jsxOptionMap,
484            affectsSourceFile: true,
485            affectsEmit: true,
486            affectsMultiFileEmitBuildInfo: true,
487            affectsModuleResolution: true,
488            paramType: Diagnostics.KIND,
489            showInSimplifiedHelpView: true,
490            category: Diagnostics.Language_and_Environment,
491            description: Diagnostics.Specify_what_JSX_code_is_generated,
492            defaultValueDescription: undefined,
493        },
494        {
495            name: "declaration",
496            shortName: "d",
497            type: "boolean",
498            affectsEmit: true,
499            affectsMultiFileEmitBuildInfo: true,
500            showInSimplifiedHelpView: true,
501            category: Diagnostics.Emit,
502            transpileOptionValue: undefined,
503            description: Diagnostics.Generate_d_ts_files_from_TypeScript_and_JavaScript_files_in_your_project,
504            defaultValueDescription: Diagnostics.false_unless_composite_is_set,
505        },
506        {
507            name: "declarationMap",
508            type: "boolean",
509            affectsEmit: true,
510            affectsMultiFileEmitBuildInfo: true,
511            showInSimplifiedHelpView: true,
512            category: Diagnostics.Emit,
513            transpileOptionValue: undefined,
514            defaultValueDescription: false,
515            description: Diagnostics.Create_sourcemaps_for_d_ts_files
516        },
517        {
518            name: "emitDeclarationOnly",
519            type: "boolean",
520            affectsEmit: true,
521            affectsMultiFileEmitBuildInfo: true,
522            showInSimplifiedHelpView: true,
523
524            category: Diagnostics.Emit,
525            description: Diagnostics.Only_output_d_ts_files_and_not_JavaScript_files,
526            transpileOptionValue: undefined,
527            defaultValueDescription: false,
528        },
529        {
530            name: "sourceMap",
531            type: "boolean",
532            affectsEmit: true,
533            affectsMultiFileEmitBuildInfo: true,
534            showInSimplifiedHelpView: true,
535            category: Diagnostics.Emit,
536            defaultValueDescription: false,
537            description: Diagnostics.Create_source_map_files_for_emitted_JavaScript_files,
538        },
539        {
540            name: "outFile",
541            type: "string",
542            affectsEmit: true,
543            affectsMultiFileEmitBuildInfo: true,
544            affectsDeclarationPath: true,
545            affectsBundleEmitBuildInfo: true,
546            isFilePath: true,
547            paramType: Diagnostics.FILE,
548            showInSimplifiedHelpView: true,
549            category: Diagnostics.Emit,
550            description: Diagnostics.Specify_a_file_that_bundles_all_outputs_into_one_JavaScript_file_If_declaration_is_true_also_designates_a_file_that_bundles_all_d_ts_output,
551            transpileOptionValue: undefined,
552        },
553        {
554            name: "outDir",
555            type: "string",
556            affectsEmit: true,
557            affectsMultiFileEmitBuildInfo: true,
558            affectsDeclarationPath: true,
559            isFilePath: true,
560            paramType: Diagnostics.DIRECTORY,
561            showInSimplifiedHelpView: true,
562            category: Diagnostics.Emit,
563            description: Diagnostics.Specify_an_output_folder_for_all_emitted_files,
564        },
565        {
566            name: "rootDir",
567            type: "string",
568            affectsEmit: true,
569            affectsMultiFileEmitBuildInfo: true,
570            affectsDeclarationPath: true,
571            isFilePath: true,
572            paramType: Diagnostics.LOCATION,
573            category: Diagnostics.Modules,
574            description: Diagnostics.Specify_the_root_folder_within_your_source_files,
575            defaultValueDescription: Diagnostics.Computed_from_the_list_of_input_files
576        },
577        {
578            name: "composite",
579            type: "boolean",
580            affectsEmit: true,
581            affectsMultiFileEmitBuildInfo: true,
582            affectsBundleEmitBuildInfo: true,
583            isTSConfigOnly: true,
584            category: Diagnostics.Projects,
585            transpileOptionValue: undefined,
586            defaultValueDescription: false,
587            description: Diagnostics.Enable_constraints_that_allow_a_TypeScript_project_to_be_used_with_project_references,
588        },
589        {
590            name: "tsBuildInfoFile",
591            type: "string",
592            affectsEmit: true,
593            affectsMultiFileEmitBuildInfo: true,
594            affectsBundleEmitBuildInfo: true,
595            isFilePath: true,
596            paramType: Diagnostics.FILE,
597            category: Diagnostics.Projects,
598            transpileOptionValue: undefined,
599            defaultValueDescription: ".tsbuildinfo",
600            description: Diagnostics.Specify_the_path_to_tsbuildinfo_incremental_compilation_file,
601        },
602        {
603            name: "removeComments",
604            type: "boolean",
605            affectsEmit: true,
606            affectsMultiFileEmitBuildInfo: true,
607            showInSimplifiedHelpView: true,
608            category: Diagnostics.Emit,
609            defaultValueDescription: false,
610            description: Diagnostics.Disable_emitting_comments,
611        },
612        {
613            name: "noEmit",
614            type: "boolean",
615            showInSimplifiedHelpView: true,
616            category: Diagnostics.Emit,
617            description: Diagnostics.Disable_emitting_files_from_a_compilation,
618            transpileOptionValue: undefined,
619            defaultValueDescription: false,
620        },
621        {
622            name: "importHelpers",
623            type: "boolean",
624            affectsEmit: true,
625            affectsMultiFileEmitBuildInfo: true,
626            category: Diagnostics.Emit,
627            description: Diagnostics.Allow_importing_helper_functions_from_tslib_once_per_project_instead_of_including_them_per_file,
628            defaultValueDescription: false,
629        },
630        {
631            name: "importsNotUsedAsValues",
632            type: new Map(getEntries({
633                remove: ImportsNotUsedAsValues.Remove,
634                preserve: ImportsNotUsedAsValues.Preserve,
635                error: ImportsNotUsedAsValues.Error,
636            })),
637            affectsEmit: true,
638            affectsSemanticDiagnostics: true,
639            affectsMultiFileEmitBuildInfo: true,
640            category: Diagnostics.Emit,
641            description: Diagnostics.Specify_emit_Slashchecking_behavior_for_imports_that_are_only_used_for_types,
642            defaultValueDescription: ImportsNotUsedAsValues.Remove,
643        },
644        {
645            name: "downlevelIteration",
646            type: "boolean",
647            affectsEmit: true,
648            affectsMultiFileEmitBuildInfo: true,
649            category: Diagnostics.Emit,
650            description: Diagnostics.Emit_more_compliant_but_verbose_and_less_performant_JavaScript_for_iteration,
651            defaultValueDescription: false,
652        },
653        {
654            name: "isolatedModules",
655            type: "boolean",
656            category: Diagnostics.Interop_Constraints,
657            description: Diagnostics.Ensure_that_each_file_can_be_safely_transpiled_without_relying_on_other_imports,
658            transpileOptionValue: true,
659            defaultValueDescription: false,
660        },
661
662        // Strict Type Checks
663        {
664            name: "strict",
665            type: "boolean",
666            // Though this affects semantic diagnostics, affectsSemanticDiagnostics is not set here
667            // The value of each strictFlag depends on own strictFlag value or this and never accessed directly.
668            // But we need to store `strict` in builf info, even though it won't be examined directly, so that the
669            // flags it controls (e.g. `strictNullChecks`) will be retrieved correctly
670            affectsMultiFileEmitBuildInfo: true,
671            showInSimplifiedHelpView: true,
672            category: Diagnostics.Type_Checking,
673            description: Diagnostics.Enable_all_strict_type_checking_options,
674            defaultValueDescription: false,
675        },
676        {
677            name: "noImplicitAny",
678            type: "boolean",
679            affectsSemanticDiagnostics: true,
680            affectsMultiFileEmitBuildInfo: true,
681            strictFlag: true,
682            category: Diagnostics.Type_Checking,
683            description: Diagnostics.Enable_error_reporting_for_expressions_and_declarations_with_an_implied_any_type,
684            defaultValueDescription: Diagnostics.false_unless_strict_is_set
685        },
686        {
687            name: "strictNullChecks",
688            type: "boolean",
689            affectsSemanticDiagnostics: true,
690            affectsMultiFileEmitBuildInfo: true,
691            strictFlag: true,
692            category: Diagnostics.Type_Checking,
693            description: Diagnostics.When_type_checking_take_into_account_null_and_undefined,
694            defaultValueDescription: Diagnostics.false_unless_strict_is_set
695        },
696        {
697            name: "strictFunctionTypes",
698            type: "boolean",
699            affectsSemanticDiagnostics: true,
700            affectsMultiFileEmitBuildInfo: true,
701            strictFlag: true,
702            category: Diagnostics.Type_Checking,
703            description: Diagnostics.When_assigning_functions_check_to_ensure_parameters_and_the_return_values_are_subtype_compatible,
704            defaultValueDescription: Diagnostics.false_unless_strict_is_set
705        },
706        {
707            name: "strictBindCallApply",
708            type: "boolean",
709            affectsSemanticDiagnostics: true,
710            affectsMultiFileEmitBuildInfo: true,
711            strictFlag: true,
712            category: Diagnostics.Type_Checking,
713            description: Diagnostics.Check_that_the_arguments_for_bind_call_and_apply_methods_match_the_original_function,
714            defaultValueDescription: Diagnostics.false_unless_strict_is_set
715        },
716        {
717            name: "strictPropertyInitialization",
718            type: "boolean",
719            affectsSemanticDiagnostics: true,
720            affectsMultiFileEmitBuildInfo: true,
721            strictFlag: true,
722            category: Diagnostics.Type_Checking,
723            description: Diagnostics.Check_for_class_properties_that_are_declared_but_not_set_in_the_constructor,
724            defaultValueDescription: Diagnostics.false_unless_strict_is_set
725        },
726        {
727            name: "noImplicitThis",
728            type: "boolean",
729            affectsSemanticDiagnostics: true,
730            affectsMultiFileEmitBuildInfo: true,
731            strictFlag: true,
732            category: Diagnostics.Type_Checking,
733            description: Diagnostics.Enable_error_reporting_when_this_is_given_the_type_any,
734            defaultValueDescription: Diagnostics.false_unless_strict_is_set
735        },
736        {
737            name: "useUnknownInCatchVariables",
738            type: "boolean",
739            affectsSemanticDiagnostics: true,
740            affectsMultiFileEmitBuildInfo: true,
741            strictFlag: true,
742            category: Diagnostics.Type_Checking,
743            description: Diagnostics.Default_catch_clause_variables_as_unknown_instead_of_any,
744            defaultValueDescription: false,
745        },
746        {
747            name: "alwaysStrict",
748            type: "boolean",
749            affectsSourceFile: true,
750            affectsEmit: true,
751            affectsMultiFileEmitBuildInfo: true,
752            strictFlag: true,
753            category: Diagnostics.Type_Checking,
754            description: Diagnostics.Ensure_use_strict_is_always_emitted,
755            defaultValueDescription: Diagnostics.false_unless_strict_is_set
756        },
757
758        // Additional Checks
759        {
760            name: "noUnusedLocals",
761            type: "boolean",
762            affectsSemanticDiagnostics: true,
763            affectsMultiFileEmitBuildInfo: true,
764            category: Diagnostics.Type_Checking,
765            description: Diagnostics.Enable_error_reporting_when_local_variables_aren_t_read,
766            defaultValueDescription: false,
767        },
768        {
769            name: "noUnusedParameters",
770            type: "boolean",
771            affectsSemanticDiagnostics: true,
772            affectsMultiFileEmitBuildInfo: true,
773            category: Diagnostics.Type_Checking,
774            description: Diagnostics.Raise_an_error_when_a_function_parameter_isn_t_read,
775            defaultValueDescription: false,
776        },
777        {
778            name: "exactOptionalPropertyTypes",
779            type: "boolean",
780            affectsSemanticDiagnostics: true,
781            affectsMultiFileEmitBuildInfo: true,
782            category: Diagnostics.Type_Checking,
783            description: Diagnostics.Interpret_optional_property_types_as_written_rather_than_adding_undefined,
784            defaultValueDescription: false,
785        },
786        {
787            name: "noImplicitReturns",
788            type: "boolean",
789            affectsSemanticDiagnostics: true,
790            affectsMultiFileEmitBuildInfo: true,
791            category: Diagnostics.Type_Checking,
792            description: Diagnostics.Enable_error_reporting_for_codepaths_that_do_not_explicitly_return_in_a_function,
793            defaultValueDescription: false,
794        },
795        {
796            name: "noFallthroughCasesInSwitch",
797            type: "boolean",
798            affectsBindDiagnostics: true,
799            affectsSemanticDiagnostics: true,
800            affectsMultiFileEmitBuildInfo: true,
801            category: Diagnostics.Type_Checking,
802            description: Diagnostics.Enable_error_reporting_for_fallthrough_cases_in_switch_statements,
803            defaultValueDescription: false,
804        },
805        {
806            name: "noUncheckedIndexedAccess",
807            type: "boolean",
808            affectsSemanticDiagnostics: true,
809            affectsMultiFileEmitBuildInfo: true,
810            category: Diagnostics.Type_Checking,
811            description: Diagnostics.Add_undefined_to_a_type_when_accessed_using_an_index,
812            defaultValueDescription: false,
813        },
814        {
815            name: "noImplicitOverride",
816            type: "boolean",
817            affectsSemanticDiagnostics: true,
818            affectsMultiFileEmitBuildInfo: true,
819            category: Diagnostics.Type_Checking,
820            description: Diagnostics.Ensure_overriding_members_in_derived_classes_are_marked_with_an_override_modifier,
821            defaultValueDescription: false,
822        },
823        {
824            name: "noPropertyAccessFromIndexSignature",
825            type: "boolean",
826            affectsSemanticDiagnostics: true,
827            affectsMultiFileEmitBuildInfo: true,
828            showInSimplifiedHelpView: false,
829            category: Diagnostics.Type_Checking,
830            description: Diagnostics.Enforces_using_indexed_accessors_for_keys_declared_using_an_indexed_type,
831            defaultValueDescription: false,
832        },
833
834        // Module Resolution
835        {
836            name: "moduleResolution",
837            type: new Map(getEntries({
838                node: ModuleResolutionKind.NodeJs,
839                classic: ModuleResolutionKind.Classic,
840                node16: ModuleResolutionKind.Node16,
841                nodenext: ModuleResolutionKind.NodeNext,
842            })),
843            affectsModuleResolution: true,
844            paramType: Diagnostics.STRATEGY,
845            category: Diagnostics.Modules,
846            description: Diagnostics.Specify_how_TypeScript_looks_up_a_file_from_a_given_module_specifier,
847            defaultValueDescription: Diagnostics.module_AMD_or_UMD_or_System_or_ES6_then_Classic_Otherwise_Node
848        },
849        {
850            name: "baseUrl",
851            type: "string",
852            affectsModuleResolution: true,
853            isFilePath: true,
854            category: Diagnostics.Modules,
855            description: Diagnostics.Specify_the_base_directory_to_resolve_non_relative_module_names
856        },
857        {
858            // this option can only be specified in tsconfig.json
859            // use type = object to copy the value as-is
860            name: "paths",
861            type: "object",
862            affectsModuleResolution: true,
863            isTSConfigOnly: true,
864            category: Diagnostics.Modules,
865            description: Diagnostics.Specify_a_set_of_entries_that_re_map_imports_to_additional_lookup_locations,
866            transpileOptionValue: undefined
867        },
868        {
869            // this option can only be specified in tsconfig.json
870            // use type = object to copy the value as-is
871            name: "rootDirs",
872            type: "list",
873            isTSConfigOnly: true,
874            element: {
875                name: "rootDirs",
876                type: "string",
877                isFilePath: true
878            },
879            affectsModuleResolution: true,
880            category: Diagnostics.Modules,
881            description: Diagnostics.Allow_multiple_folders_to_be_treated_as_one_when_resolving_modules,
882            transpileOptionValue: undefined,
883            defaultValueDescription: Diagnostics.Computed_from_the_list_of_input_files
884        },
885        {
886            name: "typeRoots",
887            type: "list",
888            element: {
889                name: "typeRoots",
890                type: "string",
891                isFilePath: true
892            },
893            affectsModuleResolution: true,
894            category: Diagnostics.Modules,
895            description: Diagnostics.Specify_multiple_folders_that_act_like_Slashnode_modules_Slash_types
896        },
897        {
898            name: "types",
899            type: "list",
900            element: {
901                name: "types",
902                type: "string"
903            },
904            affectsProgramStructure: true,
905            showInSimplifiedHelpView: true,
906            category: Diagnostics.Modules,
907            description: Diagnostics.Specify_type_package_names_to_be_included_without_being_referenced_in_a_source_file,
908            transpileOptionValue: undefined
909        },
910        {
911            name: "allowSyntheticDefaultImports",
912            type: "boolean",
913            affectsSemanticDiagnostics: true,
914            affectsMultiFileEmitBuildInfo: true,
915            category: Diagnostics.Interop_Constraints,
916            description: Diagnostics.Allow_import_x_from_y_when_a_module_doesn_t_have_a_default_export,
917            defaultValueDescription: Diagnostics.module_system_or_esModuleInterop
918        },
919        {
920            name: "esModuleInterop",
921            type: "boolean",
922            affectsSemanticDiagnostics: true,
923            affectsEmit: true,
924            affectsMultiFileEmitBuildInfo: true,
925            showInSimplifiedHelpView: true,
926            category: Diagnostics.Interop_Constraints,
927            description: Diagnostics.Emit_additional_JavaScript_to_ease_support_for_importing_CommonJS_modules_This_enables_allowSyntheticDefaultImports_for_type_compatibility,
928            defaultValueDescription: false,
929        },
930        {
931            name: "preserveSymlinks",
932            type: "boolean",
933            category: Diagnostics.Interop_Constraints,
934            description: Diagnostics.Disable_resolving_symlinks_to_their_realpath_This_correlates_to_the_same_flag_in_node,
935            defaultValueDescription: false,
936        },
937        {
938            name: "allowUmdGlobalAccess",
939            type: "boolean",
940            affectsSemanticDiagnostics: true,
941            affectsMultiFileEmitBuildInfo: true,
942            category: Diagnostics.Modules,
943            description: Diagnostics.Allow_accessing_UMD_globals_from_modules,
944            defaultValueDescription: false,
945        },
946        {
947            name: "moduleSuffixes",
948            type: "list",
949            element: {
950                name: "suffix",
951                type: "string",
952            },
953            listPreserveFalsyValues: true,
954            affectsModuleResolution: true,
955            category: Diagnostics.Modules,
956            description: Diagnostics.List_of_file_name_suffixes_to_search_when_resolving_a_module,
957        },
958
959        // Source Maps
960        {
961            name: "sourceRoot",
962            type: "string",
963            affectsEmit: true,
964            affectsMultiFileEmitBuildInfo: true,
965            paramType: Diagnostics.LOCATION,
966            category: Diagnostics.Emit,
967            description: Diagnostics.Specify_the_root_path_for_debuggers_to_find_the_reference_source_code,
968        },
969        {
970            name: "mapRoot",
971            type: "string",
972            affectsEmit: true,
973            affectsMultiFileEmitBuildInfo: true,
974            paramType: Diagnostics.LOCATION,
975            category: Diagnostics.Emit,
976            description: Diagnostics.Specify_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations,
977        },
978        {
979            name: "inlineSourceMap",
980            type: "boolean",
981            affectsEmit: true,
982            affectsMultiFileEmitBuildInfo: true,
983            category: Diagnostics.Emit,
984            description: Diagnostics.Include_sourcemap_files_inside_the_emitted_JavaScript,
985            defaultValueDescription: false,
986        },
987        {
988            name: "inlineSources",
989            type: "boolean",
990            affectsEmit: true,
991            affectsMultiFileEmitBuildInfo: true,
992            category: Diagnostics.Emit,
993            description: Diagnostics.Include_source_code_in_the_sourcemaps_inside_the_emitted_JavaScript,
994            defaultValueDescription: false,
995        },
996
997        // Experimental
998        {
999            name: "experimentalDecorators",
1000            type: "boolean",
1001            affectsSemanticDiagnostics: true,
1002            affectsMultiFileEmitBuildInfo: true,
1003            category: Diagnostics.Language_and_Environment,
1004            description: Diagnostics.Enable_experimental_support_for_TC39_stage_2_draft_decorators,
1005            defaultValueDescription: false,
1006        },
1007        {
1008            name: "emitDecoratorMetadata",
1009            type: "boolean",
1010            affectsSemanticDiagnostics: true,
1011            affectsEmit: true,
1012            affectsMultiFileEmitBuildInfo: true,
1013            category: Diagnostics.Language_and_Environment,
1014            description: Diagnostics.Emit_design_type_metadata_for_decorated_declarations_in_source_files,
1015            defaultValueDescription: false,
1016        },
1017
1018        // Advanced
1019        {
1020            name: "jsxFactory",
1021            type: "string",
1022            category: Diagnostics.Language_and_Environment,
1023            description: Diagnostics.Specify_the_JSX_factory_function_used_when_targeting_React_JSX_emit_e_g_React_createElement_or_h,
1024            defaultValueDescription: "`React.createElement`"
1025        },
1026        {
1027            name: "jsxFragmentFactory",
1028            type: "string",
1029            category: Diagnostics.Language_and_Environment,
1030            description: Diagnostics.Specify_the_JSX_Fragment_reference_used_for_fragments_when_targeting_React_JSX_emit_e_g_React_Fragment_or_Fragment,
1031            defaultValueDescription: "React.Fragment",
1032        },
1033        {
1034            name: "jsxImportSource",
1035            type: "string",
1036            affectsSemanticDiagnostics: true,
1037            affectsEmit: true,
1038            affectsMultiFileEmitBuildInfo: true,
1039            affectsModuleResolution: true,
1040            category: Diagnostics.Language_and_Environment,
1041            description: Diagnostics.Specify_module_specifier_used_to_import_the_JSX_factory_functions_when_using_jsx_Colon_react_jsx_Asterisk,
1042            defaultValueDescription: "react"
1043        },
1044        {
1045            name: "ets",
1046            type: "object",
1047            affectsSourceFile: true,
1048            affectsEmit: true,
1049            affectsModuleResolution: true,
1050            category: Diagnostics.Language_and_Environment,
1051            description: Diagnostics.Unknown_build_option_0,
1052        },
1053        {
1054            name: "packageManagerType",
1055            type: "string",
1056            affectsSourceFile: true,
1057            affectsEmit: true,
1058            affectsModuleResolution: true,
1059            category: Diagnostics.Language_and_Environment,
1060            description: Diagnostics.Unknown_build_option_0,
1061        },
1062        {
1063            name: "emitNodeModulesFiles",
1064            type: "boolean",
1065            category: Diagnostics.Language_and_Environment,
1066            description: Diagnostics.Unknown_build_option_0,
1067            defaultValueDescription: false,
1068        },
1069        {
1070            name: "resolveJsonModule",
1071            type: "boolean",
1072            affectsModuleResolution: true,
1073            category: Diagnostics.Modules,
1074            description: Diagnostics.Enable_importing_json_files,
1075            defaultValueDescription: false,
1076        },
1077
1078        {
1079            name: "out",
1080            type: "string",
1081            affectsEmit: true,
1082            affectsMultiFileEmitBuildInfo: true,
1083            affectsDeclarationPath: true,
1084            affectsBundleEmitBuildInfo: true,
1085            isFilePath: false, // This is intentionally broken to support compatability with existing tsconfig files
1086            // for correct behaviour, please use outFile
1087            category: Diagnostics.Backwards_Compatibility,
1088            paramType: Diagnostics.FILE,
1089            transpileOptionValue: undefined,
1090            description: Diagnostics.Deprecated_setting_Use_outFile_instead,
1091        },
1092        {
1093            name: "reactNamespace",
1094            type: "string",
1095            affectsEmit: true,
1096            affectsMultiFileEmitBuildInfo: true,
1097            category: Diagnostics.Language_and_Environment,
1098            description: Diagnostics.Specify_the_object_invoked_for_createElement_This_only_applies_when_targeting_react_JSX_emit,
1099            defaultValueDescription: "`React`",
1100        },
1101        {
1102            name: "skipDefaultLibCheck",
1103            type: "boolean",
1104            // We need to store these to determine whether `lib` files need to be rechecked
1105            affectsMultiFileEmitBuildInfo: true,
1106            category: Diagnostics.Completeness,
1107            description: Diagnostics.Skip_type_checking_d_ts_files_that_are_included_with_TypeScript,
1108            defaultValueDescription: false,
1109        },
1110        {
1111            name: "charset",
1112            type: "string",
1113            category: Diagnostics.Backwards_Compatibility,
1114            description: Diagnostics.No_longer_supported_In_early_versions_manually_set_the_text_encoding_for_reading_files,
1115            defaultValueDescription: "utf8"
1116        },
1117        {
1118            name: "emitBOM",
1119            type: "boolean",
1120            affectsEmit: true,
1121            affectsMultiFileEmitBuildInfo: true,
1122            category: Diagnostics.Emit,
1123            description: Diagnostics.Emit_a_UTF_8_Byte_Order_Mark_BOM_in_the_beginning_of_output_files,
1124            defaultValueDescription: false,
1125        },
1126        {
1127            name: "newLine",
1128            type: new Map(getEntries({
1129                crlf: NewLineKind.CarriageReturnLineFeed,
1130                lf: NewLineKind.LineFeed
1131            })),
1132            affectsEmit: true,
1133            affectsMultiFileEmitBuildInfo: true,
1134            paramType: Diagnostics.NEWLINE,
1135            category: Diagnostics.Emit,
1136            description: Diagnostics.Set_the_newline_character_for_emitting_files,
1137            defaultValueDescription: Diagnostics.Platform_specific
1138        },
1139        {
1140            name: "noErrorTruncation",
1141            type: "boolean",
1142            affectsSemanticDiagnostics: true,
1143            affectsMultiFileEmitBuildInfo: true,
1144            category: Diagnostics.Output_Formatting,
1145            description: Diagnostics.Disable_truncating_types_in_error_messages,
1146            defaultValueDescription: false,
1147        },
1148        {
1149            name: "noLib",
1150            type: "boolean",
1151            category: Diagnostics.Language_and_Environment,
1152            affectsProgramStructure: true,
1153            description: Diagnostics.Disable_including_any_library_files_including_the_default_lib_d_ts,
1154            // We are not returning a sourceFile for lib file when asked by the program,
1155            // so pass --noLib to avoid reporting a file not found error.
1156            transpileOptionValue: true,
1157            defaultValueDescription: false,
1158        },
1159        {
1160            name: "noResolve",
1161            type: "boolean",
1162            affectsModuleResolution: true,
1163            category: Diagnostics.Modules,
1164            description: Diagnostics.Disallow_import_s_require_s_or_reference_s_from_expanding_the_number_of_files_TypeScript_should_add_to_a_project,
1165            // We are not doing a full typecheck, we are not resolving the whole context,
1166            // so pass --noResolve to avoid reporting missing file errors.
1167            transpileOptionValue: true,
1168            defaultValueDescription: false,
1169        },
1170        {
1171            name: "stripInternal",
1172            type: "boolean",
1173            affectsEmit: true,
1174            affectsMultiFileEmitBuildInfo: true,
1175            category: Diagnostics.Emit,
1176            description: Diagnostics.Disable_emitting_declarations_that_have_internal_in_their_JSDoc_comments,
1177            defaultValueDescription: false,
1178        },
1179        {
1180            name: "disableSizeLimit",
1181            type: "boolean",
1182            affectsProgramStructure: true,
1183            category: Diagnostics.Editor_Support,
1184            description: Diagnostics.Remove_the_20mb_cap_on_total_source_code_size_for_JavaScript_files_in_the_TypeScript_language_server,
1185            defaultValueDescription: false,
1186        },
1187        {
1188            name: "disableSourceOfProjectReferenceRedirect",
1189            type: "boolean",
1190            isTSConfigOnly: true,
1191            category: Diagnostics.Projects,
1192            description: Diagnostics.Disable_preferring_source_files_instead_of_declaration_files_when_referencing_composite_projects,
1193            defaultValueDescription: false,
1194        },
1195        {
1196            name: "disableSolutionSearching",
1197            type: "boolean",
1198            isTSConfigOnly: true,
1199            category: Diagnostics.Projects,
1200            description: Diagnostics.Opt_a_project_out_of_multi_project_reference_checking_when_editing,
1201            defaultValueDescription: false,
1202        },
1203        {
1204            name: "disableReferencedProjectLoad",
1205            type: "boolean",
1206            isTSConfigOnly: true,
1207            category: Diagnostics.Projects,
1208            description: Diagnostics.Reduce_the_number_of_projects_loaded_automatically_by_TypeScript,
1209            defaultValueDescription: false,
1210        },
1211        {
1212            name: "noImplicitUseStrict",
1213            type: "boolean",
1214            affectsSemanticDiagnostics: true,
1215            affectsMultiFileEmitBuildInfo: true,
1216            category: Diagnostics.Backwards_Compatibility,
1217            description: Diagnostics.Disable_adding_use_strict_directives_in_emitted_JavaScript_files,
1218            defaultValueDescription: false,
1219        },
1220        {
1221            name: "noEmitHelpers",
1222            type: "boolean",
1223            affectsEmit: true,
1224            affectsMultiFileEmitBuildInfo: true,
1225            category: Diagnostics.Emit,
1226            description: Diagnostics.Disable_generating_custom_helper_functions_like_extends_in_compiled_output,
1227            defaultValueDescription: false,
1228        },
1229        {
1230            name: "noEmitOnError",
1231            type: "boolean",
1232            affectsEmit: true,
1233            affectsMultiFileEmitBuildInfo: true,
1234            category: Diagnostics.Emit,
1235            transpileOptionValue: undefined,
1236            description: Diagnostics.Disable_emitting_files_if_any_type_checking_errors_are_reported,
1237            defaultValueDescription: false,
1238        },
1239        {
1240            name: "preserveConstEnums",
1241            type: "boolean",
1242            affectsEmit: true,
1243            affectsMultiFileEmitBuildInfo: true,
1244            category: Diagnostics.Emit,
1245            description: Diagnostics.Disable_erasing_const_enum_declarations_in_generated_code,
1246            defaultValueDescription: false,
1247        },
1248        {
1249            name: "declarationDir",
1250            type: "string",
1251            affectsEmit: true,
1252            affectsMultiFileEmitBuildInfo: true,
1253            affectsDeclarationPath: true,
1254            isFilePath: true,
1255            paramType: Diagnostics.DIRECTORY,
1256            category: Diagnostics.Emit,
1257            transpileOptionValue: undefined,
1258            description: Diagnostics.Specify_the_output_directory_for_generated_declaration_files,
1259        },
1260        {
1261            name: "skipLibCheck",
1262            type: "boolean",
1263            // We need to store these to determine whether `lib` files need to be rechecked
1264            affectsMultiFileEmitBuildInfo: true,
1265            category: Diagnostics.Completeness,
1266            description: Diagnostics.Skip_type_checking_all_d_ts_files,
1267            defaultValueDescription: false,
1268        },
1269        {
1270            name: "allowUnusedLabels",
1271            type: "boolean",
1272            affectsBindDiagnostics: true,
1273            affectsSemanticDiagnostics: true,
1274            affectsMultiFileEmitBuildInfo: true,
1275            category: Diagnostics.Type_Checking,
1276            description: Diagnostics.Disable_error_reporting_for_unused_labels,
1277            defaultValueDescription: undefined,
1278        },
1279        {
1280            name: "allowUnreachableCode",
1281            type: "boolean",
1282            affectsBindDiagnostics: true,
1283            affectsSemanticDiagnostics: true,
1284            affectsMultiFileEmitBuildInfo: true,
1285            category: Diagnostics.Type_Checking,
1286            description: Diagnostics.Disable_error_reporting_for_unreachable_code,
1287            defaultValueDescription: undefined,
1288        },
1289        {
1290            name: "suppressExcessPropertyErrors",
1291            type: "boolean",
1292            affectsSemanticDiagnostics: true,
1293            affectsMultiFileEmitBuildInfo: true,
1294            category: Diagnostics.Backwards_Compatibility,
1295            description: Diagnostics.Disable_reporting_of_excess_property_errors_during_the_creation_of_object_literals,
1296            defaultValueDescription: false,
1297        },
1298        {
1299            name: "suppressImplicitAnyIndexErrors",
1300            type: "boolean",
1301            affectsSemanticDiagnostics: true,
1302            affectsMultiFileEmitBuildInfo: true,
1303            category: Diagnostics.Backwards_Compatibility,
1304            description: Diagnostics.Suppress_noImplicitAny_errors_when_indexing_objects_that_lack_index_signatures,
1305            defaultValueDescription: false,
1306        },
1307        {
1308            name: "forceConsistentCasingInFileNames",
1309            type: "boolean",
1310            affectsModuleResolution: true,
1311            category: Diagnostics.Interop_Constraints,
1312            description: Diagnostics.Ensure_that_casing_is_correct_in_imports,
1313            defaultValueDescription: false,
1314        },
1315        {
1316            name: "maxNodeModuleJsDepth",
1317            type: "number",
1318            affectsModuleResolution: true,
1319            category: Diagnostics.JavaScript_Support,
1320            description: Diagnostics.Specify_the_maximum_folder_depth_used_for_checking_JavaScript_files_from_node_modules_Only_applicable_with_allowJs,
1321            defaultValueDescription: 0,
1322        },
1323        {
1324            name: "noStrictGenericChecks",
1325            type: "boolean",
1326            affectsSemanticDiagnostics: true,
1327            affectsMultiFileEmitBuildInfo: true,
1328            category: Diagnostics.Backwards_Compatibility,
1329            description: Diagnostics.Disable_strict_checking_of_generic_signatures_in_function_types,
1330            defaultValueDescription: false,
1331        },
1332        {
1333            name: "useDefineForClassFields",
1334            type: "boolean",
1335            affectsSemanticDiagnostics: true,
1336            affectsEmit: true,
1337            affectsMultiFileEmitBuildInfo: true,
1338            category: Diagnostics.Language_and_Environment,
1339            description: Diagnostics.Emit_ECMAScript_standard_compliant_class_fields,
1340            defaultValueDescription: Diagnostics.true_for_ES2022_and_above_including_ESNext
1341        },
1342        {
1343            name: "preserveValueImports",
1344            type: "boolean",
1345            affectsEmit: true,
1346            affectsMultiFileEmitBuildInfo: true,
1347            category: Diagnostics.Emit,
1348            description: Diagnostics.Preserve_unused_imported_values_in_the_JavaScript_output_that_would_otherwise_be_removed,
1349            defaultValueDescription: false,
1350        },
1351
1352        {
1353            name: "keyofStringsOnly",
1354            type: "boolean",
1355            category: Diagnostics.Backwards_Compatibility,
1356            description: Diagnostics.Make_keyof_only_return_strings_instead_of_string_numbers_or_symbols_Legacy_option,
1357            defaultValueDescription: false,
1358        },
1359        {
1360            // A list of plugins to load in the language service
1361            name: "plugins",
1362            type: "list",
1363            isTSConfigOnly: true,
1364            element: {
1365                name: "plugin",
1366                type: "object"
1367            },
1368            description: Diagnostics.Specify_a_list_of_language_service_plugins_to_include,
1369            category: Diagnostics.Editor_Support,
1370
1371        },
1372        {
1373            name: "moduleDetection",
1374            type: new Map(getEntries({
1375                auto: ModuleDetectionKind.Auto,
1376                legacy: ModuleDetectionKind.Legacy,
1377                force: ModuleDetectionKind.Force,
1378            })),
1379            affectsModuleResolution: true,
1380            description: Diagnostics.Control_what_method_is_used_to_detect_module_format_JS_files,
1381            category: Diagnostics.Language_and_Environment,
1382            defaultValueDescription: Diagnostics.auto_Colon_Treat_files_with_imports_exports_import_meta_jsx_with_jsx_Colon_react_jsx_or_esm_format_with_module_Colon_node16_as_modules,
1383        },
1384        {
1385            name: "ignoreDeprecations",
1386            type: "string",
1387            defaultValueDescription: undefined,
1388        },
1389        {
1390            name: "etsAnnotationsEnable",
1391            type: "boolean",
1392            affectsSemanticDiagnostics: true,
1393            affectsEmit: true,
1394            affectsMultiFileEmitBuildInfo: true,
1395            category: Diagnostics.Language_and_Environment,
1396            description: Diagnostics.Enable_support_of_ETS_annotations,
1397            defaultValueDescription: false,
1398        },
1399    ];
1400
1401    /* @internal */
1402    export const optionDeclarations: CommandLineOption[] = [
1403        ...commonOptionsWithBuild,
1404        ...commandOptionsWithoutBuild,
1405    ];
1406
1407    /* @internal */
1408    export const semanticDiagnosticsOptionDeclarations: readonly CommandLineOption[] =
1409        optionDeclarations.filter(option => !!option.affectsSemanticDiagnostics);
1410
1411    /* @internal */
1412    export const affectsEmitOptionDeclarations: readonly CommandLineOption[] =
1413        optionDeclarations.filter(option => !!option.affectsEmit);
1414
1415    /* @internal */
1416    export const affectsDeclarationPathOptionDeclarations: readonly CommandLineOption[] =
1417        optionDeclarations.filter(option => !!option.affectsDeclarationPath);
1418
1419    /* @internal */
1420    export const moduleResolutionOptionDeclarations: readonly CommandLineOption[] =
1421        optionDeclarations.filter(option => !!option.affectsModuleResolution);
1422
1423    /* @internal */
1424    export const sourceFileAffectingCompilerOptions: readonly CommandLineOption[] = optionDeclarations.filter(option =>
1425        !!option.affectsSourceFile || !!option.affectsModuleResolution || !!option.affectsBindDiagnostics);
1426
1427    /* @internal */
1428    export const optionsAffectingProgramStructure: readonly CommandLineOption[] =
1429        optionDeclarations.filter(option => !!option.affectsProgramStructure);
1430
1431    /* @internal */
1432    export const transpileOptionValueCompilerOptions: readonly CommandLineOption[] = optionDeclarations.filter(option =>
1433        hasProperty(option, "transpileOptionValue"));
1434
1435    // Build related options
1436    /* @internal */
1437    export const optionsForBuild: CommandLineOption[] = [
1438        {
1439            name: "verbose",
1440            shortName: "v",
1441            category: Diagnostics.Command_line_Options,
1442            description: Diagnostics.Enable_verbose_logging,
1443            type: "boolean",
1444            defaultValueDescription: false,
1445        },
1446        {
1447            name: "dry",
1448            shortName: "d",
1449            category: Diagnostics.Command_line_Options,
1450            description: Diagnostics.Show_what_would_be_built_or_deleted_if_specified_with_clean,
1451            type: "boolean",
1452            defaultValueDescription: false,
1453        },
1454        {
1455            name: "force",
1456            shortName: "f",
1457            category: Diagnostics.Command_line_Options,
1458            description: Diagnostics.Build_all_projects_including_those_that_appear_to_be_up_to_date,
1459            type: "boolean",
1460            defaultValueDescription: false,
1461        },
1462        {
1463            name: "clean",
1464            category: Diagnostics.Command_line_Options,
1465            description: Diagnostics.Delete_the_outputs_of_all_projects,
1466            type: "boolean",
1467            defaultValueDescription: false,
1468        }
1469    ];
1470
1471    /* @internal */
1472    export const buildOpts: CommandLineOption[] = [
1473        ...commonOptionsWithBuild,
1474        ...optionsForBuild
1475    ];
1476
1477    /* @internal */
1478    export const typeAcquisitionDeclarations: CommandLineOption[] = [
1479        {
1480            /* @deprecated typingOptions.enableAutoDiscovery
1481             * Use typeAcquisition.enable instead.
1482             */
1483            name: "enableAutoDiscovery",
1484            type: "boolean",
1485            defaultValueDescription: false,
1486        },
1487        {
1488            name: "enable",
1489            type: "boolean",
1490            defaultValueDescription: false,
1491        },
1492        {
1493            name: "include",
1494            type: "list",
1495            element: {
1496                name: "include",
1497                type: "string"
1498            }
1499        },
1500        {
1501            name: "exclude",
1502            type: "list",
1503            element: {
1504                name: "exclude",
1505                type: "string"
1506            }
1507        },
1508        {
1509            name: "disableFilenameBasedTypeAcquisition",
1510            type: "boolean",
1511            defaultValueDescription: false,
1512        },
1513    ];
1514
1515    /* @internal */
1516    export interface OptionsNameMap {
1517        optionsNameMap: ESMap<string, CommandLineOption>;
1518        shortOptionNames: ESMap<string, string>;
1519    }
1520
1521    /*@internal*/
1522    export function createOptionNameMap(optionDeclarations: readonly CommandLineOption[]): OptionsNameMap {
1523        const optionsNameMap = new Map<string, CommandLineOption>();
1524        const shortOptionNames = new Map<string, string>();
1525        forEach(optionDeclarations, option => {
1526            optionsNameMap.set(option.name.toLowerCase(), option);
1527            if (option.shortName) {
1528                shortOptionNames.set(option.shortName, option.name);
1529            }
1530        });
1531
1532        return { optionsNameMap, shortOptionNames };
1533    }
1534
1535    let optionsNameMapCache: OptionsNameMap;
1536
1537    /* @internal */
1538    export function getOptionsNameMap(): OptionsNameMap {
1539        return optionsNameMapCache ||= createOptionNameMap(optionDeclarations);
1540    }
1541
1542    const compilerOptionsAlternateMode: AlternateModeDiagnostics = {
1543        diagnostic: Diagnostics.Compiler_option_0_may_only_be_used_with_build,
1544        getOptionsNameMap: getBuildOptionsNameMap
1545    };
1546
1547    /* @internal */
1548    export const defaultInitCompilerOptions: CompilerOptions = {
1549        module: ModuleKind.CommonJS,
1550        target: ScriptTarget.ES2016,
1551        strict: true,
1552        esModuleInterop: true,
1553        forceConsistentCasingInFileNames: true,
1554        skipLibCheck: true
1555    };
1556
1557    /* @internal */
1558    export function convertEnableAutoDiscoveryToEnable(typeAcquisition: TypeAcquisition): TypeAcquisition {
1559        // Convert deprecated typingOptions.enableAutoDiscovery to typeAcquisition.enable
1560        if (typeAcquisition && typeAcquisition.enableAutoDiscovery !== undefined && typeAcquisition.enable === undefined) {
1561            return {
1562                enable: typeAcquisition.enableAutoDiscovery,
1563                include: typeAcquisition.include || [],
1564                exclude: typeAcquisition.exclude || []
1565            };
1566        }
1567        return typeAcquisition;
1568    }
1569
1570    /* @internal */
1571    export function createCompilerDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType): Diagnostic {
1572        return createDiagnosticForInvalidCustomType(opt, createCompilerDiagnostic);
1573    }
1574
1575    function createDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType, createDiagnostic: (message: DiagnosticMessage, arg0: string, arg1: string) => Diagnostic): Diagnostic {
1576        const namesOfType = arrayFrom(opt.type.keys()).map(key => `'${key}'`).join(", ");
1577        return createDiagnostic(Diagnostics.Argument_for_0_option_must_be_Colon_1, `--${opt.name}`, namesOfType);
1578    }
1579
1580    /* @internal */
1581    export function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string, errors: Push<Diagnostic>) {
1582        return convertJsonOptionOfCustomType(opt, trimString(value || ""), errors);
1583    }
1584
1585    /* @internal */
1586    export function parseListTypeOption(opt: CommandLineOptionOfListType, value = "", errors: Push<Diagnostic>): (string | number)[] | undefined {
1587        value = trimString(value);
1588        if (startsWith(value, "-")) {
1589            return undefined;
1590        }
1591        if (value === "") {
1592            return [];
1593        }
1594        const values = value.split(",");
1595        switch (opt.element.type) {
1596            case "number":
1597                return mapDefined(values, v => validateJsonOptionValue(opt.element, parseInt(v), errors));
1598            case "string":
1599                return mapDefined(values, v => validateJsonOptionValue(opt.element, v || "", errors));
1600            default:
1601                return mapDefined(values, v => parseCustomTypeOption(opt.element as CommandLineOptionOfCustomType, v, errors));
1602        }
1603    }
1604
1605    /*@internal*/
1606    export interface OptionsBase {
1607        [option: string]: CompilerOptionsValue | TsConfigSourceFile | undefined;
1608    }
1609
1610    /*@internal*/
1611    export interface ParseCommandLineWorkerDiagnostics extends DidYouMeanOptionsDiagnostics {
1612        getOptionsNameMap: () => OptionsNameMap;
1613        optionTypeMismatchDiagnostic: DiagnosticMessage;
1614    }
1615
1616    function getOptionName(option: CommandLineOption) {
1617        return option.name;
1618    }
1619
1620    function createUnknownOptionError(
1621        unknownOption: string,
1622        diagnostics: DidYouMeanOptionsDiagnostics,
1623        createDiagnostics: (message: DiagnosticMessage, arg0: string, arg1?: string) => Diagnostic,
1624        unknownOptionErrorText?: string
1625    ) {
1626        if (diagnostics.alternateMode?.getOptionsNameMap().optionsNameMap.has(unknownOption.toLowerCase())) {
1627            return createDiagnostics(diagnostics.alternateMode.diagnostic, unknownOption);
1628        }
1629
1630        const possibleOption = getSpellingSuggestion(unknownOption, diagnostics.optionDeclarations, getOptionName);
1631        return possibleOption ?
1632            createDiagnostics(diagnostics.unknownDidYouMeanDiagnostic, unknownOptionErrorText || unknownOption, possibleOption.name) :
1633            createDiagnostics(diagnostics.unknownOptionDiagnostic, unknownOptionErrorText || unknownOption);
1634    }
1635
1636    /*@internal*/
1637    export function parseCommandLineWorker(
1638        diagnostics: ParseCommandLineWorkerDiagnostics,
1639        commandLine: readonly string[],
1640        readFile?: (path: string) => string | undefined) {
1641        const options = {} as OptionsBase;
1642        let watchOptions: WatchOptions | undefined;
1643        const fileNames: string[] = [];
1644        const errors: Diagnostic[] = [];
1645
1646        parseStrings(commandLine);
1647        return {
1648            options,
1649            watchOptions,
1650            fileNames,
1651            errors
1652        };
1653
1654        function parseStrings(args: readonly string[]) {
1655            let i = 0;
1656            while (i < args.length) {
1657                const s = args[i];
1658                i++;
1659                if (s.charCodeAt(0) === CharacterCodes.at) {
1660                    parseResponseFile(s.slice(1));
1661                }
1662                else if (s.charCodeAt(0) === CharacterCodes.minus) {
1663                    const inputOptionName = s.slice(s.charCodeAt(1) === CharacterCodes.minus ? 2 : 1);
1664                    const opt = getOptionDeclarationFromName(diagnostics.getOptionsNameMap, inputOptionName, /*allowShort*/ true);
1665                    if (opt) {
1666                        i = parseOptionValue(args, i, diagnostics, opt, options, errors);
1667                    }
1668                    else {
1669                        const watchOpt = getOptionDeclarationFromName(watchOptionsDidYouMeanDiagnostics.getOptionsNameMap, inputOptionName, /*allowShort*/ true);
1670                        if (watchOpt) {
1671                            i = parseOptionValue(args, i, watchOptionsDidYouMeanDiagnostics, watchOpt, watchOptions || (watchOptions = {}), errors);
1672                        }
1673                        else {
1674                            errors.push(createUnknownOptionError(inputOptionName, diagnostics, createCompilerDiagnostic, s));
1675                        }
1676                    }
1677                }
1678                else {
1679                    fileNames.push(s);
1680                }
1681            }
1682        }
1683
1684        function parseResponseFile(fileName: string) {
1685            const text = tryReadFile(fileName, readFile || (fileName => sys.readFile(fileName)));
1686            if (!isString(text)) {
1687                errors.push(text);
1688                return;
1689            }
1690
1691            const args: string[] = [];
1692            let pos = 0;
1693            while (true) {
1694                while (pos < text.length && text.charCodeAt(pos) <= CharacterCodes.space) pos++;
1695                if (pos >= text.length) break;
1696                const start = pos;
1697                if (text.charCodeAt(start) === CharacterCodes.doubleQuote) {
1698                    pos++;
1699                    while (pos < text.length && text.charCodeAt(pos) !== CharacterCodes.doubleQuote) pos++;
1700                    if (pos < text.length) {
1701                        args.push(text.substring(start + 1, pos));
1702                        pos++;
1703                    }
1704                    else {
1705                        errors.push(createCompilerDiagnostic(Diagnostics.Unterminated_quoted_string_in_response_file_0, fileName));
1706                    }
1707                }
1708                else {
1709                    while (text.charCodeAt(pos) > CharacterCodes.space) pos++;
1710                    args.push(text.substring(start, pos));
1711                }
1712            }
1713            parseStrings(args);
1714        }
1715    }
1716
1717    function parseOptionValue(
1718        args: readonly string[],
1719        i: number,
1720        diagnostics: ParseCommandLineWorkerDiagnostics,
1721        opt: CommandLineOption,
1722        options: OptionsBase,
1723        errors: Diagnostic[]
1724    ) {
1725        if (opt.isTSConfigOnly) {
1726            const optValue = args[i];
1727            if (optValue === "null") {
1728                options[opt.name] = undefined;
1729                i++;
1730            }
1731            else if (opt.type === "boolean") {
1732                if (optValue === "false") {
1733                    options[opt.name] = validateJsonOptionValue(opt, /*value*/ false, errors);
1734                    i++;
1735                }
1736                else {
1737                    if (optValue === "true") i++;
1738                    errors.push(createCompilerDiagnostic(Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file_or_set_to_false_or_null_on_command_line, opt.name));
1739                }
1740            }
1741            else {
1742                errors.push(createCompilerDiagnostic(Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file_or_set_to_null_on_command_line, opt.name));
1743                if (optValue && !startsWith(optValue, "-")) i++;
1744            }
1745        }
1746        else {
1747            // Check to see if no argument was provided (e.g. "--locale" is the last command-line argument).
1748            if (!args[i] && opt.type !== "boolean") {
1749                errors.push(createCompilerDiagnostic(diagnostics.optionTypeMismatchDiagnostic, opt.name, getCompilerOptionValueTypeString(opt)));
1750            }
1751
1752            if (args[i] !== "null") {
1753                switch (opt.type) {
1754                    case "number":
1755                        options[opt.name] = validateJsonOptionValue(opt, parseInt(args[i]), errors);
1756                        i++;
1757                        break;
1758                    case "boolean":
1759                        // boolean flag has optional value true, false, others
1760                        const optValue = args[i];
1761                        options[opt.name] = validateJsonOptionValue(opt, optValue !== "false", errors);
1762                        // consume next argument as boolean flag value
1763                        if (optValue === "false" || optValue === "true") {
1764                            i++;
1765                        }
1766                        break;
1767                    case "string":
1768                        options[opt.name] = validateJsonOptionValue(opt, args[i] || "", errors);
1769                        i++;
1770                        break;
1771                    case "list":
1772                        const result = parseListTypeOption(opt, args[i], errors);
1773                        options[opt.name] = result || [];
1774                        if (result) {
1775                            i++;
1776                        }
1777                        break;
1778                    // If not a primitive, the possible types are specified in what is effectively a map of options.
1779                    default:
1780                        options[opt.name] = parseCustomTypeOption(opt as CommandLineOptionOfCustomType, args[i], errors);
1781                        i++;
1782                        break;
1783                }
1784            }
1785            else {
1786                options[opt.name] = undefined;
1787                i++;
1788            }
1789        }
1790        return i;
1791    }
1792
1793    /*@internal*/
1794    export const compilerOptionsDidYouMeanDiagnostics: ParseCommandLineWorkerDiagnostics = {
1795        alternateMode: compilerOptionsAlternateMode,
1796        getOptionsNameMap,
1797        optionDeclarations,
1798        unknownOptionDiagnostic: Diagnostics.Unknown_compiler_option_0,
1799        unknownDidYouMeanDiagnostic: Diagnostics.Unknown_compiler_option_0_Did_you_mean_1,
1800        optionTypeMismatchDiagnostic: Diagnostics.Compiler_option_0_expects_an_argument
1801    };
1802    export function parseCommandLine(commandLine: readonly string[], readFile?: (path: string) => string | undefined): ParsedCommandLine {
1803        return parseCommandLineWorker(compilerOptionsDidYouMeanDiagnostics, commandLine, readFile);
1804    }
1805
1806    /** @internal */
1807    export function getOptionFromName(optionName: string, allowShort?: boolean): CommandLineOption | undefined {
1808        return getOptionDeclarationFromName(getOptionsNameMap, optionName, allowShort);
1809    }
1810
1811    function getOptionDeclarationFromName(getOptionNameMap: () => OptionsNameMap, optionName: string, allowShort = false): CommandLineOption | undefined {
1812        optionName = optionName.toLowerCase();
1813        const { optionsNameMap, shortOptionNames } = getOptionNameMap();
1814        // Try to translate short option names to their full equivalents.
1815        if (allowShort) {
1816            const short = shortOptionNames.get(optionName);
1817            if (short !== undefined) {
1818                optionName = short;
1819            }
1820        }
1821        return optionsNameMap.get(optionName);
1822    }
1823
1824    /*@internal*/
1825    export interface ParsedBuildCommand {
1826        buildOptions: BuildOptions;
1827        watchOptions: WatchOptions | undefined;
1828        projects: string[];
1829        errors: Diagnostic[];
1830    }
1831
1832    let buildOptionsNameMapCache: OptionsNameMap;
1833    function getBuildOptionsNameMap(): OptionsNameMap {
1834        return buildOptionsNameMapCache || (buildOptionsNameMapCache = createOptionNameMap(buildOpts));
1835    }
1836
1837    const buildOptionsAlternateMode: AlternateModeDiagnostics = {
1838        diagnostic: Diagnostics.Compiler_option_0_may_not_be_used_with_build,
1839        getOptionsNameMap
1840    };
1841
1842    const buildOptionsDidYouMeanDiagnostics: ParseCommandLineWorkerDiagnostics = {
1843        alternateMode: buildOptionsAlternateMode,
1844        getOptionsNameMap: getBuildOptionsNameMap,
1845        optionDeclarations: buildOpts,
1846        unknownOptionDiagnostic: Diagnostics.Unknown_build_option_0,
1847        unknownDidYouMeanDiagnostic: Diagnostics.Unknown_build_option_0_Did_you_mean_1,
1848        optionTypeMismatchDiagnostic: Diagnostics.Build_option_0_requires_a_value_of_type_1
1849    };
1850
1851    /*@internal*/
1852    export function parseBuildCommand(args: readonly string[]): ParsedBuildCommand {
1853        const { options, watchOptions, fileNames: projects, errors } = parseCommandLineWorker(
1854            buildOptionsDidYouMeanDiagnostics,
1855            args
1856        );
1857        const buildOptions = options as BuildOptions;
1858
1859        if (projects.length === 0) {
1860            // tsc -b invoked with no extra arguments; act as if invoked with "tsc -b ."
1861            projects.push(".");
1862        }
1863
1864        // Nonsensical combinations
1865        if (buildOptions.clean && buildOptions.force) {
1866            errors.push(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "force"));
1867        }
1868        if (buildOptions.clean && buildOptions.verbose) {
1869            errors.push(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "verbose"));
1870        }
1871        if (buildOptions.clean && buildOptions.watch) {
1872            errors.push(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "watch"));
1873        }
1874        if (buildOptions.watch && buildOptions.dry) {
1875            errors.push(createCompilerDiagnostic(Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "dry"));
1876        }
1877
1878        return { buildOptions, watchOptions, projects, errors };
1879    }
1880
1881    /* @internal */
1882    export function getDiagnosticText(_message: DiagnosticMessage, ..._args: any[]): string {
1883        const diagnostic = createCompilerDiagnostic.apply(undefined, arguments);
1884        return diagnostic.messageText as string;
1885    }
1886
1887    export type DiagnosticReporter = (diagnostic: Diagnostic) => void;
1888    /**
1889     * Reports config file diagnostics
1890     */
1891    export interface ConfigFileDiagnosticsReporter {
1892        /**
1893         * Reports unrecoverable error when parsing config file
1894         */
1895        onUnRecoverableConfigFileDiagnostic: DiagnosticReporter;
1896    }
1897
1898    /**
1899     * Interface extending ParseConfigHost to support ParseConfigFile that reads config file and reports errors
1900     */
1901    export interface ParseConfigFileHost extends ParseConfigHost, ConfigFileDiagnosticsReporter {
1902        getCurrentDirectory(): string;
1903    }
1904
1905    /**
1906     * Reads the config file, reports errors if any and exits if the config file cannot be found
1907     */
1908    export function getParsedCommandLineOfConfigFile(
1909        configFileName: string,
1910        optionsToExtend: CompilerOptions | undefined,
1911        host: ParseConfigFileHost,
1912        extendedConfigCache?: Map<ExtendedConfigCacheEntry>,
1913        watchOptionsToExtend?: WatchOptions,
1914        extraFileExtensions?: readonly FileExtensionInfo[],
1915    ): ParsedCommandLine | undefined {
1916        const configFileText = tryReadFile(configFileName, fileName => host.readFile(fileName));
1917        if (!isString(configFileText)) {
1918            host.onUnRecoverableConfigFileDiagnostic(configFileText);
1919            return undefined;
1920        }
1921
1922        const result = parseJsonText(configFileName, configFileText);
1923        const cwd = host.getCurrentDirectory();
1924        result.path = toPath(configFileName, cwd, createGetCanonicalFileName(host.useCaseSensitiveFileNames));
1925        result.resolvedPath = result.path;
1926        result.originalFileName = result.fileName;
1927        return parseJsonSourceFileConfigFileContent(
1928            result,
1929            host,
1930            getNormalizedAbsolutePath(getDirectoryPath(configFileName), cwd),
1931            optionsToExtend,
1932            getNormalizedAbsolutePath(configFileName, cwd),
1933            /*resolutionStack*/ undefined,
1934            extraFileExtensions,
1935            extendedConfigCache,
1936            watchOptionsToExtend
1937        );
1938    }
1939
1940    /**
1941     * Read tsconfig.json file
1942     * @param fileName The path to the config file
1943     */
1944    export function readConfigFile(fileName: string, readFile: (path: string) => string | undefined): { config?: any; error?: Diagnostic } {
1945        const textOrDiagnostic = tryReadFile(fileName, readFile);
1946        return isString(textOrDiagnostic) ? parseConfigFileTextToJson(fileName, textOrDiagnostic) : { config: {}, error: textOrDiagnostic };
1947    }
1948
1949    /**
1950     * Parse the text of the tsconfig.json file
1951     * @param fileName The path to the config file
1952     * @param jsonText The text of the config file
1953     */
1954    export function parseConfigFileTextToJson(fileName: string, jsonText: string): { config?: any; error?: Diagnostic } {
1955        const jsonSourceFile = parseJsonText(fileName, jsonText);
1956        return {
1957            config: convertConfigFileToObject(jsonSourceFile, jsonSourceFile.parseDiagnostics, /*reportOptionsErrors*/ false, /*optionsIterator*/ undefined),
1958            error: jsonSourceFile.parseDiagnostics.length ? jsonSourceFile.parseDiagnostics[0] : undefined
1959        };
1960    }
1961
1962    /**
1963     * Read tsconfig.json file
1964     * @param fileName The path to the config file
1965     */
1966    export function readJsonConfigFile(fileName: string, readFile: (path: string) => string | undefined): TsConfigSourceFile {
1967        const textOrDiagnostic = tryReadFile(fileName, readFile);
1968        return isString(textOrDiagnostic) ? parseJsonText(fileName, textOrDiagnostic) : { fileName, parseDiagnostics: [textOrDiagnostic] } as TsConfigSourceFile;
1969    }
1970
1971    /*@internal*/
1972    export function tryReadFile(fileName: string, readFile: (path: string) => string | undefined): string | Diagnostic {
1973        let text: string | undefined;
1974        try {
1975            text = readFile(fileName);
1976        }
1977        catch (e) {
1978            return createCompilerDiagnostic(Diagnostics.Cannot_read_file_0_Colon_1, fileName, e.message);
1979        }
1980        return text === undefined ? createCompilerDiagnostic(Diagnostics.Cannot_read_file_0, fileName) : text;
1981    }
1982
1983    function commandLineOptionsToMap(options: readonly CommandLineOption[]) {
1984        return arrayToMap(options, getOptionName);
1985    }
1986
1987    const typeAcquisitionDidYouMeanDiagnostics: DidYouMeanOptionsDiagnostics = {
1988        optionDeclarations: typeAcquisitionDeclarations,
1989        unknownOptionDiagnostic: Diagnostics.Unknown_type_acquisition_option_0,
1990        unknownDidYouMeanDiagnostic: Diagnostics.Unknown_type_acquisition_option_0_Did_you_mean_1,
1991    };
1992
1993    let watchOptionsNameMapCache: OptionsNameMap;
1994    function getWatchOptionsNameMap(): OptionsNameMap {
1995        return watchOptionsNameMapCache || (watchOptionsNameMapCache = createOptionNameMap(optionsForWatch));
1996    }
1997    const watchOptionsDidYouMeanDiagnostics: ParseCommandLineWorkerDiagnostics = {
1998        getOptionsNameMap: getWatchOptionsNameMap,
1999        optionDeclarations: optionsForWatch,
2000        unknownOptionDiagnostic: Diagnostics.Unknown_watch_option_0,
2001        unknownDidYouMeanDiagnostic: Diagnostics.Unknown_watch_option_0_Did_you_mean_1,
2002        optionTypeMismatchDiagnostic: Diagnostics.Watch_option_0_requires_a_value_of_type_1
2003    };
2004
2005    let commandLineCompilerOptionsMapCache: ESMap<string, CommandLineOption>;
2006    function getCommandLineCompilerOptionsMap() {
2007        return commandLineCompilerOptionsMapCache || (commandLineCompilerOptionsMapCache = commandLineOptionsToMap(optionDeclarations));
2008    }
2009    let commandLineWatchOptionsMapCache: ESMap<string, CommandLineOption>;
2010    function getCommandLineWatchOptionsMap() {
2011        return commandLineWatchOptionsMapCache || (commandLineWatchOptionsMapCache = commandLineOptionsToMap(optionsForWatch));
2012    }
2013    let commandLineTypeAcquisitionMapCache: ESMap<string, CommandLineOption>;
2014    function getCommandLineTypeAcquisitionMap() {
2015        return commandLineTypeAcquisitionMapCache || (commandLineTypeAcquisitionMapCache = commandLineOptionsToMap(typeAcquisitionDeclarations));
2016    }
2017
2018    let _tsconfigRootOptions: TsConfigOnlyOption;
2019    function getTsconfigRootOptionsMap() {
2020        if (_tsconfigRootOptions === undefined) {
2021            _tsconfigRootOptions = {
2022                name: undefined!, // should never be needed since this is root
2023                type: "object",
2024                elementOptions: commandLineOptionsToMap([
2025                    {
2026                        name: "compilerOptions",
2027                        type: "object",
2028                        elementOptions: getCommandLineCompilerOptionsMap(),
2029                        extraKeyDiagnostics: compilerOptionsDidYouMeanDiagnostics,
2030                    },
2031                    {
2032                        name: "watchOptions",
2033                        type: "object",
2034                        elementOptions: getCommandLineWatchOptionsMap(),
2035                        extraKeyDiagnostics: watchOptionsDidYouMeanDiagnostics,
2036                    },
2037                    {
2038                        name: "typingOptions",
2039                        type: "object",
2040                        elementOptions: getCommandLineTypeAcquisitionMap(),
2041                        extraKeyDiagnostics: typeAcquisitionDidYouMeanDiagnostics,
2042                    },
2043                    {
2044                        name: "typeAcquisition",
2045                        type: "object",
2046                        elementOptions: getCommandLineTypeAcquisitionMap(),
2047                        extraKeyDiagnostics: typeAcquisitionDidYouMeanDiagnostics
2048                    },
2049                    {
2050                        name: "extends",
2051                        type: "string",
2052                        category: Diagnostics.File_Management,
2053                    },
2054                    {
2055                        name: "references",
2056                        type: "list",
2057                        element: {
2058                            name: "references",
2059                            type: "object"
2060                        },
2061                        category: Diagnostics.Projects,
2062                    },
2063                    {
2064                        name: "files",
2065                        type: "list",
2066                        element: {
2067                            name: "files",
2068                            type: "string"
2069                        },
2070                        category: Diagnostics.File_Management,
2071                    },
2072                    {
2073                        name: "include",
2074                        type: "list",
2075                        element: {
2076                            name: "include",
2077                            type: "string"
2078                        },
2079                        category: Diagnostics.File_Management,
2080                        defaultValueDescription: Diagnostics.if_files_is_specified_otherwise_Asterisk_Asterisk_Slash_Asterisk
2081                    },
2082                    {
2083                        name: "exclude",
2084                        type: "list",
2085                        element: {
2086                            name: "exclude",
2087                            type: "string"
2088                        },
2089                        category: Diagnostics.File_Management,
2090                        defaultValueDescription: Diagnostics.node_modules_bower_components_jspm_packages_plus_the_value_of_outDir_if_one_is_specified
2091                    },
2092                    compileOnSaveCommandLineOption
2093                ])
2094            };
2095        }
2096        return _tsconfigRootOptions;
2097    }
2098
2099    /*@internal*/
2100    interface JsonConversionNotifier {
2101        /**
2102         * Notifies parent option object is being set with the optionKey and a valid optionValue
2103         * Currently it notifies only if there is element with type object (parentOption) and
2104         * has element's option declarations map associated with it
2105         * @param parentOption parent option name in which the option and value are being set
2106         * @param option option declaration which is being set with the value
2107         * @param value value of the option
2108         */
2109        onSetValidOptionKeyValueInParent(parentOption: string, option: CommandLineOption, value: CompilerOptionsValue): void;
2110        /**
2111         * Notify when valid root key value option is being set
2112         * @param key option key
2113         * @param keyNode node corresponding to node in the source file
2114         * @param value computed value of the key
2115         * @param ValueNode node corresponding to value in the source file
2116         */
2117        onSetValidOptionKeyValueInRoot(key: string, keyNode: PropertyName, value: CompilerOptionsValue, valueNode: Expression): void;
2118        /**
2119         * Notify when unknown root key value option is being set
2120         * @param key option key
2121         * @param keyNode node corresponding to node in the source file
2122         * @param value computed value of the key
2123         * @param ValueNode node corresponding to value in the source file
2124         */
2125        onSetUnknownOptionKeyValueInRoot(key: string, keyNode: PropertyName, value: CompilerOptionsValue, valueNode: Expression): void;
2126    }
2127
2128    function convertConfigFileToObject(sourceFile: JsonSourceFile, errors: Push<Diagnostic>, reportOptionsErrors: boolean, optionsIterator: JsonConversionNotifier | undefined): any {
2129        const rootExpression: Expression | undefined = sourceFile.statements[0]?.expression;
2130        const knownRootOptions = reportOptionsErrors ? getTsconfigRootOptionsMap() : undefined;
2131        if (rootExpression && rootExpression.kind !== SyntaxKind.ObjectLiteralExpression) {
2132            errors.push(createDiagnosticForNodeInSourceFile(
2133                sourceFile,
2134                rootExpression,
2135                Diagnostics.The_root_value_of_a_0_file_must_be_an_object,
2136                getBaseFileName(sourceFile.fileName) === "jsconfig.json" ? "jsconfig.json" : "tsconfig.json"
2137            ));
2138            // Last-ditch error recovery. Somewhat useful because the JSON parser will recover from some parse errors by
2139            // synthesizing a top-level array literal expression. There's a reasonable chance the first element of that
2140            // array is a well-formed configuration object, made into an array element by stray characters.
2141            if (isArrayLiteralExpression(rootExpression)) {
2142                const firstObject = find(rootExpression.elements, isObjectLiteralExpression);
2143                if (firstObject) {
2144                    return convertToObjectWorker(sourceFile, firstObject, errors, /*returnValue*/ true, knownRootOptions, optionsIterator);
2145                }
2146            }
2147            return {};
2148        }
2149        return convertToObjectWorker(sourceFile, rootExpression, errors, /*returnValue*/ true, knownRootOptions, optionsIterator);
2150    }
2151
2152    /**
2153     * Convert the json syntax tree into the json value
2154     */
2155    export function convertToObject(sourceFile: JsonSourceFile, errors: Push<Diagnostic>): any {
2156        return convertToObjectWorker(sourceFile, sourceFile.statements[0]?.expression, errors, /*returnValue*/ true, /*knownRootOptions*/ undefined, /*jsonConversionNotifier*/ undefined);
2157    }
2158
2159    /**
2160     * Convert the json syntax tree into the json value and report errors
2161     * This returns the json value (apart from checking errors) only if returnValue provided is true.
2162     * Otherwise it just checks the errors and returns undefined
2163     */
2164    /*@internal*/
2165    export function convertToObjectWorker(
2166        sourceFile: JsonSourceFile,
2167        rootExpression: Expression | undefined,
2168        errors: Push<Diagnostic>,
2169        returnValue: boolean,
2170        knownRootOptions: CommandLineOption | undefined,
2171        jsonConversionNotifier: JsonConversionNotifier | undefined): any {
2172        if (!rootExpression) {
2173            return returnValue ? {} : undefined;
2174        }
2175
2176        return convertPropertyValueToJson(rootExpression, knownRootOptions);
2177
2178        function isRootOptionMap(knownOptions: ESMap<string, CommandLineOption> | undefined) {
2179            return knownRootOptions && (knownRootOptions as TsConfigOnlyOption).elementOptions === knownOptions;
2180        }
2181
2182        function convertObjectLiteralExpressionToJson(
2183            node: ObjectLiteralExpression,
2184            knownOptions: ESMap<string, CommandLineOption> | undefined,
2185            extraKeyDiagnostics: DidYouMeanOptionsDiagnostics | undefined,
2186            parentOption: string | undefined
2187        ): any {
2188            const result: any = returnValue ? {} : undefined;
2189            for (const element of node.properties) {
2190                if (element.kind !== SyntaxKind.PropertyAssignment) {
2191                    errors.push(createDiagnosticForNodeInSourceFile(sourceFile, element, Diagnostics.Property_assignment_expected));
2192                    continue;
2193                }
2194
2195                if (element.questionToken) {
2196                    errors.push(createDiagnosticForNodeInSourceFile(sourceFile, element.questionToken, Diagnostics.The_0_modifier_can_only_be_used_in_TypeScript_files, "?"));
2197                }
2198                if (!isDoubleQuotedString(element.name)) {
2199                    errors.push(createDiagnosticForNodeInSourceFile(sourceFile, element.name, Diagnostics.String_literal_with_double_quotes_expected));
2200                }
2201
2202                const textOfKey = isComputedNonLiteralName(element.name) ? undefined : getTextOfPropertyName(element.name);
2203                const keyText = textOfKey && unescapeLeadingUnderscores(textOfKey);
2204                const option = keyText && knownOptions ? knownOptions.get(keyText) : undefined;
2205                if (keyText && extraKeyDiagnostics && !option) {
2206                    if (knownOptions) {
2207                        errors.push(createUnknownOptionError(
2208                            keyText,
2209                            extraKeyDiagnostics,
2210                            (message, arg0, arg1) => createDiagnosticForNodeInSourceFile(sourceFile, element.name, message, arg0, arg1)
2211                        ));
2212                    }
2213                    else {
2214                        errors.push(createDiagnosticForNodeInSourceFile(sourceFile, element.name, extraKeyDiagnostics.unknownOptionDiagnostic, keyText));
2215                    }
2216                }
2217                const value = convertPropertyValueToJson(element.initializer, option);
2218                if (typeof keyText !== "undefined") {
2219                    if (returnValue) {
2220                        result[keyText] = value;
2221                    }
2222                    // Notify key value set, if user asked for it
2223                    if (jsonConversionNotifier &&
2224                        // Current callbacks are only on known parent option or if we are setting values in the root
2225                        (parentOption || isRootOptionMap(knownOptions))) {
2226                        const isValidOptionValue = isCompilerOptionsValue(option, value);
2227                        if (parentOption) {
2228                            if (isValidOptionValue) {
2229                                // Notify option set in the parent if its a valid option value
2230                                jsonConversionNotifier.onSetValidOptionKeyValueInParent(parentOption, option!, value);
2231                            }
2232                        }
2233                        else if (isRootOptionMap(knownOptions)) {
2234                            if (isValidOptionValue) {
2235                                // Notify about the valid root key value being set
2236                                jsonConversionNotifier.onSetValidOptionKeyValueInRoot(keyText, element.name, value, element.initializer);
2237                            }
2238                            else if (!option) {
2239                                // Notify about the unknown root key value being set
2240                                jsonConversionNotifier.onSetUnknownOptionKeyValueInRoot(keyText, element.name, value, element.initializer);
2241                            }
2242                        }
2243                    }
2244                }
2245            }
2246            return result;
2247        }
2248
2249        function convertArrayLiteralExpressionToJson(
2250            elements: NodeArray<Expression>,
2251            elementOption: CommandLineOption | undefined
2252        ) {
2253            if (!returnValue) {
2254                elements.forEach(element => convertPropertyValueToJson(element, elementOption));
2255                return undefined;
2256            }
2257
2258            // Filter out invalid values
2259            return filter(elements.map(element => convertPropertyValueToJson(element, elementOption)), v => v !== undefined);
2260        }
2261
2262        function convertPropertyValueToJson(valueExpression: Expression, option: CommandLineOption | undefined): any {
2263            let invalidReported: boolean | undefined;
2264            switch (valueExpression.kind) {
2265                case SyntaxKind.TrueKeyword:
2266                    reportInvalidOptionValue(option && option.type !== "boolean");
2267                    return validateValue(/*value*/ true);
2268
2269                case SyntaxKind.FalseKeyword:
2270                    reportInvalidOptionValue(option && option.type !== "boolean");
2271                    return validateValue(/*value*/ false);
2272
2273                case SyntaxKind.NullKeyword:
2274                    reportInvalidOptionValue(option && option.name === "extends"); // "extends" is the only option we don't allow null/undefined for
2275                    return validateValue(/*value*/ null); // eslint-disable-line no-null/no-null
2276
2277                case SyntaxKind.StringLiteral:
2278                    if (!isDoubleQuotedString(valueExpression)) {
2279                        errors.push(createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, Diagnostics.String_literal_with_double_quotes_expected));
2280                    }
2281                    reportInvalidOptionValue(option && (isString(option.type) && option.type !== "string"));
2282                    const text = (valueExpression as StringLiteral).text;
2283                    if (option && !isString(option.type)) {
2284                        const customOption = option as CommandLineOptionOfCustomType;
2285                        // Validate custom option type
2286                        if (!customOption.type.has(text.toLowerCase())) {
2287                            errors.push(
2288                                createDiagnosticForInvalidCustomType(
2289                                    customOption,
2290                                    (message, arg0, arg1) => createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, message, arg0, arg1)
2291                                )
2292                            );
2293                            invalidReported = true;
2294                        }
2295                    }
2296                    return validateValue(text);
2297
2298                case SyntaxKind.NumericLiteral:
2299                    reportInvalidOptionValue(option && option.type !== "number");
2300                    return validateValue(Number((valueExpression as NumericLiteral).text));
2301
2302                case SyntaxKind.PrefixUnaryExpression:
2303                    if ((valueExpression as PrefixUnaryExpression).operator !== SyntaxKind.MinusToken || (valueExpression as PrefixUnaryExpression).operand.kind !== SyntaxKind.NumericLiteral) {
2304                        break; // not valid JSON syntax
2305                    }
2306                    reportInvalidOptionValue(option && option.type !== "number");
2307                    return validateValue(-Number(((valueExpression as PrefixUnaryExpression).operand as NumericLiteral).text));
2308
2309                case SyntaxKind.ObjectLiteralExpression:
2310                    reportInvalidOptionValue(option && option.type !== "object");
2311                    const objectLiteralExpression = valueExpression as ObjectLiteralExpression;
2312
2313                    // Currently having element option declaration in the tsconfig with type "object"
2314                    // determines if it needs onSetValidOptionKeyValueInParent callback or not
2315                    // At moment there are only "compilerOptions", "typeAcquisition" and "typingOptions"
2316                    // that satifies it and need it to modify options set in them (for normalizing file paths)
2317                    // vs what we set in the json
2318                    // If need arises, we can modify this interface and callbacks as needed
2319                    if (option) {
2320                        const { elementOptions, extraKeyDiagnostics, name: optionName } = option as TsConfigOnlyOption;
2321                        return validateValue(convertObjectLiteralExpressionToJson(objectLiteralExpression,
2322                            elementOptions, extraKeyDiagnostics, optionName));
2323                    }
2324                    else {
2325                        return validateValue(convertObjectLiteralExpressionToJson(
2326                            objectLiteralExpression, /* knownOptions*/ undefined,
2327                            /*extraKeyDiagnosticMessage */ undefined, /*parentOption*/ undefined));
2328                    }
2329
2330                case SyntaxKind.ArrayLiteralExpression:
2331                    reportInvalidOptionValue(option && option.type !== "list");
2332                    return validateValue(convertArrayLiteralExpressionToJson(
2333                        (valueExpression as ArrayLiteralExpression).elements,
2334                        option && (option as CommandLineOptionOfListType).element));
2335            }
2336
2337            // Not in expected format
2338            if (option) {
2339                reportInvalidOptionValue(/*isError*/ true);
2340            }
2341            else {
2342                errors.push(createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, Diagnostics.Property_value_can_only_be_string_literal_numeric_literal_true_false_null_object_literal_or_array_literal));
2343            }
2344
2345            return undefined;
2346
2347            function validateValue(value: CompilerOptionsValue) {
2348                if (!invalidReported) {
2349                    const diagnostic = option?.extraValidation?.(value);
2350                    if (diagnostic) {
2351                        errors.push(createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, ...diagnostic));
2352                        return undefined;
2353                    }
2354                }
2355                return value;
2356            }
2357
2358            function reportInvalidOptionValue(isError: boolean | undefined) {
2359                if (isError) {
2360                    errors.push(createDiagnosticForNodeInSourceFile(sourceFile, valueExpression, Diagnostics.Compiler_option_0_requires_a_value_of_type_1, option!.name, getCompilerOptionValueTypeString(option!)));
2361                    invalidReported = true;
2362                }
2363            }
2364        }
2365
2366        function isDoubleQuotedString(node: Node): boolean {
2367            return isStringLiteral(node) && isStringDoubleQuoted(node, sourceFile);
2368        }
2369    }
2370
2371    function getCompilerOptionValueTypeString(option: CommandLineOption) {
2372        return option.type === "list" ?
2373            "Array" :
2374            isString(option.type) ? option.type : "string";
2375    }
2376
2377    function isCompilerOptionsValue(option: CommandLineOption | undefined, value: any): value is CompilerOptionsValue {
2378        if (option) {
2379            if (isNullOrUndefined(value)) return true; // All options are undefinable/nullable
2380            if (option.type === "list") {
2381                return isArray(value);
2382            }
2383            const expectedType = isString(option.type) ? option.type : "string";
2384            return typeof value === expectedType;
2385        }
2386        return false;
2387    }
2388
2389    /** @internal */
2390    export interface TSConfig {
2391        compilerOptions: CompilerOptions;
2392        compileOnSave: boolean | undefined;
2393        exclude?: readonly string[];
2394        files: readonly string[] | undefined;
2395        include?: readonly string[];
2396        references: readonly ProjectReference[] | undefined;
2397    }
2398
2399    /** @internal */
2400    export interface ConvertToTSConfigHost {
2401        getCurrentDirectory(): string;
2402        useCaseSensitiveFileNames: boolean;
2403    }
2404
2405    /**
2406     * Generate an uncommented, complete tsconfig for use with "--showConfig"
2407     * @param configParseResult options to be generated into tsconfig.json
2408     * @param configFileName name of the parsed config file - output paths will be generated relative to this
2409     * @param host provides current directory and case sensitivity services
2410     */
2411    /** @internal */
2412    export function convertToTSConfig(configParseResult: ParsedCommandLine, configFileName: string, host: ConvertToTSConfigHost): TSConfig {
2413        const getCanonicalFileName = createGetCanonicalFileName(host.useCaseSensitiveFileNames);
2414        const files = map(
2415            filter(
2416                configParseResult.fileNames,
2417                !configParseResult.options.configFile?.configFileSpecs?.validatedIncludeSpecs ? returnTrue : matchesSpecs(
2418                    configFileName,
2419                    configParseResult.options.configFile.configFileSpecs.validatedIncludeSpecs,
2420                    configParseResult.options.configFile.configFileSpecs.validatedExcludeSpecs,
2421                    host,
2422                )
2423            ),
2424            f => getRelativePathFromFile(getNormalizedAbsolutePath(configFileName, host.getCurrentDirectory()), getNormalizedAbsolutePath(f, host.getCurrentDirectory()), getCanonicalFileName)
2425        );
2426        const optionMap = serializeCompilerOptions(configParseResult.options, { configFilePath: getNormalizedAbsolutePath(configFileName, host.getCurrentDirectory()), useCaseSensitiveFileNames: host.useCaseSensitiveFileNames });
2427        const watchOptionMap = configParseResult.watchOptions && serializeWatchOptions(configParseResult.watchOptions);
2428        const config = {
2429            compilerOptions: {
2430                ...optionMapToObject(optionMap),
2431                showConfig: undefined,
2432                configFile: undefined,
2433                configFilePath: undefined,
2434                help: undefined,
2435                init: undefined,
2436                listFiles: undefined,
2437                listEmittedFiles: undefined,
2438                project: undefined,
2439                build: undefined,
2440                version: undefined,
2441            },
2442            watchOptions: watchOptionMap && optionMapToObject(watchOptionMap),
2443            references: map(configParseResult.projectReferences, r => ({ ...r, path: r.originalPath ? r.originalPath : "", originalPath: undefined })),
2444            files: length(files) ? files : undefined,
2445            ...(configParseResult.options.configFile?.configFileSpecs ? {
2446                include: filterSameAsDefaultInclude(configParseResult.options.configFile.configFileSpecs.validatedIncludeSpecs),
2447                exclude: configParseResult.options.configFile.configFileSpecs.validatedExcludeSpecs
2448            } : {}),
2449            compileOnSave: !!configParseResult.compileOnSave ? true : undefined
2450        };
2451        return config;
2452    }
2453
2454    function optionMapToObject(optionMap: ESMap<string, CompilerOptionsValue>): object {
2455        return {
2456            ...arrayFrom(optionMap.entries()).reduce((prev, cur) => ({ ...prev, [cur[0]]: cur[1] }), {}),
2457        };
2458    }
2459
2460    function filterSameAsDefaultInclude(specs: readonly string[] | undefined) {
2461        if (!length(specs)) return undefined;
2462        if (length(specs) !== 1) return specs;
2463        if (specs![0] === defaultIncludeSpec) return undefined;
2464        return specs;
2465    }
2466
2467    function matchesSpecs(path: string, includeSpecs: readonly string[] | undefined, excludeSpecs: readonly string[] | undefined, host: ConvertToTSConfigHost): (path: string) => boolean {
2468        if (!includeSpecs) return returnTrue;
2469        const patterns = getFileMatcherPatterns(path, excludeSpecs, includeSpecs, host.useCaseSensitiveFileNames, host.getCurrentDirectory());
2470        const excludeRe = patterns.excludePattern && getRegexFromPattern(patterns.excludePattern, host.useCaseSensitiveFileNames);
2471        const includeRe = patterns.includeFilePattern && getRegexFromPattern(patterns.includeFilePattern, host.useCaseSensitiveFileNames);
2472        if (includeRe) {
2473            if (excludeRe) {
2474                return path => !(includeRe.test(path) && !excludeRe.test(path));
2475            }
2476            return path => !includeRe.test(path);
2477        }
2478        if (excludeRe) {
2479            return path => excludeRe.test(path);
2480        }
2481        return returnTrue;
2482    }
2483
2484    function getCustomTypeMapOfCommandLineOption(optionDefinition: CommandLineOption): ESMap<string, string | number> | undefined {
2485        if (optionDefinition.type === "string" || optionDefinition.type === "number" || optionDefinition.type === "boolean" || optionDefinition.type === "object") {
2486            // this is of a type CommandLineOptionOfPrimitiveType
2487            return undefined;
2488        }
2489        else if (optionDefinition.type === "list") {
2490            return getCustomTypeMapOfCommandLineOption(optionDefinition.element);
2491        }
2492        else {
2493            return optionDefinition.type;
2494        }
2495    }
2496
2497    /* @internal */
2498    export function getNameOfCompilerOptionValue(value: CompilerOptionsValue, customTypeMap: ESMap<string, string | number>): string | undefined {
2499        // There is a typeMap associated with this command-line option so use it to map value back to its name
2500        return forEachEntry(customTypeMap, (mapValue, key) => {
2501            if (mapValue === value) {
2502                return key;
2503            }
2504        });
2505    }
2506
2507    function serializeCompilerOptions(
2508        options: CompilerOptions,
2509        pathOptions?: { configFilePath: string, useCaseSensitiveFileNames: boolean }
2510    ): ESMap<string, CompilerOptionsValue> {
2511        return serializeOptionBaseObject(options, getOptionsNameMap(), pathOptions);
2512    }
2513
2514    function serializeWatchOptions(options: WatchOptions) {
2515        return serializeOptionBaseObject(options, getWatchOptionsNameMap());
2516    }
2517
2518    function serializeOptionBaseObject(
2519        options: OptionsBase,
2520        { optionsNameMap }: OptionsNameMap,
2521        pathOptions?: { configFilePath: string, useCaseSensitiveFileNames: boolean }
2522    ): ESMap<string, CompilerOptionsValue> {
2523        const result = new Map<string, CompilerOptionsValue>();
2524        const getCanonicalFileName = pathOptions && createGetCanonicalFileName(pathOptions.useCaseSensitiveFileNames);
2525
2526        for (const name in options) {
2527            if (hasProperty(options, name)) {
2528                // tsconfig only options cannot be specified via command line,
2529                // so we can assume that only types that can appear here string | number | boolean
2530                if (optionsNameMap.has(name) && (optionsNameMap.get(name)!.category === Diagnostics.Command_line_Options || optionsNameMap.get(name)!.category === Diagnostics.Output_Formatting)) {
2531                    continue;
2532                }
2533                const value = options[name] as CompilerOptionsValue;
2534                const optionDefinition = optionsNameMap.get(name.toLowerCase());
2535                if (optionDefinition) {
2536                    const customTypeMap = getCustomTypeMapOfCommandLineOption(optionDefinition);
2537                    if (!customTypeMap) {
2538                        // There is no map associated with this compiler option then use the value as-is
2539                        // This is the case if the value is expect to be string, number, boolean or list of string
2540                        if (pathOptions && optionDefinition.isFilePath) {
2541                            result.set(name, getRelativePathFromFile(pathOptions.configFilePath, getNormalizedAbsolutePath(value as string, getDirectoryPath(pathOptions.configFilePath)), getCanonicalFileName!));
2542                        }
2543                        else {
2544                            result.set(name, value);
2545                        }
2546                    }
2547                    else {
2548                        if (optionDefinition.type === "list") {
2549                            result.set(name, (value as readonly (string | number)[]).map(element => getNameOfCompilerOptionValue(element, customTypeMap)!)); // TODO: GH#18217
2550                        }
2551                        else {
2552                            // There is a typeMap associated with this command-line option so use it to map value back to its name
2553                            result.set(name, getNameOfCompilerOptionValue(value, customTypeMap));
2554                        }
2555                    }
2556                }
2557            }
2558        }
2559        return result;
2560    }
2561
2562    /**
2563     * Generate a list of the compiler options whose value is not the default.
2564     * @param options compilerOptions to be evaluated.
2565    /** @internal */
2566    export function getCompilerOptionsDiffValue(options: CompilerOptions, newLine: string): string {
2567        const compilerOptionsMap = getSerializedCompilerOption(options);
2568        return getOverwrittenDefaultOptions();
2569
2570        function makePadding(paddingLength: number): string {
2571            return Array(paddingLength + 1).join(" ");
2572        }
2573
2574        function getOverwrittenDefaultOptions() {
2575            const result: string[] = [];
2576             const tab = makePadding(2);
2577            commandOptionsWithoutBuild.forEach(cmd => {
2578                if (!compilerOptionsMap.has(cmd.name)) {
2579                    return;
2580                }
2581
2582                const newValue = compilerOptionsMap.get(cmd.name);
2583                const defaultValue = getDefaultValueForOption(cmd);
2584                if (newValue !== defaultValue) {
2585                    result.push(`${tab}${cmd.name}: ${newValue}`);
2586                }
2587                else if (hasProperty(defaultInitCompilerOptions, cmd.name)) {
2588                    result.push(`${tab}${cmd.name}: ${defaultValue}`);
2589                }
2590            });
2591            return result.join(newLine) + newLine;
2592        }
2593    }
2594
2595    /**
2596     * Get the compiler options to be written into the tsconfig.json.
2597     * @param options commandlineOptions to be included in the compileOptions.
2598     */
2599    function getSerializedCompilerOption(options: CompilerOptions): ESMap<string, CompilerOptionsValue> {
2600        const compilerOptions = extend(options, defaultInitCompilerOptions);
2601        return serializeCompilerOptions(compilerOptions);
2602    }
2603    /**
2604     * Generate tsconfig configuration when running command line "--init"
2605     * @param options commandlineOptions to be generated into tsconfig.json
2606     * @param fileNames array of filenames to be generated into tsconfig.json
2607     */
2608    /* @internal */
2609    export function generateTSConfig(options: CompilerOptions, fileNames: readonly string[], newLine: string): string {
2610        const compilerOptionsMap = getSerializedCompilerOption(options);
2611        return writeConfigurations();
2612
2613        function makePadding(paddingLength: number): string {
2614            return Array(paddingLength + 1).join(" ");
2615        }
2616
2617        function isAllowedOptionForOutput({ category, name, isCommandLineOnly }: CommandLineOption): boolean {
2618            // Skip options which do not have a category or have categories which are more niche
2619            const categoriesToSkip = [Diagnostics.Command_line_Options, Diagnostics.Editor_Support, Diagnostics.Compiler_Diagnostics, Diagnostics.Backwards_Compatibility, Diagnostics.Watch_and_Build_Modes, Diagnostics.Output_Formatting];
2620            return !isCommandLineOnly && category !== undefined && (!categoriesToSkip.includes(category) || compilerOptionsMap.has(name));
2621        }
2622
2623        function writeConfigurations() {
2624            // Filter applicable options to place in the file
2625            const categorizedOptions = new Map<DiagnosticMessage, CommandLineOption[]>();
2626            // Set allowed categories in order
2627            categorizedOptions.set(Diagnostics.Projects, []);
2628            categorizedOptions.set(Diagnostics.Language_and_Environment, []);
2629            categorizedOptions.set(Diagnostics.Modules, []);
2630            categorizedOptions.set(Diagnostics.JavaScript_Support, []);
2631            categorizedOptions.set(Diagnostics.Emit, []);
2632            categorizedOptions.set(Diagnostics.Interop_Constraints, []);
2633            categorizedOptions.set(Diagnostics.Type_Checking, []);
2634            categorizedOptions.set(Diagnostics.Completeness, []);
2635            for (const option of optionDeclarations) {
2636                if (isAllowedOptionForOutput(option)) {
2637                    let listForCategory = categorizedOptions.get(option.category!);
2638                    if (!listForCategory) categorizedOptions.set(option.category!, listForCategory = []);
2639                    listForCategory.push(option);
2640                }
2641            }
2642
2643            // Serialize all options and their descriptions
2644            let marginLength = 0;
2645            let seenKnownKeys = 0;
2646            const entries: { value: string, description?: string }[] = [];
2647            categorizedOptions.forEach((options, category) => {
2648                if (entries.length !== 0) {
2649                    entries.push({ value: "" });
2650                }
2651                entries.push({ value: `/* ${getLocaleSpecificMessage(category)} */` });
2652                for (const option of options) {
2653                    let optionName;
2654                    if (compilerOptionsMap.has(option.name)) {
2655                        optionName = `"${option.name}": ${JSON.stringify(compilerOptionsMap.get(option.name))}${(seenKnownKeys += 1) === compilerOptionsMap.size ? "" : ","}`;
2656                    }
2657                    else {
2658                        optionName = `// "${option.name}": ${JSON.stringify(getDefaultValueForOption(option))},`;
2659                    }
2660                    entries.push({
2661                        value: optionName,
2662                        description: `/* ${option.description && getLocaleSpecificMessage(option.description) || option.name} */`
2663                    });
2664                    marginLength = Math.max(optionName.length, marginLength);
2665                }
2666            });
2667
2668            // Write the output
2669            const tab = makePadding(2);
2670            const result: string[] = [];
2671            result.push(`{`);
2672            result.push(`${tab}"compilerOptions": {`);
2673            result.push(`${tab}${tab}/* ${getLocaleSpecificMessage(Diagnostics.Visit_https_Colon_Slash_Slashaka_ms_Slashtsconfig_to_read_more_about_this_file)} */`);
2674            result.push("");
2675            // Print out each row, aligning all the descriptions on the same column.
2676            for (const entry of entries) {
2677                const { value, description = "" } = entry;
2678                result.push(value && `${tab}${tab}${value}${description && (makePadding(marginLength - value.length + 2) + description)}`);
2679            }
2680            if (fileNames.length) {
2681                result.push(`${tab}},`);
2682                result.push(`${tab}"files": [`);
2683                for (let i = 0; i < fileNames.length; i++) {
2684                    result.push(`${tab}${tab}${JSON.stringify(fileNames[i])}${i === fileNames.length - 1 ? "" : ","}`);
2685                }
2686                result.push(`${tab}]`);
2687            }
2688            else {
2689                result.push(`${tab}}`);
2690            }
2691            result.push(`}`);
2692
2693            return result.join(newLine) + newLine;
2694        }
2695    }
2696
2697    /* @internal */
2698    export function convertToOptionsWithAbsolutePaths(options: CompilerOptions, toAbsolutePath: (path: string) => string) {
2699        const result: CompilerOptions = {};
2700        const optionsNameMap = getOptionsNameMap().optionsNameMap;
2701
2702        for (const name in options) {
2703            if (hasProperty(options, name)) {
2704                result[name] = convertToOptionValueWithAbsolutePaths(
2705                    optionsNameMap.get(name.toLowerCase()),
2706                    options[name] as CompilerOptionsValue,
2707                    toAbsolutePath
2708                );
2709            }
2710        }
2711        if (result.configFilePath) {
2712            result.configFilePath = toAbsolutePath(result.configFilePath);
2713        }
2714        return result;
2715    }
2716
2717    function convertToOptionValueWithAbsolutePaths(option: CommandLineOption | undefined, value: CompilerOptionsValue, toAbsolutePath: (path: string) => string) {
2718        if (option && !isNullOrUndefined(value)) {
2719            if (option.type === "list") {
2720                const values = value as readonly (string | number)[];
2721                if (option.element.isFilePath && values.length) {
2722                    return values.map(toAbsolutePath);
2723                }
2724            }
2725            else if (option.isFilePath) {
2726                return toAbsolutePath(value as string);
2727            }
2728        }
2729        return value;
2730    }
2731
2732    /**
2733     * Parse the contents of a config file (tsconfig.json).
2734     * @param json The contents of the config file to parse
2735     * @param host Instance of ParseConfigHost used to enumerate files in folder.
2736     * @param basePath A root directory to resolve relative path entries in the config
2737     *    file to. e.g. outDir
2738     */
2739    export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[], extraFileExtensions?: readonly FileExtensionInfo[], extendedConfigCache?: Map<ExtendedConfigCacheEntry>, existingWatchOptions?: WatchOptions): ParsedCommandLine {
2740        return parseJsonConfigFileContentWorker(json, /*sourceFile*/ undefined, host, basePath, existingOptions, existingWatchOptions, configFileName, resolutionStack, extraFileExtensions, extendedConfigCache);
2741    }
2742
2743    /**
2744     * Parse the contents of a config file (tsconfig.json).
2745     * @param jsonNode The contents of the config file to parse
2746     * @param host Instance of ParseConfigHost used to enumerate files in folder.
2747     * @param basePath A root directory to resolve relative path entries in the config
2748     *    file to. e.g. outDir
2749     */
2750    export function parseJsonSourceFileConfigFileContent(sourceFile: TsConfigSourceFile, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[], extraFileExtensions?: readonly FileExtensionInfo[], extendedConfigCache?: Map<ExtendedConfigCacheEntry>, existingWatchOptions?: WatchOptions): ParsedCommandLine {
2751        tracing?.push(tracing.Phase.Parse, "parseJsonSourceFileConfigFileContent", { path: sourceFile.fileName });
2752        const result = parseJsonConfigFileContentWorker(/*json*/ undefined, sourceFile, host, basePath, existingOptions, existingWatchOptions, configFileName, resolutionStack, extraFileExtensions, extendedConfigCache);
2753        tracing?.pop();
2754        return result;
2755    }
2756
2757    /*@internal*/
2758    export function setConfigFileInOptions(options: CompilerOptions, configFile: TsConfigSourceFile | undefined) {
2759        if (configFile) {
2760            Object.defineProperty(options, "configFile", { enumerable: false, writable: false, value: configFile });
2761        }
2762    }
2763
2764    function isNullOrUndefined(x: any): x is null | undefined {
2765        return x === undefined || x === null; // eslint-disable-line no-null/no-null
2766    }
2767
2768    function directoryOfCombinedPath(fileName: string, basePath: string) {
2769        // Use the `getNormalizedAbsolutePath` function to avoid canonicalizing the path, as it must remain noncanonical
2770        // until consistent casing errors are reported
2771        return getDirectoryPath(getNormalizedAbsolutePath(fileName, basePath));
2772    }
2773
2774    /*@internal*/
2775    export const defaultIncludeSpec = "**/*";
2776
2777    /**
2778     * Parse the contents of a config file from json or json source file (tsconfig.json).
2779     * @param json The contents of the config file to parse
2780     * @param sourceFile sourceFile corresponding to the Json
2781     * @param host Instance of ParseConfigHost used to enumerate files in folder.
2782     * @param basePath A root directory to resolve relative path entries in the config
2783     *    file to. e.g. outDir
2784     * @param resolutionStack Only present for backwards-compatibility. Should be empty.
2785     */
2786    function parseJsonConfigFileContentWorker(
2787        json: any,
2788        sourceFile: TsConfigSourceFile | undefined,
2789        host: ParseConfigHost,
2790        basePath: string,
2791        existingOptions: CompilerOptions = {},
2792        existingWatchOptions: WatchOptions | undefined,
2793        configFileName?: string,
2794        resolutionStack: Path[] = [],
2795        extraFileExtensions: readonly FileExtensionInfo[] = [],
2796        extendedConfigCache?: ESMap<string, ExtendedConfigCacheEntry>
2797    ): ParsedCommandLine {
2798        Debug.assert((json === undefined && sourceFile !== undefined) || (json !== undefined && sourceFile === undefined));
2799        const errors: Diagnostic[] = [];
2800
2801        const parsedConfig = parseConfig(json, sourceFile, host, basePath, configFileName, resolutionStack, errors, extendedConfigCache);
2802        const { raw } = parsedConfig;
2803        const options = extend(existingOptions, parsedConfig.options || {});
2804        const watchOptions = existingWatchOptions && parsedConfig.watchOptions ?
2805            extend(existingWatchOptions, parsedConfig.watchOptions) :
2806            parsedConfig.watchOptions || existingWatchOptions;
2807
2808        options.configFilePath = configFileName && normalizeSlashes(configFileName);
2809        const configFileSpecs = getConfigFileSpecs();
2810        if (sourceFile) sourceFile.configFileSpecs = configFileSpecs;
2811        setConfigFileInOptions(options, sourceFile);
2812
2813        const basePathForFileNames = normalizePath(configFileName ? directoryOfCombinedPath(configFileName, basePath) : basePath);
2814        return {
2815            options,
2816            watchOptions,
2817            fileNames: getFileNames(basePathForFileNames),
2818            projectReferences: getProjectReferences(basePathForFileNames),
2819            typeAcquisition: parsedConfig.typeAcquisition || getDefaultTypeAcquisition(),
2820            raw,
2821            errors,
2822            // Wildcard directories (provided as part of a wildcard path) are stored in a
2823            // file map that marks whether it was a regular wildcard match (with a `*` or `?` token),
2824            // or a recursive directory. This information is used by filesystem watchers to monitor for
2825            // new entries in these paths.
2826            wildcardDirectories: getWildcardDirectories(configFileSpecs, basePathForFileNames, host.useCaseSensitiveFileNames),
2827            compileOnSave: !!raw.compileOnSave,
2828        };
2829
2830        function getConfigFileSpecs(): ConfigFileSpecs {
2831            const referencesOfRaw = getPropFromRaw<ProjectReference>("references", element => typeof element === "object", "object");
2832            const filesSpecs = toPropValue(getSpecsFromRaw("files"));
2833            if (filesSpecs) {
2834                const hasZeroOrNoReferences = referencesOfRaw === "no-prop" || isArray(referencesOfRaw) && referencesOfRaw.length === 0;
2835                const hasExtends = hasProperty(raw, "extends");
2836                if (filesSpecs.length === 0 && hasZeroOrNoReferences && !hasExtends) {
2837                    if (sourceFile) {
2838                        const fileName = configFileName || "tsconfig.json";
2839                        const diagnosticMessage = Diagnostics.The_files_list_in_config_file_0_is_empty;
2840                        const nodeValue = firstDefined(getTsConfigPropArray(sourceFile, "files"), property => property.initializer);
2841                        const error = nodeValue
2842                            ? createDiagnosticForNodeInSourceFile(sourceFile, nodeValue, diagnosticMessage, fileName)
2843                            : createCompilerDiagnostic(diagnosticMessage, fileName);
2844                        errors.push(error);
2845                    }
2846                    else {
2847                        createCompilerDiagnosticOnlyIfJson(Diagnostics.The_files_list_in_config_file_0_is_empty, configFileName || "tsconfig.json");
2848                    }
2849                }
2850            }
2851
2852            let includeSpecs = toPropValue(getSpecsFromRaw("include"));
2853
2854            const excludeOfRaw = getSpecsFromRaw("exclude");
2855            let isDefaultIncludeSpec = false;
2856            let excludeSpecs = toPropValue(excludeOfRaw);
2857            if (excludeOfRaw === "no-prop" && raw.compilerOptions) {
2858                const outDir = raw.compilerOptions.outDir;
2859                const declarationDir = raw.compilerOptions.declarationDir;
2860
2861                if (outDir || declarationDir) {
2862                    excludeSpecs = [outDir, declarationDir].filter(d => !!d);
2863                }
2864            }
2865
2866            if (filesSpecs === undefined && includeSpecs === undefined) {
2867                includeSpecs = [defaultIncludeSpec];
2868                isDefaultIncludeSpec = true;
2869            }
2870            let validatedIncludeSpecs: readonly string[] | undefined, validatedExcludeSpecs: readonly string[] | undefined;
2871
2872            // The exclude spec list is converted into a regular expression, which allows us to quickly
2873            // test whether a file or directory should be excluded before recursively traversing the
2874            // file system.
2875
2876            if (includeSpecs) {
2877                validatedIncludeSpecs = validateSpecs(includeSpecs, errors, /*disallowTrailingRecursion*/ true, sourceFile, "include");
2878            }
2879
2880            if (excludeSpecs) {
2881                validatedExcludeSpecs = validateSpecs(excludeSpecs, errors, /*disallowTrailingRecursion*/ false, sourceFile, "exclude");
2882            }
2883
2884            return {
2885                filesSpecs,
2886                includeSpecs,
2887                excludeSpecs,
2888                validatedFilesSpec: filter(filesSpecs, isString),
2889                validatedIncludeSpecs,
2890                validatedExcludeSpecs,
2891                pathPatterns: undefined, // Initialized on first use
2892                isDefaultIncludeSpec,
2893            };
2894        }
2895
2896        function getFileNames(basePath: string): string[] {
2897            const fileNames = getFileNamesFromConfigSpecs(configFileSpecs, basePath, options, host, extraFileExtensions);
2898            if (shouldReportNoInputFiles(fileNames, canJsonReportNoInputFiles(raw), resolutionStack)) {
2899                errors.push(getErrorForNoInputFiles(configFileSpecs, configFileName));
2900            }
2901            return fileNames;
2902        }
2903
2904        function getProjectReferences(basePath: string): readonly ProjectReference[] | undefined {
2905            let projectReferences: ProjectReference[] | undefined;
2906            const referencesOfRaw = getPropFromRaw<ProjectReference>("references", element => typeof element === "object", "object");
2907            if (isArray(referencesOfRaw)) {
2908                for (const ref of referencesOfRaw) {
2909                    if (typeof ref.path !== "string") {
2910                        createCompilerDiagnosticOnlyIfJson(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "reference.path", "string");
2911                    }
2912                    else {
2913                        (projectReferences || (projectReferences = [])).push({
2914                            path: getNormalizedAbsolutePath(ref.path, basePath),
2915                            originalPath: ref.path,
2916                            prepend: ref.prepend,
2917                            circular: ref.circular
2918                        });
2919                    }
2920                }
2921            }
2922            return projectReferences;
2923        }
2924
2925        type PropOfRaw<T> = readonly T[] | "not-array" | "no-prop";
2926        function toPropValue<T>(specResult: PropOfRaw<T>) {
2927            return isArray(specResult) ? specResult : undefined;
2928        }
2929
2930        function getSpecsFromRaw(prop: "files" | "include" | "exclude"): PropOfRaw<string> {
2931            return getPropFromRaw(prop, isString, "string");
2932        }
2933
2934        function getPropFromRaw<T>(prop: "files" | "include" | "exclude" | "references", validateElement: (value: unknown) => boolean, elementTypeName: string): PropOfRaw<T> {
2935            if (hasProperty(raw, prop) && !isNullOrUndefined(raw[prop])) {
2936                if (isArray(raw[prop])) {
2937                    const result = raw[prop] as T[];
2938                    if (!sourceFile && !every(result, validateElement)) {
2939                        errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, prop, elementTypeName));
2940                    }
2941                    return result;
2942                }
2943                else {
2944                    createCompilerDiagnosticOnlyIfJson(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, prop, "Array");
2945                    return "not-array";
2946                }
2947            }
2948            return "no-prop";
2949        }
2950
2951        function createCompilerDiagnosticOnlyIfJson(message: DiagnosticMessage, arg0?: string, arg1?: string) {
2952            if (!sourceFile) {
2953                errors.push(createCompilerDiagnostic(message, arg0, arg1));
2954            }
2955        }
2956    }
2957
2958    function isErrorNoInputFiles(error: Diagnostic) {
2959        return error.code === Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2.code;
2960    }
2961
2962    function getErrorForNoInputFiles({ includeSpecs, excludeSpecs }: ConfigFileSpecs, configFileName: string | undefined) {
2963        return createCompilerDiagnostic(
2964            Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
2965            configFileName || "tsconfig.json",
2966            JSON.stringify(includeSpecs || []),
2967            JSON.stringify(excludeSpecs || []));
2968    }
2969
2970    function shouldReportNoInputFiles(fileNames: string[], canJsonReportNoInutFiles: boolean, resolutionStack?: Path[]) {
2971        return fileNames.length === 0 && canJsonReportNoInutFiles && (!resolutionStack || resolutionStack.length === 0);
2972    }
2973
2974    /*@internal*/
2975    export function canJsonReportNoInputFiles(raw: any) {
2976        return !hasProperty(raw, "files") && !hasProperty(raw, "references");
2977    }
2978
2979    /*@internal*/
2980    export function updateErrorForNoInputFiles(fileNames: string[], configFileName: string, configFileSpecs: ConfigFileSpecs, configParseDiagnostics: Diagnostic[], canJsonReportNoInutFiles: boolean) {
2981        const existingErrors = configParseDiagnostics.length;
2982        if (shouldReportNoInputFiles(fileNames, canJsonReportNoInutFiles)) {
2983            configParseDiagnostics.push(getErrorForNoInputFiles(configFileSpecs, configFileName));
2984        }
2985        else {
2986            filterMutate(configParseDiagnostics, error => !isErrorNoInputFiles(error));
2987        }
2988        return existingErrors !== configParseDiagnostics.length;
2989    }
2990
2991    export interface ParsedTsconfig {
2992        raw: any;
2993        options?: CompilerOptions;
2994        watchOptions?: WatchOptions;
2995        typeAcquisition?: TypeAcquisition;
2996        /**
2997         * Note that the case of the config path has not yet been normalized, as no files have been imported into the project yet
2998         */
2999        extendedConfigPath?: string;
3000    }
3001
3002    function isSuccessfulParsedTsconfig(value: ParsedTsconfig) {
3003        return !!value.options;
3004    }
3005
3006    /**
3007     * This *just* extracts options/include/exclude/files out of a config file.
3008     * It does *not* resolve the included files.
3009     */
3010    function parseConfig(
3011        json: any,
3012        sourceFile: TsConfigSourceFile | undefined,
3013        host: ParseConfigHost,
3014        basePath: string,
3015        configFileName: string | undefined,
3016        resolutionStack: string[],
3017        errors: Push<Diagnostic>,
3018        extendedConfigCache?: ESMap<string, ExtendedConfigCacheEntry>
3019    ): ParsedTsconfig {
3020        basePath = normalizeSlashes(basePath);
3021        const resolvedPath = getNormalizedAbsolutePath(configFileName || "", basePath);
3022
3023        if (resolutionStack.indexOf(resolvedPath) >= 0) {
3024            errors.push(createCompilerDiagnostic(Diagnostics.Circularity_detected_while_resolving_configuration_Colon_0, [...resolutionStack, resolvedPath].join(" -> ")));
3025            return { raw: json || convertToObject(sourceFile!, errors) };
3026        }
3027
3028        const ownConfig = json ?
3029            parseOwnConfigOfJson(json, host, basePath, configFileName, errors) :
3030            parseOwnConfigOfJsonSourceFile(sourceFile!, host, basePath, configFileName, errors);
3031
3032        if (ownConfig.options?.paths) {
3033            // If we end up needing to resolve relative paths from 'paths' relative to
3034            // the config file location, we'll need to know where that config file was.
3035            // Since 'paths' can be inherited from an extended config in another directory,
3036            // we wouldn't know which directory to use unless we store it here.
3037            ownConfig.options.pathsBasePath = basePath;
3038        }
3039        if (ownConfig.extendedConfigPath) {
3040            // copy the resolution stack so it is never reused between branches in potential diamond-problem scenarios.
3041            resolutionStack = resolutionStack.concat([resolvedPath]);
3042            const extendedConfig = getExtendedConfig(sourceFile, ownConfig.extendedConfigPath, host, resolutionStack, errors, extendedConfigCache);
3043            if (extendedConfig && isSuccessfulParsedTsconfig(extendedConfig)) {
3044                const baseRaw = extendedConfig.raw;
3045                const raw = ownConfig.raw;
3046                let relativeDifference: string | undefined ;
3047                const setPropertyInRawIfNotUndefined = (propertyName: string) => {
3048                    if (!raw[propertyName] && baseRaw[propertyName]) {
3049                        raw[propertyName] = map(baseRaw[propertyName], (path: string) => isRootedDiskPath(path) ? path : combinePaths(
3050                            relativeDifference ||= convertToRelativePath(getDirectoryPath(ownConfig.extendedConfigPath!), basePath, createGetCanonicalFileName(host.useCaseSensitiveFileNames)),
3051                            path
3052                        ));
3053                    }
3054                };
3055                setPropertyInRawIfNotUndefined("include");
3056                setPropertyInRawIfNotUndefined("exclude");
3057                setPropertyInRawIfNotUndefined("files");
3058                if (raw.compileOnSave === undefined) {
3059                    raw.compileOnSave = baseRaw.compileOnSave;
3060                }
3061                ownConfig.options = assign({}, extendedConfig.options, ownConfig.options);
3062                ownConfig.watchOptions = ownConfig.watchOptions && extendedConfig.watchOptions ?
3063                    assign({}, extendedConfig.watchOptions, ownConfig.watchOptions) :
3064                    ownConfig.watchOptions || extendedConfig.watchOptions;
3065                // TODO extend type typeAcquisition
3066            }
3067        }
3068
3069        return ownConfig;
3070    }
3071
3072    function parseOwnConfigOfJson(
3073        json: any,
3074        host: ParseConfigHost,
3075        basePath: string,
3076        configFileName: string | undefined,
3077        errors: Push<Diagnostic>
3078    ): ParsedTsconfig {
3079        if (hasProperty(json, "excludes")) {
3080            errors.push(createCompilerDiagnostic(Diagnostics.Unknown_option_excludes_Did_you_mean_exclude));
3081        }
3082
3083        const options = convertCompilerOptionsFromJsonWorker(json.compilerOptions, basePath, errors, configFileName);
3084        // typingOptions has been deprecated and is only supported for backward compatibility purposes.
3085        // It should be removed in future releases - use typeAcquisition instead.
3086        const typeAcquisition = convertTypeAcquisitionFromJsonWorker(json.typeAcquisition || json.typingOptions, basePath, errors, configFileName);
3087        const watchOptions = convertWatchOptionsFromJsonWorker(json.watchOptions, basePath, errors);
3088        json.compileOnSave = convertCompileOnSaveOptionFromJson(json, basePath, errors);
3089        let extendedConfigPath: string | undefined;
3090
3091        if (json.extends) {
3092            if (!isString(json.extends)) {
3093                errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "extends", "string"));
3094            }
3095            else {
3096                const newBase = configFileName ? directoryOfCombinedPath(configFileName, basePath) : basePath;
3097                extendedConfigPath = getExtendsConfigPath(json.extends, host, newBase, errors, createCompilerDiagnostic);
3098            }
3099        }
3100        return { raw: json, options, watchOptions, typeAcquisition, extendedConfigPath };
3101    }
3102
3103    function parseOwnConfigOfJsonSourceFile(
3104        sourceFile: TsConfigSourceFile,
3105        host: ParseConfigHost,
3106        basePath: string,
3107        configFileName: string | undefined,
3108        errors: Push<Diagnostic>
3109    ): ParsedTsconfig {
3110        const options = getDefaultCompilerOptions(configFileName);
3111        let typeAcquisition: TypeAcquisition | undefined, typingOptionstypeAcquisition: TypeAcquisition | undefined;
3112        let watchOptions: WatchOptions | undefined;
3113        let extendedConfigPath: string | undefined;
3114        let rootCompilerOptions: PropertyName[] | undefined;
3115
3116        const optionsIterator: JsonConversionNotifier = {
3117            onSetValidOptionKeyValueInParent(parentOption: string, option: CommandLineOption, value: CompilerOptionsValue) {
3118                let currentOption;
3119                switch (parentOption) {
3120                    case "compilerOptions":
3121                        currentOption = options;
3122                        break;
3123                    case "watchOptions":
3124                        currentOption = (watchOptions || (watchOptions = {}));
3125                        break;
3126                    case "typeAcquisition":
3127                        currentOption = (typeAcquisition || (typeAcquisition = getDefaultTypeAcquisition(configFileName)));
3128                        break;
3129                    case "typingOptions":
3130                        currentOption = (typingOptionstypeAcquisition || (typingOptionstypeAcquisition = getDefaultTypeAcquisition(configFileName)));
3131                        break;
3132                    default:
3133                        Debug.fail("Unknown option");
3134                }
3135
3136                currentOption[option.name] = normalizeOptionValue(option, basePath, value);
3137            },
3138            onSetValidOptionKeyValueInRoot(key: string, _keyNode: PropertyName, value: CompilerOptionsValue, valueNode: Expression) {
3139                switch (key) {
3140                    case "extends":
3141                        const newBase = configFileName ? directoryOfCombinedPath(configFileName, basePath) : basePath;
3142                        extendedConfigPath = getExtendsConfigPath(
3143                            value as string,
3144                            host,
3145                            newBase,
3146                            errors,
3147                            (message, arg0) =>
3148                                createDiagnosticForNodeInSourceFile(sourceFile, valueNode, message, arg0)
3149                        );
3150                        return;
3151                }
3152            },
3153            onSetUnknownOptionKeyValueInRoot(key: string, keyNode: PropertyName, _value: CompilerOptionsValue, _valueNode: Expression) {
3154                if (key === "excludes") {
3155                    errors.push(createDiagnosticForNodeInSourceFile(sourceFile, keyNode, Diagnostics.Unknown_option_excludes_Did_you_mean_exclude));
3156                }
3157                if (find(commandOptionsWithoutBuild, (opt) => opt.name === key)) {
3158                    rootCompilerOptions = append(rootCompilerOptions, keyNode);
3159                }
3160            }
3161        };
3162        const json = convertConfigFileToObject(sourceFile, errors, /*reportOptionsErrors*/ true, optionsIterator);
3163
3164        if (!typeAcquisition) {
3165            if (typingOptionstypeAcquisition) {
3166                typeAcquisition = (typingOptionstypeAcquisition.enableAutoDiscovery !== undefined) ?
3167                    {
3168                        enable: typingOptionstypeAcquisition.enableAutoDiscovery,
3169                        include: typingOptionstypeAcquisition.include,
3170                        exclude: typingOptionstypeAcquisition.exclude
3171                    } :
3172                    typingOptionstypeAcquisition;
3173            }
3174            else {
3175                typeAcquisition = getDefaultTypeAcquisition(configFileName);
3176            }
3177        }
3178
3179        if (rootCompilerOptions && json && json.compilerOptions === undefined) {
3180            errors.push(createDiagnosticForNodeInSourceFile(sourceFile, rootCompilerOptions[0], Diagnostics._0_should_be_set_inside_the_compilerOptions_object_of_the_config_json_file, getTextOfPropertyName(rootCompilerOptions[0]) as string));
3181        }
3182
3183        return { raw: json, options, watchOptions, typeAcquisition, extendedConfigPath };
3184    }
3185
3186    function getExtendsConfigPath(
3187        extendedConfig: string,
3188        host: ParseConfigHost,
3189        basePath: string,
3190        errors: Push<Diagnostic>,
3191        createDiagnostic: (message: DiagnosticMessage, arg1?: string) => Diagnostic) {
3192        extendedConfig = normalizeSlashes(extendedConfig);
3193        if (isRootedDiskPath(extendedConfig) || startsWith(extendedConfig, "./") || startsWith(extendedConfig, "../")) {
3194            let extendedConfigPath = getNormalizedAbsolutePath(extendedConfig, basePath);
3195            if (!host.fileExists(extendedConfigPath) && !endsWith(extendedConfigPath, Extension.Json)) {
3196                extendedConfigPath = `${extendedConfigPath}.json`;
3197                if (!host.fileExists(extendedConfigPath)) {
3198                    errors.push(createDiagnostic(Diagnostics.File_0_not_found, extendedConfig));
3199                    return undefined;
3200                }
3201            }
3202            return extendedConfigPath;
3203        }
3204        // If the path isn't a rooted or relative path, resolve like a module
3205        const resolved = nodeModuleNameResolver(extendedConfig, combinePaths(basePath, "tsconfig.json"), { moduleResolution: ModuleResolutionKind.NodeJs }, host, /*cache*/ undefined, /*projectRefs*/ undefined, /*lookupConfig*/ true);
3206        if (resolved.resolvedModule) {
3207            return resolved.resolvedModule.resolvedFileName;
3208        }
3209        errors.push(createDiagnostic(Diagnostics.File_0_not_found, extendedConfig));
3210        return undefined;
3211    }
3212
3213    export interface ExtendedConfigCacheEntry {
3214        extendedResult: TsConfigSourceFile;
3215        extendedConfig: ParsedTsconfig | undefined;
3216    }
3217
3218    function getExtendedConfig(
3219        sourceFile: TsConfigSourceFile | undefined,
3220        extendedConfigPath: string,
3221        host: ParseConfigHost,
3222        resolutionStack: string[],
3223        errors: Push<Diagnostic>,
3224        extendedConfigCache?: ESMap<string, ExtendedConfigCacheEntry>
3225    ): ParsedTsconfig | undefined {
3226        const path = host.useCaseSensitiveFileNames ? extendedConfigPath : toFileNameLowerCase(extendedConfigPath);
3227        let value: ExtendedConfigCacheEntry | undefined;
3228        let extendedResult: TsConfigSourceFile;
3229        let extendedConfig: ParsedTsconfig | undefined;
3230        if (extendedConfigCache && (value = extendedConfigCache.get(path))) {
3231            ({ extendedResult, extendedConfig } = value);
3232        }
3233        else {
3234            extendedResult = readJsonConfigFile(extendedConfigPath, path => host.readFile(path));
3235            if (!extendedResult.parseDiagnostics.length) {
3236                extendedConfig = parseConfig(/*json*/ undefined, extendedResult, host, getDirectoryPath(extendedConfigPath),
3237                    getBaseFileName(extendedConfigPath), resolutionStack, errors, extendedConfigCache);
3238            }
3239            if (extendedConfigCache) {
3240                extendedConfigCache.set(path, { extendedResult, extendedConfig });
3241            }
3242        }
3243        if (sourceFile) {
3244            sourceFile.extendedSourceFiles = [extendedResult.fileName];
3245            if (extendedResult.extendedSourceFiles) {
3246                sourceFile.extendedSourceFiles.push(...extendedResult.extendedSourceFiles);
3247            }
3248        }
3249        if (extendedResult.parseDiagnostics.length) {
3250            errors.push(...extendedResult.parseDiagnostics);
3251            return undefined;
3252        }
3253        return extendedConfig!;
3254    }
3255
3256    function convertCompileOnSaveOptionFromJson(jsonOption: any, basePath: string, errors: Push<Diagnostic>): boolean {
3257        if (!hasProperty(jsonOption, compileOnSaveCommandLineOption.name)) {
3258            return false;
3259        }
3260        const result = convertJsonOption(compileOnSaveCommandLineOption, jsonOption.compileOnSave, basePath, errors);
3261        return typeof result === "boolean" && result;
3262    }
3263
3264    export function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: CompilerOptions, errors: Diagnostic[] } {
3265        const errors: Diagnostic[] = [];
3266        const options = convertCompilerOptionsFromJsonWorker(jsonOptions, basePath, errors, configFileName);
3267        return { options, errors };
3268    }
3269
3270    export function convertTypeAcquisitionFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: TypeAcquisition, errors: Diagnostic[] } {
3271        const errors: Diagnostic[] = [];
3272        const options = convertTypeAcquisitionFromJsonWorker(jsonOptions, basePath, errors, configFileName);
3273        return { options, errors };
3274    }
3275
3276    function getDefaultCompilerOptions(configFileName?: string) {
3277        const options: CompilerOptions = configFileName && getBaseFileName(configFileName) === "jsconfig.json"
3278            ? { allowJs: true, maxNodeModuleJsDepth: 2, allowSyntheticDefaultImports: true, skipLibCheck: true, noEmit: true }
3279            : {};
3280        return options;
3281    }
3282
3283    function convertCompilerOptionsFromJsonWorker(jsonOptions: any,
3284        basePath: string, errors: Push<Diagnostic>, configFileName?: string): CompilerOptions {
3285
3286        const options = getDefaultCompilerOptions(configFileName);
3287        convertOptionsFromJson(getCommandLineCompilerOptionsMap(), jsonOptions, basePath, options, compilerOptionsDidYouMeanDiagnostics, errors);
3288        if (configFileName) {
3289            options.configFilePath = normalizeSlashes(configFileName);
3290        }
3291        return options;
3292    }
3293
3294    function getDefaultTypeAcquisition(configFileName?: string): TypeAcquisition {
3295        return { enable: !!configFileName && getBaseFileName(configFileName) === "jsconfig.json", include: [], exclude: [] };
3296    }
3297
3298    function convertTypeAcquisitionFromJsonWorker(jsonOptions: any,
3299        basePath: string, errors: Push<Diagnostic>, configFileName?: string): TypeAcquisition {
3300
3301        const options = getDefaultTypeAcquisition(configFileName);
3302        const typeAcquisition = convertEnableAutoDiscoveryToEnable(jsonOptions);
3303
3304        convertOptionsFromJson(getCommandLineTypeAcquisitionMap(), typeAcquisition, basePath, options, typeAcquisitionDidYouMeanDiagnostics, errors);
3305        return options;
3306    }
3307
3308    function convertWatchOptionsFromJsonWorker(jsonOptions: any, basePath: string, errors: Push<Diagnostic>): WatchOptions | undefined {
3309        return convertOptionsFromJson(getCommandLineWatchOptionsMap(), jsonOptions, basePath, /*defaultOptions*/ undefined, watchOptionsDidYouMeanDiagnostics, errors);
3310    }
3311
3312    function convertOptionsFromJson(optionsNameMap: ESMap<string, CommandLineOption>, jsonOptions: any, basePath: string,
3313        defaultOptions: undefined, diagnostics: DidYouMeanOptionsDiagnostics, errors: Push<Diagnostic>): WatchOptions | undefined;
3314    function convertOptionsFromJson(optionsNameMap: ESMap<string, CommandLineOption>, jsonOptions: any, basePath: string,
3315        defaultOptions: CompilerOptions | TypeAcquisition, diagnostics: DidYouMeanOptionsDiagnostics, errors: Push<Diagnostic>): CompilerOptions | TypeAcquisition;
3316    function convertOptionsFromJson(optionsNameMap: ESMap<string, CommandLineOption>, jsonOptions: any, basePath: string,
3317        defaultOptions: CompilerOptions | TypeAcquisition | WatchOptions | undefined, diagnostics: DidYouMeanOptionsDiagnostics, errors: Push<Diagnostic>) {
3318
3319        if (!jsonOptions) {
3320            return;
3321        }
3322
3323        for (const id in jsonOptions) {
3324            const opt = optionsNameMap.get(id);
3325            if (opt) {
3326                (defaultOptions || (defaultOptions = {}))[opt.name] = convertJsonOption(opt, jsonOptions[id], basePath, errors);
3327            }
3328            else {
3329                errors.push(createUnknownOptionError(id, diagnostics, createCompilerDiagnostic));
3330            }
3331        }
3332        return defaultOptions;
3333    }
3334
3335    /*@internal*/
3336    export function convertJsonOption(opt: CommandLineOption, value: any, basePath: string, errors: Push<Diagnostic>): CompilerOptionsValue {
3337        if (isCompilerOptionsValue(opt, value)) {
3338            const optType = opt.type;
3339            if (optType === "list" && isArray(value)) {
3340                return convertJsonOptionOfListType(opt , value, basePath, errors);
3341            }
3342            else if (!isString(optType)) {
3343                return convertJsonOptionOfCustomType(opt as CommandLineOptionOfCustomType, value as string, errors);
3344            }
3345            const validatedValue = validateJsonOptionValue(opt, value, errors);
3346            return isNullOrUndefined(validatedValue) ? validatedValue : normalizeNonListOptionValue(opt, basePath, validatedValue);
3347        }
3348        else {
3349            errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, opt.name, getCompilerOptionValueTypeString(opt)));
3350        }
3351    }
3352
3353    function normalizeOptionValue(option: CommandLineOption, basePath: string, value: any): CompilerOptionsValue {
3354        if (isNullOrUndefined(value)) return undefined;
3355        if (option.type === "list") {
3356            const listOption = option;
3357            if (listOption.element.isFilePath || !isString(listOption.element.type)) {
3358                return filter(map(value, v => normalizeOptionValue(listOption.element, basePath, v)), v => listOption.listPreserveFalsyValues ? true : !!v) as CompilerOptionsValue;
3359            }
3360            return value;
3361        }
3362        else if (!isString(option.type)) {
3363            return option.type.get(isString(value) ? value.toLowerCase() : value);
3364        }
3365        return normalizeNonListOptionValue(option, basePath, value);
3366    }
3367
3368    function normalizeNonListOptionValue(option: CommandLineOption, basePath: string, value: any): CompilerOptionsValue {
3369        if (option.isFilePath) {
3370            value = getNormalizedAbsolutePath(value, basePath);
3371            if (value === "") {
3372                value = ".";
3373            }
3374        }
3375        return value;
3376    }
3377
3378    function validateJsonOptionValue<T extends CompilerOptionsValue>(opt: CommandLineOption, value: T, errors: Push<Diagnostic>): T | undefined {
3379        if (isNullOrUndefined(value)) return undefined;
3380        const d = opt.extraValidation?.(value);
3381        if (!d) return value;
3382        errors.push(createCompilerDiagnostic(...d));
3383        return undefined;
3384    }
3385
3386    function convertJsonOptionOfCustomType(opt: CommandLineOptionOfCustomType, value: string, errors: Push<Diagnostic>) {
3387        if (isNullOrUndefined(value)) return undefined;
3388        const key = value.toLowerCase();
3389        const val = opt.type.get(key);
3390        if (val !== undefined) {
3391            return validateJsonOptionValue(opt, val, errors);
3392        }
3393        else {
3394            errors.push(createCompilerDiagnosticForInvalidCustomType(opt));
3395        }
3396    }
3397
3398    function convertJsonOptionOfListType(option: CommandLineOptionOfListType, values: readonly any[], basePath: string, errors: Push<Diagnostic>): any[] {
3399        return filter(map(values, v => convertJsonOption(option.element, v, basePath, errors)), v => option.listPreserveFalsyValues ? true : !!v);
3400    }
3401
3402    /**
3403     * Tests for a path that ends in a recursive directory wildcard.
3404     * Matches **, \**, **\, and \**\, but not a**b.
3405     *
3406     * NOTE: used \ in place of / above to avoid issues with multiline comments.
3407     *
3408     * Breakdown:
3409     *  (^|\/)      # matches either the beginning of the string or a directory separator.
3410     *  \*\*        # matches the recursive directory wildcard "**".
3411     *  \/?$        # matches an optional trailing directory separator at the end of the string.
3412     */
3413    const invalidTrailingRecursionPattern = /(^|\/)\*\*\/?$/;
3414
3415    /**
3416     * Matches the portion of a wildcard path that does not contain wildcards.
3417     * Matches \a of \a\*, or \a\b\c of \a\b\c\?\d.
3418     *
3419     * NOTE: used \ in place of / above to avoid issues with multiline comments.
3420     *
3421     * Breakdown:
3422     *  ^                   # matches the beginning of the string
3423     *  [^*?]*              # matches any number of non-wildcard characters
3424     *  (?=\/[^/]*[*?])     # lookahead that matches a directory separator followed by
3425     *                      # a path component that contains at least one wildcard character (* or ?).
3426     */
3427    const wildcardDirectoryPattern = /^[^*?]*(?=\/[^/]*[*?])/;
3428
3429    /**
3430     * Gets the file names from the provided config file specs that contain, files, include, exclude and
3431     * other properties needed to resolve the file names
3432     * @param configFileSpecs The config file specs extracted with file names to include, wildcards to include/exclude and other details
3433     * @param basePath The base path for any relative file specifications.
3434     * @param options Compiler options.
3435     * @param host The host used to resolve files and directories.
3436     * @param extraFileExtensions optionaly file extra file extension information from host
3437     */
3438    /* @internal */
3439    export function getFileNamesFromConfigSpecs(
3440        configFileSpecs: ConfigFileSpecs,
3441        basePath: string,
3442        options: CompilerOptions,
3443        host: ParseConfigHost,
3444        extraFileExtensions: readonly FileExtensionInfo[] = emptyArray
3445    ): string[] {
3446        basePath = normalizePath(basePath);
3447
3448        const keyMapper = createGetCanonicalFileName(host.useCaseSensitiveFileNames);
3449
3450        // Literal file names (provided via the "files" array in tsconfig.json) are stored in a
3451        // file map with a possibly case insensitive key. We use this map later when when including
3452        // wildcard paths.
3453        const literalFileMap = new Map<string, string>();
3454
3455        // Wildcard paths (provided via the "includes" array in tsconfig.json) are stored in a
3456        // file map with a possibly case insensitive key. We use this map to store paths matched
3457        // via wildcard, and to handle extension priority.
3458        const wildcardFileMap = new Map<string, string>();
3459
3460        // Wildcard paths of json files (provided via the "includes" array in tsconfig.json) are stored in a
3461        // file map with a possibly case insensitive key. We use this map to store paths matched
3462        // via wildcard of *.json kind
3463        const wildCardJsonFileMap = new Map<string, string>();
3464        const { validatedFilesSpec, validatedIncludeSpecs, validatedExcludeSpecs } = configFileSpecs;
3465
3466        // Rather than re-query this for each file and filespec, we query the supported extensions
3467        // once and store it on the expansion context.
3468        const supportedExtensions = getSupportedExtensions(options, extraFileExtensions);
3469        const supportedExtensionsWithJsonIfResolveJsonModule = getSupportedExtensionsWithJsonIfResolveJsonModule(options, supportedExtensions);
3470
3471        // Literal files are always included verbatim. An "include" or "exclude" specification cannot
3472        // remove a literal file.
3473        if (validatedFilesSpec) {
3474            for (const fileName of validatedFilesSpec) {
3475                const file = getNormalizedAbsolutePath(fileName, basePath);
3476                literalFileMap.set(keyMapper(file), file);
3477            }
3478        }
3479
3480        let jsonOnlyIncludeRegexes: readonly RegExp[] | undefined;
3481        if (validatedIncludeSpecs && validatedIncludeSpecs.length > 0) {
3482            for (const file of host.readDirectory(basePath, flatten(supportedExtensionsWithJsonIfResolveJsonModule), validatedExcludeSpecs, validatedIncludeSpecs, /*depth*/ undefined)) {
3483                if (fileExtensionIs(file, Extension.Json)) {
3484                    // Valid only if *.json specified
3485                    if (!jsonOnlyIncludeRegexes) {
3486                        const includes = validatedIncludeSpecs.filter(s => endsWith(s, Extension.Json));
3487                        const includeFilePatterns = map(getRegularExpressionsForWildcards(includes, basePath, "files"), pattern => `^${pattern}$`);
3488                        jsonOnlyIncludeRegexes = includeFilePatterns ? includeFilePatterns.map(pattern => getRegexFromPattern(pattern, host.useCaseSensitiveFileNames)) : emptyArray;
3489                    }
3490                    const includeIndex = findIndex(jsonOnlyIncludeRegexes, re => re.test(file));
3491                    if (includeIndex !== -1) {
3492                        const key = keyMapper(file);
3493                        if (!literalFileMap.has(key) && !wildCardJsonFileMap.has(key)) {
3494                            wildCardJsonFileMap.set(key, file);
3495                        }
3496                    }
3497                    continue;
3498                }
3499                // If we have already included a literal or wildcard path with a
3500                // higher priority extension, we should skip this file.
3501                //
3502                // This handles cases where we may encounter both <file>.ts and
3503                // <file>.d.ts (or <file>.js if "allowJs" is enabled) in the same
3504                // directory when they are compilation outputs.
3505                if (hasFileWithHigherPriorityExtension(file, literalFileMap, wildcardFileMap, supportedExtensions, keyMapper)) {
3506                    continue;
3507                }
3508
3509                // We may have included a wildcard path with a lower priority
3510                // extension due to the user-defined order of entries in the
3511                // "include" array. If there is a lower priority extension in the
3512                // same directory, we should remove it.
3513                removeWildcardFilesWithLowerPriorityExtension(file, wildcardFileMap, supportedExtensions, keyMapper);
3514
3515                const key = keyMapper(file);
3516                if (!literalFileMap.has(key) && !wildcardFileMap.has(key)) {
3517                    wildcardFileMap.set(key, file);
3518                }
3519            }
3520        }
3521
3522        const literalFiles = arrayFrom(literalFileMap.values());
3523        const wildcardFiles = arrayFrom(wildcardFileMap.values());
3524
3525        return literalFiles.concat(wildcardFiles, arrayFrom(wildCardJsonFileMap.values()));
3526    }
3527
3528    /* @internal */
3529    export function isExcludedFile(
3530        pathToCheck: string,
3531        spec: ConfigFileSpecs,
3532        basePath: string,
3533        useCaseSensitiveFileNames: boolean,
3534        currentDirectory: string
3535    ): boolean {
3536        const { validatedFilesSpec, validatedIncludeSpecs, validatedExcludeSpecs } = spec;
3537        if (!length(validatedIncludeSpecs) || !length(validatedExcludeSpecs)) return false;
3538
3539        basePath = normalizePath(basePath);
3540
3541        const keyMapper = createGetCanonicalFileName(useCaseSensitiveFileNames);
3542        if (validatedFilesSpec) {
3543            for (const fileName of validatedFilesSpec) {
3544                if (keyMapper(getNormalizedAbsolutePath(fileName, basePath)) === pathToCheck) return false;
3545            }
3546        }
3547
3548        return matchesExcludeWorker(pathToCheck, validatedExcludeSpecs, useCaseSensitiveFileNames, currentDirectory, basePath);
3549    }
3550
3551    function invalidDotDotAfterRecursiveWildcard(s: string) {
3552        // We used to use the regex /(^|\/)\*\*\/(.*\/)?\.\.($|\/)/ to check for this case, but
3553        // in v8, that has polynomial performance because the recursive wildcard match - **/ -
3554        // can be matched in many arbitrary positions when multiple are present, resulting
3555        // in bad backtracking (and we don't care which is matched - just that some /.. segment
3556        // comes after some **/ segment).
3557        const wildcardIndex = startsWith(s, "**/") ? 0 : s.indexOf("/**/");
3558        if (wildcardIndex === -1) {
3559            return false;
3560        }
3561        const lastDotIndex = endsWith(s, "/..") ? s.length : s.lastIndexOf("/../");
3562        return lastDotIndex > wildcardIndex;
3563    }
3564
3565    /* @internal */
3566    export function matchesExclude(
3567        pathToCheck: string,
3568        excludeSpecs: readonly string[] | undefined,
3569        useCaseSensitiveFileNames: boolean,
3570        currentDirectory: string
3571    ) {
3572        return matchesExcludeWorker(
3573            pathToCheck,
3574            filter(excludeSpecs, spec => !invalidDotDotAfterRecursiveWildcard(spec)),
3575            useCaseSensitiveFileNames,
3576            currentDirectory
3577        );
3578    }
3579
3580    function matchesExcludeWorker(
3581        pathToCheck: string,
3582        excludeSpecs: readonly string[] | undefined,
3583        useCaseSensitiveFileNames: boolean,
3584        currentDirectory: string,
3585        basePath?: string
3586    ) {
3587        const excludePattern = getRegularExpressionForWildcard(excludeSpecs, combinePaths(normalizePath(currentDirectory), basePath), "exclude");
3588        const excludeRegex = excludePattern && getRegexFromPattern(excludePattern, useCaseSensitiveFileNames);
3589        if (!excludeRegex) return false;
3590        if (excludeRegex.test(pathToCheck)) return true;
3591        return !hasExtension(pathToCheck) && excludeRegex.test(ensureTrailingDirectorySeparator(pathToCheck));
3592    }
3593
3594    function validateSpecs(specs: readonly string[], errors: Push<Diagnostic>, disallowTrailingRecursion: boolean, jsonSourceFile: TsConfigSourceFile | undefined, specKey: string): readonly string[] {
3595        return specs.filter(spec => {
3596            if (!isString(spec)) return false;
3597            const diag = specToDiagnostic(spec, disallowTrailingRecursion);
3598            if (diag !== undefined) {
3599                errors.push(createDiagnostic(...diag));
3600            }
3601            return diag === undefined;
3602        });
3603
3604        function createDiagnostic(message: DiagnosticMessage, spec: string): Diagnostic {
3605            const element = getTsConfigPropArrayElementValue(jsonSourceFile, specKey, spec);
3606            return element ?
3607                createDiagnosticForNodeInSourceFile(jsonSourceFile!, element, message, spec) :
3608                createCompilerDiagnostic(message, spec);
3609        }
3610    }
3611
3612    function specToDiagnostic(spec: string, disallowTrailingRecursion?: boolean): [DiagnosticMessage, string] | undefined {
3613        if (disallowTrailingRecursion && invalidTrailingRecursionPattern.test(spec)) {
3614            return [Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, spec];
3615        }
3616        else if (invalidDotDotAfterRecursiveWildcard(spec)) {
3617            return [Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, spec];
3618        }
3619    }
3620
3621    /**
3622     * Gets directories in a set of include patterns that should be watched for changes.
3623     */
3624    function getWildcardDirectories({ validatedIncludeSpecs: include, validatedExcludeSpecs: exclude }: ConfigFileSpecs, path: string, useCaseSensitiveFileNames: boolean): MapLike<WatchDirectoryFlags> {
3625        // We watch a directory recursively if it contains a wildcard anywhere in a directory segment
3626        // of the pattern:
3627        //
3628        //  /a/b/**/d   - Watch /a/b recursively to catch changes to any d in any subfolder recursively
3629        //  /a/b/*/d    - Watch /a/b recursively to catch any d in any immediate subfolder, even if a new subfolder is added
3630        //  /a/b        - Watch /a/b recursively to catch changes to anything in any recursive subfoler
3631        //
3632        // We watch a directory without recursion if it contains a wildcard in the file segment of
3633        // the pattern:
3634        //
3635        //  /a/b/*      - Watch /a/b directly to catch any new file
3636        //  /a/b/a?z    - Watch /a/b directly to catch any new file matching a?z
3637        const rawExcludeRegex = getRegularExpressionForWildcard(exclude, path, "exclude");
3638        const excludeRegex = rawExcludeRegex && new RegExp(rawExcludeRegex, useCaseSensitiveFileNames ? "" : "i");
3639        const wildcardDirectories: MapLike<WatchDirectoryFlags> = {};
3640        if (include !== undefined) {
3641            const recursiveKeys: string[] = [];
3642            for (const file of include) {
3643                const spec = normalizePath(combinePaths(path, file));
3644                if (excludeRegex && excludeRegex.test(spec)) {
3645                    continue;
3646                }
3647
3648                const match = getWildcardDirectoryFromSpec(spec, useCaseSensitiveFileNames);
3649                if (match) {
3650                    const { key, flags } = match;
3651                    const existingFlags = wildcardDirectories[key];
3652                    if (existingFlags === undefined || existingFlags < flags) {
3653                        wildcardDirectories[key] = flags;
3654                        if (flags === WatchDirectoryFlags.Recursive) {
3655                            recursiveKeys.push(key);
3656                        }
3657                    }
3658                }
3659            }
3660
3661            // Remove any subpaths under an existing recursively watched directory.
3662            for (const key in wildcardDirectories) {
3663                if (hasProperty(wildcardDirectories, key)) {
3664                    for (const recursiveKey of recursiveKeys) {
3665                        if (key !== recursiveKey && containsPath(recursiveKey, key, path, !useCaseSensitiveFileNames)) {
3666                            delete wildcardDirectories[key];
3667                        }
3668                    }
3669                }
3670            }
3671        }
3672
3673        return wildcardDirectories;
3674    }
3675
3676    function getWildcardDirectoryFromSpec(spec: string, useCaseSensitiveFileNames: boolean): { key: string, flags: WatchDirectoryFlags } | undefined {
3677        const match = wildcardDirectoryPattern.exec(spec);
3678        if (match) {
3679            // We check this with a few `indexOf` calls because 3 `indexOf`/`lastIndexOf` calls is
3680            // less algorithmically complex (roughly O(3n) worst-case) than the regex we used to use,
3681            // \/[^/]*?[*?][^/]*\/ which was polynominal in v8, since arbitrary sequences of wildcard
3682            // characters could match any of the central patterns, resulting in bad backtracking.
3683            const questionWildcardIndex = spec.indexOf("?");
3684            const starWildcardIndex = spec.indexOf("*");
3685            const lastDirectorySeperatorIndex = spec.lastIndexOf(directorySeparator);
3686            return {
3687                key: useCaseSensitiveFileNames ? match[0] : toFileNameLowerCase(match[0]),
3688                flags: (questionWildcardIndex !== -1 && questionWildcardIndex < lastDirectorySeperatorIndex)
3689                    || (starWildcardIndex !== -1 && starWildcardIndex < lastDirectorySeperatorIndex)
3690                    ? WatchDirectoryFlags.Recursive : WatchDirectoryFlags.None
3691            };
3692        }
3693        if (isImplicitGlob(spec.substring(spec.lastIndexOf(directorySeparator) + 1))) {
3694            return {
3695                key: removeTrailingDirectorySeparator(useCaseSensitiveFileNames ? spec : toFileNameLowerCase(spec)),
3696                flags: WatchDirectoryFlags.Recursive
3697            };
3698        }
3699        return undefined;
3700    }
3701
3702    /**
3703     * Determines whether a literal or wildcard file has already been included that has a higher
3704     * extension priority.
3705     *
3706     * @param file The path to the file.
3707     */
3708    function hasFileWithHigherPriorityExtension(file: string, literalFiles: ESMap<string, string>, wildcardFiles: ESMap<string, string>, extensions: readonly string[][], keyMapper: (value: string) => string) {
3709        const extensionGroup = forEach(extensions, group => fileExtensionIsOneOf(file, group) ? group : undefined);
3710        if (!extensionGroup) {
3711            return false;
3712        }
3713        for (const ext of extensionGroup) {
3714            if (fileExtensionIs(file, ext)) {
3715                return false;
3716            }
3717            const higherPriorityPath = keyMapper(changeExtension(file, ext));
3718            if (literalFiles.has(higherPriorityPath) || wildcardFiles.has(higherPriorityPath)) {
3719                if (ext === Extension.Dts && (fileExtensionIs(file, Extension.Js) || fileExtensionIs(file, Extension.Jsx))) {
3720                    // LEGACY BEHAVIOR: An off-by-one bug somewhere in the extension priority system for wildcard module loading allowed declaration
3721                    // files to be loaded alongside their js(x) counterparts. We regard this as generally undesirable, but retain the behavior to
3722                    // prevent breakage.
3723                    continue;
3724                }
3725                return true;
3726            }
3727        }
3728
3729        return false;
3730    }
3731
3732    /**
3733     * Removes files included via wildcard expansion with a lower extension priority that have
3734     * already been included.
3735     *
3736     * @param file The path to the file.
3737     */
3738    function removeWildcardFilesWithLowerPriorityExtension(file: string, wildcardFiles: ESMap<string, string>, extensions: readonly string[][], keyMapper: (value: string) => string) {
3739        const extensionGroup = forEach(extensions, group => fileExtensionIsOneOf(file, group) ? group : undefined);
3740        if (!extensionGroup) {
3741            return;
3742        }
3743        for (let i = extensionGroup.length - 1; i >= 0; i--) {
3744            const ext = extensionGroup[i];
3745            if (fileExtensionIs(file, ext)) {
3746                return;
3747            }
3748            const lowerPriorityPath = keyMapper(changeExtension(file, ext));
3749            wildcardFiles.delete(lowerPriorityPath);
3750        }
3751    }
3752
3753    /**
3754     * Produces a cleaned version of compiler options with personally identifying info (aka, paths) removed.
3755     * Also converts enum values back to strings.
3756     */
3757    /* @internal */
3758    export function convertCompilerOptionsForTelemetry(opts: CompilerOptions): CompilerOptions {
3759        const out: CompilerOptions = {};
3760        for (const key in opts) {
3761            if (hasProperty(opts, key)) {
3762                const type = getOptionFromName(key);
3763                if (type !== undefined) { // Ignore unknown options
3764                    out[key] = getOptionValueWithEmptyStrings(opts[key], type);
3765                }
3766            }
3767        }
3768        return out;
3769    }
3770
3771    function getOptionValueWithEmptyStrings(value: any, option: CommandLineOption): {} {
3772        switch (option.type) {
3773            case "object": // "paths". Can't get any useful information from the value since we blank out strings, so just return "".
3774                return "";
3775            case "string": // Could be any arbitrary string -- use empty string instead.
3776                return "";
3777            case "number": // Allow numbers, but be sure to check it's actually a number.
3778                return typeof value === "number" ? value : "";
3779            case "boolean":
3780                return typeof value === "boolean" ? value : "";
3781            case "list":
3782                const elementType = option.element;
3783                return isArray(value) ? value.map(v => getOptionValueWithEmptyStrings(v, elementType)) : "";
3784            default:
3785                return forEachEntry(option.type, (optionEnumValue, optionStringValue) => {
3786                    if (optionEnumValue === value) {
3787                        return optionStringValue;
3788                    }
3789                })!; // TODO: GH#18217
3790        }
3791    }
3792
3793
3794    function getDefaultValueForOption(option: CommandLineOption) {
3795        switch (option.type) {
3796            case "number":
3797                return 1;
3798            case "boolean":
3799                return true;
3800            case "string":
3801                const defaultValue = option.defaultValueDescription;
3802                return option.isFilePath ? `./${defaultValue && typeof defaultValue === "string" ? defaultValue : ""}` : "";
3803            case "list":
3804                return [];
3805            case "object":
3806                return {};
3807            default:
3808                const iterResult = option.type.keys().next();
3809                if (!iterResult.done) return iterResult.value;
3810                return Debug.fail("Expected 'option.type' to have entries.");
3811        }
3812    }
3813}
3814