Skip to content

Commit a8eb76f

Browse files
committed
Remove the logic for parsing compilation of comma seperated list of strings on command line
Also removed logic to accept multiple values for the option
1 parent ea57efa commit a8eb76f

5 files changed

Lines changed: 77 additions & 147 deletions

File tree

src/compiler/commandLineParser.ts

Lines changed: 41 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -312,23 +312,31 @@ namespace ts {
312312
if (hasProperty(optionNameMap, s)) {
313313
let opt = optionNameMap[s];
314314

315-
if (opt.type === "boolean") {
316-
// This needs to be treated specially since it doesnt accept argument
317-
options[opt.name] = true;
315+
// Check to see if no argument was provided (e.g. "--locale" is the last command-line argument).
316+
if (!args[i] && opt.type !== "boolean") {
317+
errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_expects_an_argument, opt.name));
318318
}
319-
else {
320-
// Check to see if no argument was provided (e.g. "--locale" is the last command-line argument).
321-
if (!args[i]) {
322-
errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_expects_an_argument, opt.name));
323-
}
324319

325-
let { hasError, value} = parseOption(opt, args[i++], options[opt.name]);
326-
if (hasError) {
327-
errors.push(createCompilerDiagnostic((<CommandLineOptionOfCustomType>opt).error));
328-
}
329-
else {
330-
options[opt.name] = value;
331-
}
320+
switch (opt.type) {
321+
case "number":
322+
options[opt.name] = parseInt(args[i++]);
323+
break;
324+
case "boolean":
325+
options[opt.name] = true;
326+
break;
327+
case "string":
328+
options[opt.name] = args[i++] || "";
329+
break;
330+
// If not a primitive, the possible types are specified in what is effectively a map of options.
331+
default:
332+
let map = <Map<number>>opt.type;
333+
let key = (args[i++] || "").toLowerCase();
334+
if (hasProperty(map, key)) {
335+
options[opt.name] = map[key];
336+
}
337+
else {
338+
errors.push(createCompilerDiagnostic((<CommandLineOptionOfCustomType>opt).error));
339+
}
332340
}
333341
}
334342
else {
@@ -375,68 +383,6 @@ namespace ts {
375383
}
376384
}
377385

378-
/**
379-
* Parses non quoted strings separated by comma e.g. "a,b" would result in string array ["a", "b"]
380-
* @param s
381-
* @param existingValue
382-
*/
383-
function parseMultiValueStringArray(s: string, existingValue: string[]) {
384-
let value: string[] = existingValue || [];
385-
let hasError = false;
386-
let currentString = "";
387-
if (s) {
388-
for (let i = 0; i < s.length; i++) {
389-
let ch = s.charCodeAt(i);
390-
if (ch === CharacterCodes.comma) {
391-
pushCurrentStringToResult();
392-
}
393-
else {
394-
currentString += s.charAt(i);
395-
}
396-
}
397-
// push last string
398-
pushCurrentStringToResult();
399-
}
400-
return { value, hasError };
401-
402-
function pushCurrentStringToResult() {
403-
if (currentString) {
404-
value.push(currentString);
405-
currentString = "";
406-
}
407-
else {
408-
hasError = true;
409-
}
410-
}
411-
}
412-
413-
/* @internal */
414-
export function parseOption(option: CommandLineOption, stringValue: string, existingValue: CompilerOptionsValueType) {
415-
let hasError: boolean;
416-
let value: CompilerOptionsValueType;
417-
switch (option.type) {
418-
case "number":
419-
value = parseInt(stringValue);
420-
break;
421-
case "string":
422-
value = stringValue || "";
423-
break;
424-
case "string[]":
425-
return parseMultiValueStringArray(stringValue, <string[]>existingValue);
426-
// If not a primitive, the possible types are specified in what is effectively a map of options.
427-
default:
428-
let map = <Map<number>>option.type;
429-
let key = (stringValue || "").toLowerCase();
430-
if (hasProperty(map, key)) {
431-
value = map[key];
432-
}
433-
else {
434-
hasError = true;
435-
}
436-
}
437-
return { hasError, value };
438-
}
439-
440386
/**
441387
* Read tsconfig.json file
442388
* @param fileName The path to the config file
@@ -466,44 +412,11 @@ namespace ts {
466412
}
467413
}
468414

469-
/* @internal */
470-
export function parseJsonCompilerOption(opt: CommandLineOption, jsonValue: any, errors: Diagnostic[]) {
471-
let optType = opt.type;
472-
let expectedType = typeof optType === "string" ? optType : "string";
473-
let hasValidValue = true;
474-
if (typeof jsonValue === expectedType) {
475-
if (typeof optType !== "string") {
476-
let key = jsonValue.toLowerCase();
477-
if (hasProperty(optType, key)) {
478-
jsonValue = optType[key];
479-
}
480-
else {
481-
errors.push(createCompilerDiagnostic((<CommandLineOptionOfCustomType>opt).error));
482-
jsonValue = 0;
483-
}
484-
}
485-
}
486-
// Check if the value asked was string[] and value provided was not string[]
487-
else if (expectedType !== "string[]" ||
488-
!(jsonValue instanceof Array) ||
489-
forEach(<string[]>jsonValue, individualValue => typeof individualValue !== "string")) {
490-
// Not expectedType
491-
errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, opt.name, expectedType));
492-
hasValidValue = false;
493-
}
494-
495-
return {
496-
value: <CompilerOptionsValueType>jsonValue,
497-
hasValidValue
498-
};
499-
}
500-
501415
/**
502416
* Parse the contents of a config file (tsconfig.json).
503417
* @param json The contents of the config file to parse
504418
* @param basePath A root directory to resolve relative path entries in the config
505419
* file to. e.g. outDir
506-
* @param existingOptions optional existing options to extend into
507420
*/
508421
export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}): ParsedCommandLine {
509422
let errors: Diagnostic[] = [];
@@ -526,16 +439,31 @@ namespace ts {
526439
for (let id in jsonOptions) {
527440
if (hasProperty(optionNameMap, id)) {
528441
let opt = optionNameMap[id];
529-
let { hasValidValue, value } = parseJsonCompilerOption(opt, jsonOptions[id], errors);
530-
if (hasValidValue) {
442+
let optType = opt.type;
443+
let value = jsonOptions[id];
444+
let expectedType = typeof optType === "string" ? optType : "string";
445+
if (typeof value === expectedType) {
446+
if (typeof optType !== "string") {
447+
let key = value.toLowerCase();
448+
if (hasProperty(optType, key)) {
449+
value = optType[key];
450+
}
451+
else {
452+
errors.push(createCompilerDiagnostic((<CommandLineOptionOfCustomType>opt).error));
453+
value = 0;
454+
}
455+
}
531456
if (opt.isFilePath) {
532-
value = normalizePath(combinePaths(basePath, <string>value));
457+
value = normalizePath(combinePaths(basePath, value));
533458
if (value === "") {
534459
value = ".";
535460
}
536461
}
537462
options[opt.name] = value;
538463
}
464+
else {
465+
errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, id, expectedType));
466+
}
539467
}
540468
else {
541469
errors.push(createCompilerDiagnostic(Diagnostics.Unknown_compiler_option_0, id));

src/compiler/tsc.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -588,8 +588,8 @@ namespace ts {
588588

589589
return;
590590

591-
function serializeCompilerOptions(options: CompilerOptions): Map<CompilerOptionsValueType> {
592-
let result: Map<CompilerOptionsValueType> = {};
591+
function serializeCompilerOptions(options: CompilerOptions): Map<string | number | boolean> {
592+
let result: Map<string | number | boolean> = {};
593593
let optionsNameMap = getOptionNameMap().optionNameMap;
594594

595595
for (let name in options) {
@@ -606,8 +606,8 @@ namespace ts {
606606
let optionDefinition = optionsNameMap[name.toLowerCase()];
607607
if (optionDefinition) {
608608
if (typeof optionDefinition.type === "string") {
609-
// string, number, boolean or string[]
610-
result[name] = <string | number | boolean | string[]>value;
609+
// string, number or boolean
610+
result[name] = value;
611611
}
612612
else {
613613
// Enum

src/compiler/types.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2095,11 +2095,9 @@ namespace ts {
20952095
// Skip checking lib.d.ts to help speed up tests.
20962096
/* @internal */ skipDefaultLibCheck?: boolean;
20972097

2098-
[option: string]: CompilerOptionsValueType;
2098+
[option: string]: string | number | boolean;
20992099
}
21002100

2101-
export type CompilerOptionsValueType = string | number | boolean | string[];
2102-
21032101
export const enum ModuleKind {
21042102
None = 0,
21052103
CommonJS = 1,
@@ -2166,7 +2164,7 @@ namespace ts {
21662164

21672165
/* @internal */
21682166
export interface CommandLineOptionOfCustomType extends CommandLineOptionBase {
2169-
type: Map<number> | string; // an object literal mapping named values to actual values | string if it is string[]
2167+
type: Map<number>; // an object literal mapping named values to actual values
21702168
error: DiagnosticMessage; // The error given when the argument does not fit a customized 'type'
21712169
}
21722170

src/harness/harness.ts

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1006,17 +1006,23 @@ namespace Harness {
10061006
}
10071007
let option = getCommandLineOption(name);
10081008
if (option) {
1009-
if (option.type === "boolean") {
1010-
options[option.name] = value.toLowerCase() === "true";
1011-
}
1012-
else {
1013-
let { hasError, value: parsedValue } = ts.parseOption(option, value, options[option.name]);
1014-
if (hasError) {
1015-
throw new Error(`Unknown value '${value}' for compiler option '${name}'.`);
1016-
}
1017-
else {
1018-
options[option.name] = parsedValue;
1019-
}
1009+
switch (option.type) {
1010+
case "boolean":
1011+
options[option.name] = value.toLowerCase() === "true";
1012+
break;
1013+
case "string":
1014+
options[option.name] = value;
1015+
break;
1016+
// If not a primitive, the possible types are specified in what is effectively a map of options.
1017+
default:
1018+
let map = <ts.Map<number>>option.type;
1019+
let key = value.toLowerCase();
1020+
if (ts.hasProperty(map, key)) {
1021+
options[option.name] = map[key];
1022+
}
1023+
else {
1024+
throw new Error(`Unknown value '${value}' for compiler option '${name}'.`);
1025+
}
10201026
}
10211027
}
10221028
else {

src/harness/projectsRunner.ts

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
/* tslint:disable:no-null */
44

55
// Test case is json of below type in tests/cases/project/
6-
interface ProjectRunnerTestCase extends ts.CompilerOptions {
6+
interface ProjectRunnerTestCase {
77
scenario: string;
88
projectRoot: string; // project where it lives - this also is the current directory when compiling
99
inputFiles: string[]; // list of input files to be given to program
@@ -51,7 +51,7 @@ class ProjectRunner extends RunnerBase {
5151
}
5252

5353
private runProjectTestCase(testCaseFileName: string) {
54-
let testCase: ProjectRunnerTestCase;
54+
let testCase: ProjectRunnerTestCase & ts.CompilerOptions;
5555

5656
let testFileText: string = null;
5757
try {
@@ -62,7 +62,7 @@ class ProjectRunner extends RunnerBase {
6262
}
6363

6464
try {
65-
testCase = <ProjectRunnerTestCase>JSON.parse(testFileText);
65+
testCase = <ProjectRunnerTestCase & ts.CompilerOptions>JSON.parse(testFileText);
6666
}
6767
catch (e) {
6868
assert(false, "Testcase: " + testCaseFileName + " does not contain valid json format: " + e.message);
@@ -183,13 +183,7 @@ class ProjectRunner extends RunnerBase {
183183

184184
let outputFiles: BatchCompileProjectTestCaseEmittedFile[] = [];
185185
let inputFiles = testCase.inputFiles;
186-
let { errors, compilerOptions } = createCompilerOptions();
187-
if (errors.length) {
188-
return {
189-
moduleKind,
190-
errors
191-
};
192-
}
186+
let compilerOptions = createCompilerOptions();
193187

194188
let configFileName: string;
195189
if (compilerOptions.project) {
@@ -240,7 +234,6 @@ class ProjectRunner extends RunnerBase {
240234
module: moduleKind,
241235
moduleResolution: ts.ModuleResolutionKind.Classic, // currently all tests use classic module resolution kind, this will change in the future
242236
};
243-
let errors: ts.Diagnostic[] = [];
244237
// Set the values specified using json
245238
let optionNameMap: ts.Map<ts.CommandLineOption> = {};
246239
ts.forEach(ts.optionDeclarations, option => {
@@ -249,14 +242,19 @@ class ProjectRunner extends RunnerBase {
249242
for (let name in testCase) {
250243
if (name !== "mapRoot" && name !== "sourceRoot" && ts.hasProperty(optionNameMap, name)) {
251244
let option = optionNameMap[name];
252-
let { hasValidValue, value } = ts.parseJsonCompilerOption(option, testCase[name], errors);
253-
if (hasValidValue) {
254-
compilerOptions[option.name] = value;
245+
let optType = option.type;
246+
let value = <any>testCase[name];
247+
if (typeof optType !== "string") {
248+
let key = value.toLowerCase();
249+
if (ts.hasProperty(optType, key)) {
250+
value = optType[key];
251+
}
255252
}
253+
compilerOptions[option.name] = value;
256254
}
257255
}
258256

259-
return { errors, compilerOptions };
257+
return compilerOptions;
260258
}
261259

262260
function getFileNameInTheProjectTest(fileName: string): string {

0 commit comments

Comments
 (0)