Skip to content

Commit 071d790

Browse files
committed
Unify tsbuild option parsing with command line options parsing
1 parent 8e49fec commit 071d790

File tree

4 files changed

+99
-88
lines changed

4 files changed

+99
-88
lines changed

src/compiler/commandLineParser.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -815,10 +815,11 @@ namespace ts {
815815
}
816816

817817
function getOptionNameMap(): OptionNameMap {
818-
if (optionNameMapCache) {
819-
return optionNameMapCache;
820-
}
818+
return optionNameMapCache || (optionNameMapCache = createOptionNameMap(optionDeclarations));
819+
}
821820

821+
/*@internal*/
822+
export function createOptionNameMap(optionDeclarations: ReadonlyArray<CommandLineOption>): OptionNameMap {
822823
const optionNameMap = createMap<CommandLineOption>();
823824
const shortOptionNames = createMap<string>();
824825
forEach(optionDeclarations, option => {
@@ -828,8 +829,7 @@ namespace ts {
828829
}
829830
});
830831

831-
optionNameMapCache = { optionNameMap, shortOptionNames };
832-
return optionNameMapCache;
832+
return { optionNameMap, shortOptionNames };
833833
}
834834

835835
/* @internal */
@@ -979,7 +979,12 @@ namespace ts {
979979
}
980980

981981
/** @internal */
982-
export function getOptionFromName(optionName: string, allowShort = false): CommandLineOption | undefined {
982+
export function getOptionFromName(optionName: string, allowShort?: boolean): CommandLineOption | undefined {
983+
return getOptionDeclarationFromName(getOptionNameMap, optionName, allowShort);
984+
}
985+
986+
/*@internal*/
987+
export function getOptionDeclarationFromName(getOptionNameMap: () => OptionNameMap, optionName: string, allowShort = false): CommandLineOption | undefined {
983988
optionName = optionName.toLowerCase();
984989
const { optionNameMap, shortOptionNames } = getOptionNameMap();
985990
// Try to translate short option names to their full equivalents.

src/compiler/diagnosticMessages.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2900,6 +2900,11 @@
29002900
"category": "Error",
29012901
"code": 5071
29022902
},
2903+
"Unknown build option '{0}'.": {
2904+
"category": "Error",
2905+
"code": 5072
2906+
},
2907+
29032908

29042909
"Generates a sourcemap for each corresponding '.d.ts' file.": {
29052910
"category": "Message",

src/compiler/tsbuild.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,13 @@ namespace ts {
4747
dependencyMap: Mapper;
4848
}
4949

50-
interface BuildOptions {
51-
dry: boolean;
52-
force: boolean;
53-
verbose: boolean;
50+
export interface BuildOptions {
51+
dry?: boolean;
52+
force?: boolean;
53+
verbose?: boolean;
54+
/*@internal*/ clean?: boolean;
55+
/*@internal*/ watch?: boolean;
56+
/*@internal*/ help?: boolean;
5457
}
5558

5659
enum BuildResultFlags {

src/tsc/tsc.ts

Lines changed: 76 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ namespace ts {
6262
message: report,
6363
errorDiagnostic: d => reportDiag(d)
6464
};
65-
const result = performBuild(args.slice(1), createCompilerHost({}), buildHost, sys);
65+
const result = performBuild(args.slice(1), createCompilerHost({}), buildHost);
6666
// undefined = in watch mode, do not exit
6767
if (result !== undefined) {
6868
return sys.exit(result);
@@ -172,96 +172,94 @@ namespace ts {
172172
}
173173
}
174174

175-
const buildOpts: CommandLineOption[] = [
176-
{
177-
name: "verbose",
178-
shortName: "v",
179-
category: Diagnostics.Command_line_Options,
180-
description: Diagnostics.Enable_verbose_logging,
181-
type: "boolean"
182-
},
183-
{
184-
name: "dry",
185-
shortName: "d",
186-
category: Diagnostics.Command_line_Options,
187-
description: Diagnostics.Show_what_would_be_built_or_deleted_if_specified_with_clean,
188-
type: "boolean"
189-
},
190-
{
191-
name: "force",
192-
shortName: "f",
193-
category: Diagnostics.Command_line_Options,
194-
description: Diagnostics.Build_all_projects_including_those_that_appear_to_be_up_to_date,
195-
type: "boolean"
196-
},
197-
{
198-
name: "clean",
199-
category: Diagnostics.Command_line_Options,
200-
description: Diagnostics.Delete_the_outputs_of_all_projects,
201-
type: "boolean"
202-
},
203-
{
204-
name: "watch",
205-
category: Diagnostics.Command_line_Options,
206-
description: Diagnostics.Watch_input_files,
207-
type: "boolean"
208-
}
209-
];
210-
211-
function performBuild(args: string[], compilerHost: CompilerHost, buildHost: BuildHost, system?: System): number | undefined {
212-
let verbose = false;
213-
let dry = false;
214-
let force = false;
215-
let clean = false;
216-
let watch = false;
175+
function performBuild(args: string[], compilerHost: CompilerHost, buildHost: BuildHost): number | undefined {
176+
const buildOpts: CommandLineOption[] = [
177+
{
178+
name: "help",
179+
shortName: "h",
180+
type: "boolean",
181+
showInSimplifiedHelpView: true,
182+
category: Diagnostics.Command_line_Options,
183+
description: Diagnostics.Print_this_message,
184+
},
185+
{
186+
name: "help",
187+
shortName: "?",
188+
type: "boolean"
189+
},
190+
{
191+
name: "verbose",
192+
shortName: "v",
193+
category: Diagnostics.Command_line_Options,
194+
description: Diagnostics.Enable_verbose_logging,
195+
type: "boolean"
196+
},
197+
{
198+
name: "dry",
199+
shortName: "d",
200+
category: Diagnostics.Command_line_Options,
201+
description: Diagnostics.Show_what_would_be_built_or_deleted_if_specified_with_clean,
202+
type: "boolean"
203+
},
204+
{
205+
name: "force",
206+
shortName: "f",
207+
category: Diagnostics.Command_line_Options,
208+
description: Diagnostics.Build_all_projects_including_those_that_appear_to_be_up_to_date,
209+
type: "boolean"
210+
},
211+
{
212+
name: "clean",
213+
category: Diagnostics.Command_line_Options,
214+
description: Diagnostics.Delete_the_outputs_of_all_projects,
215+
type: "boolean"
216+
},
217+
{
218+
name: "watch",
219+
category: Diagnostics.Command_line_Options,
220+
description: Diagnostics.Watch_input_files,
221+
type: "boolean"
222+
}
223+
];
224+
let buildOptionNameMap: OptionNameMap | undefined;
225+
const returnBuildOptionNameMap = () => (buildOptionNameMap || (buildOptionNameMap = createOptionNameMap(buildOpts)));
217226

227+
const buildOptions: BuildOptions = {};
218228
const projects: string[] = [];
219229
for (const arg of args) {
220-
switch (arg.toLowerCase()) {
221-
case "-v":
222-
case "--verbose":
223-
verbose = true;
224-
continue;
225-
case "-d":
226-
case "--dry":
227-
dry = true;
228-
continue;
229-
case "-f":
230-
case "--force":
231-
force = true;
232-
continue;
233-
case "--clean":
234-
clean = true;
235-
continue;
236-
case "--watch":
237-
case "-w":
238-
watch = true;
239-
continue;
240-
241-
case "--?":
242-
case "-?":
243-
case "--help":
244-
printHelp(buildOpts, "--build ");
245-
return ExitStatus.Success;
230+
if (arg.charCodeAt(0) === CharacterCodes.minus) {
231+
const opt = getOptionDeclarationFromName(returnBuildOptionNameMap, arg.slice(arg.charCodeAt(1) === CharacterCodes.minus ? 2 : 1), /*allowShort*/ true);
232+
if (opt) {
233+
buildOptions[opt.name as keyof BuildOptions] = true;
234+
}
235+
else {
236+
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Unknown_build_option_0, arg));
237+
}
246238
}
247-
// Not a flag, parse as filename
248-
addProject(arg);
239+
else {
240+
// Not a flag, parse as filename
241+
addProject(arg);
242+
}
243+
}
244+
245+
if (buildOptions.help) {
246+
printHelp(buildOpts, "--build "); return ExitStatus.Success;
249247
}
250248

251249
// Nonsensical combinations
252-
if (clean && force) {
250+
if (buildOptions.clean && buildOptions.force) {
253251
buildHost.error(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "force");
254252
return ExitStatus.DiagnosticsPresent_OutputsSkipped;
255253
}
256-
if (clean && verbose) {
254+
if (buildOptions.clean && buildOptions.verbose) {
257255
buildHost.error(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "verbose");
258256
return ExitStatus.DiagnosticsPresent_OutputsSkipped;
259257
}
260-
if (clean && watch) {
258+
if (buildOptions.clean && buildOptions.watch) {
261259
buildHost.error(Diagnostics.Options_0_and_1_cannot_be_combined, "clean", "watch");
262260
return ExitStatus.DiagnosticsPresent_OutputsSkipped;
263261
}
264-
if (watch && dry) {
262+
if (buildOptions.watch && buildOptions.dry) {
265263
buildHost.error(Diagnostics.Options_0_and_1_cannot_be_combined, "watch", "dry");
266264
return ExitStatus.DiagnosticsPresent_OutputsSkipped;
267265
}
@@ -271,12 +269,12 @@ namespace ts {
271269
addProject(".");
272270
}
273271

274-
const builder = createSolutionBuilder(compilerHost, buildHost, projects, { dry, force, verbose }, system);
275-
if (clean) {
272+
const builder = createSolutionBuilder(compilerHost, buildHost, projects, buildOptions);
273+
if (buildOptions.clean) {
276274
return builder.cleanAllProjects();
277275
}
278276

279-
if (watch) {
277+
if (buildOptions.watch) {
280278
builder.buildAllProjects();
281279
builder.startWatching();
282280
return undefined;

0 commit comments

Comments
 (0)