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
This commit is contained in:
Sheetal Nandi 2015-10-28 15:26:48 -07:00
parent ea57efa430
commit a8eb76fde1
5 changed files with 77 additions and 147 deletions

View file

@ -312,23 +312,31 @@ namespace ts {
if (hasProperty(optionNameMap, s)) {
let opt = optionNameMap[s];
if (opt.type === "boolean") {
// This needs to be treated specially since it doesnt accept argument
options[opt.name] = true;
// Check to see if no argument was provided (e.g. "--locale" is the last command-line argument).
if (!args[i] && opt.type !== "boolean") {
errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_expects_an_argument, opt.name));
}
else {
// Check to see if no argument was provided (e.g. "--locale" is the last command-line argument).
if (!args[i]) {
errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_expects_an_argument, opt.name));
}
let { hasError, value} = parseOption(opt, args[i++], options[opt.name]);
if (hasError) {
errors.push(createCompilerDiagnostic((<CommandLineOptionOfCustomType>opt).error));
}
else {
options[opt.name] = value;
}
switch (opt.type) {
case "number":
options[opt.name] = parseInt(args[i++]);
break;
case "boolean":
options[opt.name] = true;
break;
case "string":
options[opt.name] = args[i++] || "";
break;
// If not a primitive, the possible types are specified in what is effectively a map of options.
default:
let map = <Map<number>>opt.type;
let key = (args[i++] || "").toLowerCase();
if (hasProperty(map, key)) {
options[opt.name] = map[key];
}
else {
errors.push(createCompilerDiagnostic((<CommandLineOptionOfCustomType>opt).error));
}
}
}
else {
@ -375,68 +383,6 @@ namespace ts {
}
}
/**
* Parses non quoted strings separated by comma e.g. "a,b" would result in string array ["a", "b"]
* @param s
* @param existingValue
*/
function parseMultiValueStringArray(s: string, existingValue: string[]) {
let value: string[] = existingValue || [];
let hasError = false;
let currentString = "";
if (s) {
for (let i = 0; i < s.length; i++) {
let ch = s.charCodeAt(i);
if (ch === CharacterCodes.comma) {
pushCurrentStringToResult();
}
else {
currentString += s.charAt(i);
}
}
// push last string
pushCurrentStringToResult();
}
return { value, hasError };
function pushCurrentStringToResult() {
if (currentString) {
value.push(currentString);
currentString = "";
}
else {
hasError = true;
}
}
}
/* @internal */
export function parseOption(option: CommandLineOption, stringValue: string, existingValue: CompilerOptionsValueType) {
let hasError: boolean;
let value: CompilerOptionsValueType;
switch (option.type) {
case "number":
value = parseInt(stringValue);
break;
case "string":
value = stringValue || "";
break;
case "string[]":
return parseMultiValueStringArray(stringValue, <string[]>existingValue);
// If not a primitive, the possible types are specified in what is effectively a map of options.
default:
let map = <Map<number>>option.type;
let key = (stringValue || "").toLowerCase();
if (hasProperty(map, key)) {
value = map[key];
}
else {
hasError = true;
}
}
return { hasError, value };
}
/**
* Read tsconfig.json file
* @param fileName The path to the config file
@ -466,44 +412,11 @@ namespace ts {
}
}
/* @internal */
export function parseJsonCompilerOption(opt: CommandLineOption, jsonValue: any, errors: Diagnostic[]) {
let optType = opt.type;
let expectedType = typeof optType === "string" ? optType : "string";
let hasValidValue = true;
if (typeof jsonValue === expectedType) {
if (typeof optType !== "string") {
let key = jsonValue.toLowerCase();
if (hasProperty(optType, key)) {
jsonValue = optType[key];
}
else {
errors.push(createCompilerDiagnostic((<CommandLineOptionOfCustomType>opt).error));
jsonValue = 0;
}
}
}
// Check if the value asked was string[] and value provided was not string[]
else if (expectedType !== "string[]" ||
!(jsonValue instanceof Array) ||
forEach(<string[]>jsonValue, individualValue => typeof individualValue !== "string")) {
// Not expectedType
errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, opt.name, expectedType));
hasValidValue = false;
}
return {
value: <CompilerOptionsValueType>jsonValue,
hasValidValue
};
}
/**
* Parse the contents of a config file (tsconfig.json).
* @param json The contents of the config file to parse
* @param basePath A root directory to resolve relative path entries in the config
* file to. e.g. outDir
* @param existingOptions optional existing options to extend into
*/
export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}): ParsedCommandLine {
let errors: Diagnostic[] = [];
@ -526,16 +439,31 @@ namespace ts {
for (let id in jsonOptions) {
if (hasProperty(optionNameMap, id)) {
let opt = optionNameMap[id];
let { hasValidValue, value } = parseJsonCompilerOption(opt, jsonOptions[id], errors);
if (hasValidValue) {
let optType = opt.type;
let value = jsonOptions[id];
let expectedType = typeof optType === "string" ? optType : "string";
if (typeof value === expectedType) {
if (typeof optType !== "string") {
let key = value.toLowerCase();
if (hasProperty(optType, key)) {
value = optType[key];
}
else {
errors.push(createCompilerDiagnostic((<CommandLineOptionOfCustomType>opt).error));
value = 0;
}
}
if (opt.isFilePath) {
value = normalizePath(combinePaths(basePath, <string>value));
value = normalizePath(combinePaths(basePath, value));
if (value === "") {
value = ".";
}
}
options[opt.name] = value;
}
else {
errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, id, expectedType));
}
}
else {
errors.push(createCompilerDiagnostic(Diagnostics.Unknown_compiler_option_0, id));

View file

@ -588,8 +588,8 @@ namespace ts {
return;
function serializeCompilerOptions(options: CompilerOptions): Map<CompilerOptionsValueType> {
let result: Map<CompilerOptionsValueType> = {};
function serializeCompilerOptions(options: CompilerOptions): Map<string | number | boolean> {
let result: Map<string | number | boolean> = {};
let optionsNameMap = getOptionNameMap().optionNameMap;
for (let name in options) {
@ -606,8 +606,8 @@ namespace ts {
let optionDefinition = optionsNameMap[name.toLowerCase()];
if (optionDefinition) {
if (typeof optionDefinition.type === "string") {
// string, number, boolean or string[]
result[name] = <string | number | boolean | string[]>value;
// string, number or boolean
result[name] = value;
}
else {
// Enum

View file

@ -2095,11 +2095,9 @@ namespace ts {
// Skip checking lib.d.ts to help speed up tests.
/* @internal */ skipDefaultLibCheck?: boolean;
[option: string]: CompilerOptionsValueType;
[option: string]: string | number | boolean;
}
export type CompilerOptionsValueType = string | number | boolean | string[];
export const enum ModuleKind {
None = 0,
CommonJS = 1,
@ -2166,7 +2164,7 @@ namespace ts {
/* @internal */
export interface CommandLineOptionOfCustomType extends CommandLineOptionBase {
type: Map<number> | string; // an object literal mapping named values to actual values | string if it is string[]
type: Map<number>; // an object literal mapping named values to actual values
error: DiagnosticMessage; // The error given when the argument does not fit a customized 'type'
}

View file

@ -1006,17 +1006,23 @@ namespace Harness {
}
let option = getCommandLineOption(name);
if (option) {
if (option.type === "boolean") {
options[option.name] = value.toLowerCase() === "true";
}
else {
let { hasError, value: parsedValue } = ts.parseOption(option, value, options[option.name]);
if (hasError) {
throw new Error(`Unknown value '${value}' for compiler option '${name}'.`);
}
else {
options[option.name] = parsedValue;
}
switch (option.type) {
case "boolean":
options[option.name] = value.toLowerCase() === "true";
break;
case "string":
options[option.name] = value;
break;
// If not a primitive, the possible types are specified in what is effectively a map of options.
default:
let map = <ts.Map<number>>option.type;
let key = value.toLowerCase();
if (ts.hasProperty(map, key)) {
options[option.name] = map[key];
}
else {
throw new Error(`Unknown value '${value}' for compiler option '${name}'.`);
}
}
}
else {

View file

@ -3,7 +3,7 @@
/* tslint:disable:no-null */
// Test case is json of below type in tests/cases/project/
interface ProjectRunnerTestCase extends ts.CompilerOptions {
interface ProjectRunnerTestCase {
scenario: string;
projectRoot: string; // project where it lives - this also is the current directory when compiling
inputFiles: string[]; // list of input files to be given to program
@ -51,7 +51,7 @@ class ProjectRunner extends RunnerBase {
}
private runProjectTestCase(testCaseFileName: string) {
let testCase: ProjectRunnerTestCase;
let testCase: ProjectRunnerTestCase & ts.CompilerOptions;
let testFileText: string = null;
try {
@ -62,7 +62,7 @@ class ProjectRunner extends RunnerBase {
}
try {
testCase = <ProjectRunnerTestCase>JSON.parse(testFileText);
testCase = <ProjectRunnerTestCase & ts.CompilerOptions>JSON.parse(testFileText);
}
catch (e) {
assert(false, "Testcase: " + testCaseFileName + " does not contain valid json format: " + e.message);
@ -183,13 +183,7 @@ class ProjectRunner extends RunnerBase {
let outputFiles: BatchCompileProjectTestCaseEmittedFile[] = [];
let inputFiles = testCase.inputFiles;
let { errors, compilerOptions } = createCompilerOptions();
if (errors.length) {
return {
moduleKind,
errors
};
}
let compilerOptions = createCompilerOptions();
let configFileName: string;
if (compilerOptions.project) {
@ -240,7 +234,6 @@ class ProjectRunner extends RunnerBase {
module: moduleKind,
moduleResolution: ts.ModuleResolutionKind.Classic, // currently all tests use classic module resolution kind, this will change in the future
};
let errors: ts.Diagnostic[] = [];
// Set the values specified using json
let optionNameMap: ts.Map<ts.CommandLineOption> = {};
ts.forEach(ts.optionDeclarations, option => {
@ -249,14 +242,19 @@ class ProjectRunner extends RunnerBase {
for (let name in testCase) {
if (name !== "mapRoot" && name !== "sourceRoot" && ts.hasProperty(optionNameMap, name)) {
let option = optionNameMap[name];
let { hasValidValue, value } = ts.parseJsonCompilerOption(option, testCase[name], errors);
if (hasValidValue) {
compilerOptions[option.name] = value;
let optType = option.type;
let value = <any>testCase[name];
if (typeof optType !== "string") {
let key = value.toLowerCase();
if (ts.hasProperty(optType, key)) {
value = optType[key];
}
}
compilerOptions[option.name] = value;
}
}
return { errors, compilerOptions };
return compilerOptions;
}
function getFileNameInTheProjectTest(fileName: string): string {