Skip to content

Commit 164000b

Browse files
committed
Add showConfig tsc flag for debugging configs
1 parent e1fd0ea commit 164000b

File tree

4 files changed

+103
-0
lines changed

4 files changed

+103
-0
lines changed

src/compiler/commandLineParser.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,13 @@ namespace ts {
164164
category: Diagnostics.Command_line_Options,
165165
description: Diagnostics.Stylize_errors_and_messages_using_color_and_context_experimental
166166
},
167+
{
168+
name: "showConfig",
169+
type: "boolean",
170+
category: Diagnostics.Command_line_Options,
171+
isCommandLineOnly: true,
172+
description: Diagnostics.Print_the_final_configuration_instead_of_building
173+
},
167174

168175
// Basic
169176
{

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,10 @@
10071007
"category": "Error",
10081008
"code": 1349
10091009
},
1010+
"Print the final configuration instead of building.": {
1011+
"category": "Message",
1012+
"code": 1350
1013+
},
10101014

10111015
"Duplicate identifier '{0}'.": {
10121016
"category": "Error",

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4443,6 +4443,7 @@ namespace ts {
44434443
/*@internal*/ version?: boolean;
44444444
/*@internal*/ watch?: boolean;
44454445
esModuleInterop?: boolean;
4446+
/* @internal */ showConfig?: boolean;
44464447

44474448
[option: string]: CompilerOptionsValue | TsConfigSourceFile | undefined;
44484449
}

src/tsc/tsc.ts

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,50 @@ namespace ts {
132132
const commandLineOptions = commandLine.options;
133133
if (configFileName) {
134134
const configParseResult = parseConfigFileWithSystem(configFileName, commandLineOptions, sys, reportDiagnostic)!; // TODO: GH#18217
135+
if (commandLineOptions.showConfig) {
136+
const getCanonicalFileName = createGetCanonicalFileName(sys.useCaseSensitiveFileNames);
137+
const files = map(
138+
filter(
139+
configParseResult.fileNames,
140+
!configParseResult.configFileSpecs ? _ => false : matchesSpecs(
141+
configFileName,
142+
configParseResult.configFileSpecs.validatedIncludeSpecs,
143+
configParseResult.configFileSpecs.validatedExcludeSpecs
144+
)
145+
),
146+
f => getRelativePathFromFile(getNormalizedAbsolutePath(configFileName!, sys.getCurrentDirectory()), f, getCanonicalFileName)
147+
);
148+
const config = {
149+
compilerOptions: {
150+
...Object.keys(configParseResult.options).map((key) => {
151+
const value = configParseResult.options[key];
152+
const option = getOptionFromName(key);
153+
if (!option) {
154+
return [key, value] as [keyof CompilerOptions, {} | undefined];
155+
}
156+
return [key, unencodeCompilerOption(value, option, getCanonicalFileName)] as [keyof CompilerOptions, {} | undefined];
157+
}).reduce((prev, cur) => ({...prev, [cur[0]]: cur[1]}), {}),
158+
showConfig: undefined,
159+
configFile: undefined,
160+
configFilePath: undefined,
161+
help: undefined,
162+
init: undefined,
163+
listFiles: undefined,
164+
listEmittedFiles: undefined,
165+
project: undefined,
166+
},
167+
references: map(configParseResult.projectReferences, r => ({...r, path: r.originalPath, originalPath: undefined})),
168+
files: length(files) ? files : undefined,
169+
...(configParseResult.configFileSpecs ? {
170+
include: filterSameAsDefaultInclude(configParseResult.configFileSpecs.validatedIncludeSpecs),
171+
exclude: configParseResult.configFileSpecs.validatedExcludeSpecs
172+
} : {}),
173+
compilerOnSave: !!configParseResult.compileOnSave ? true : undefined
174+
}
175+
// tslint:disable-next-line:no-null
176+
sys.write(JSON.stringify(config, null, 4) + sys.newLine);
177+
return sys.exit(ExitStatus.Success);
178+
}
135179
updateReportDiagnostic(configParseResult.options);
136180
if (isWatchSet(configParseResult.options)) {
137181
reportWatchModeWithoutSysSupport();
@@ -153,6 +197,53 @@ namespace ts {
153197
}
154198
}
155199

200+
function unencodeCompilerOption(value: any, option: CommandLineOption, getCanonicalFileName: ReturnType<typeof createGetCanonicalFileName>): {} | undefined {
201+
switch (option.type) {
202+
case "object":
203+
case "number":
204+
case "boolean":
205+
return value;
206+
case "string":
207+
if (option.isFilePath) {
208+
return getRelativePathFromFile(sys.getCurrentDirectory(), getNormalizedAbsolutePath(value as string, sys.getCurrentDirectory()), getCanonicalFileName);
209+
}
210+
return value;
211+
case "list":
212+
const elementType = (option as CommandLineOptionOfListType).element;
213+
return isArray(value) ? value.map(v => unencodeCompilerOption(v, elementType, getCanonicalFileName)) : undefined;
214+
default:
215+
return forEachEntry(option.type, (optionEnumValue, optionStringValue) => {
216+
if (optionEnumValue === value) {
217+
return optionStringValue;
218+
}
219+
});
220+
}
221+
}
222+
223+
function filterSameAsDefaultInclude(specs: ReadonlyArray<string> | undefined) {
224+
if (!length(specs)) return undefined;
225+
if (length(specs) !== 1) return specs;
226+
if (specs![0] === "**/*") return undefined;
227+
return specs;
228+
}
229+
230+
function matchesSpecs(path: string, includeSpecs: ReadonlyArray<string> | undefined, excludeSpecs: ReadonlyArray<string> | undefined): (path: string) => boolean {
231+
if (!includeSpecs) return _ => false;
232+
const patterns = getFileMatcherPatterns(path, excludeSpecs, includeSpecs, sys.useCaseSensitiveFileNames, sys.getCurrentDirectory());
233+
const excludeRe = patterns.excludePattern && getRegexFromPattern(patterns.excludePattern, sys.useCaseSensitiveFileNames);
234+
const includeRe = patterns.includeFilePattern && getRegexFromPattern(patterns.includeFilePattern, sys.useCaseSensitiveFileNames);
235+
if (includeRe) {
236+
if (excludeRe) {
237+
return path => includeRe.test(path) && !excludeRe.test(path);
238+
}
239+
return path => includeRe.test(path);
240+
}
241+
if (excludeRe) {
242+
return path => !excludeRe.test(path);
243+
}
244+
return _ => false;
245+
}
246+
156247
function reportWatchModeWithoutSysSupport() {
157248
if (!sys.watchFile || !sys.watchDirectory) {
158249
reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch"));

0 commit comments

Comments
 (0)