From 157b8e7456a7a34faca007883bb620c8b599173b Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 15 Mar 2016 11:44:33 -0700 Subject: [PATCH] Add a new unittest for command line parsing for --lib --- Jakefile.js | 3 +- src/compiler/commandLineParser.ts | 15 +- src/compiler/types.ts | 3 +- tests/cases/unittests/commandLineParsing.ts | 160 ++++++++++++++++++++ tests/cases/unittests/tsconfigParsing.ts | 18 +-- 5 files changed, 182 insertions(+), 17 deletions(-) create mode 100644 tests/cases/unittests/commandLineParsing.ts diff --git a/Jakefile.js b/Jakefile.js index 2ffdfc37807..8932e6d976a 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -150,7 +150,8 @@ var harnessSources = harnessCoreSources.concat([ "reuseProgramStructure.ts", "cachingInServerLSHost.ts", "moduleResolution.ts", - "tsconfigParsing.ts" + "tsconfigParsing.ts", + "commandLineParsing.ts" ].map(function (f) { return path.join(unittestsDirectory, f); })).concat([ diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index ad0a8e7b3d1..024a202b2f9 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -518,7 +518,7 @@ namespace ts { } function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string) { - const map = >opt.type; + const map = opt.type; const key = (value || "").toLowerCase(); if (hasProperty(map, key)) { return map[key]; @@ -529,12 +529,15 @@ namespace ts { } } - function parseListTypeOption(opt: CommandLineOptionOfListType, value: string): number[] | string[] { - const values = (value || "").split(","); + function parseListTypeOption(opt: CommandLineOptionOfListType, value: string): (number | string)[] { + const values = (value || "").split(",").filter(v => { return v != undefined; }); switch (opt.element.type) { - case "number": return ts.map(values, parseInt); - case "string": return ts.map(values, v => v || ""); - default: return ts.map(values, v => parseCustomTypeOption(opt.element, v)); + case "number": + return ts.map(values, parseInt); + case "string": + return ts.map(values, v => v || ""); + default: + return ts.map(values, v => parseCustomTypeOption(opt.element, v)).filter(v => { return v != undefined; }); } } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index b1efda95a30..85febc5e968 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2437,6 +2437,7 @@ namespace ts { allowSyntheticDefaultImports?: boolean; allowJs?: boolean; noImplicitUseStrict?: boolean; + lib?: string[]; /* @internal */ stripInternal?: boolean; // Skip checking lib.d.ts to help speed up tests. @@ -2446,7 +2447,7 @@ namespace ts { list?: string[]; - [option: string]: string | number | boolean | TsConfigOnlyOptions | string[] | number[]; + [option: string]: string | number | boolean | TsConfigOnlyOptions | (string | number)[]; } export interface TypingOptions { diff --git a/tests/cases/unittests/commandLineParsing.ts b/tests/cases/unittests/commandLineParsing.ts new file mode 100644 index 00000000000..a77d1e56494 --- /dev/null +++ b/tests/cases/unittests/commandLineParsing.ts @@ -0,0 +1,160 @@ +/// +/// + +namespace ts { + describe('parseCommandLine', () => { + + function assertParseResult(commandLine: string[], expectedParsedCommandLine: ts.ParsedCommandLine) { + const parsed = ts.parseCommandLine(commandLine); + const parsedCompilerOptions = JSON.stringify(parsed.options); + const expectedCompilerOptions = JSON.stringify(expectedParsedCommandLine.options); + assert.equal(parsedCompilerOptions, expectedCompilerOptions); + + const parsedErrors = parsed.errors; + const expectedErrors = expectedParsedCommandLine.errors; + assert.isTrue(parsedErrors.length === expectedErrors.length, `Expected error: ${JSON.stringify(expectedErrors)}. Actual error: ${JSON.stringify(parsedErrors)}.`); + for (let i = 0; i < parsedErrors.length; ++i) { + const parsedError = parsedErrors[i]; + const expectedError = expectedErrors[i]; + assert.equal(parsedError.code, expectedError.code, `Expected error-code: ${JSON.stringify(expectedError.code)}. Actual error-code: ${JSON.stringify(parsedError.code)}.`); + assert.equal(parsedError.category, expectedError.category, `Expected error-category: ${JSON.stringify(expectedError.category)}. Actual error-category: ${JSON.stringify(parsedError.category)}.`); + } + + const parsedFileNames = parsed.fileNames; + const expectedFileNames = expectedParsedCommandLine.fileNames; + assert.isTrue(parsedFileNames.length === expectedFileNames.length, `Expected fileNames: [${JSON.stringify(expectedFileNames)}]. Actual fileNames: [${JSON.stringify(parsedFileNames)}].`); + for (let i = 0; i < parsedFileNames.length; ++i) { + const parsedFileName = parsedFileNames[i]; + const expectedFileName = expectedFileNames[i]; + assert.equal(parsedFileName, expectedFileName, `Expected filename: ${JSON.stringify(expectedFileName)}. Actual fileName: ${JSON.stringify(parsedFileName)}.`); + } + } + + it("Parse single option of library flag ", () => { + // --lib es6 0.ts + assertParseResult(["--lib", "es6", "0.ts"], + { + errors: [], + fileNames: ["0.ts"], + options: { + lib: ["lib.es6.d.ts"] + } + }); + }); + + it("Parse multiple options of library flags ", () => { + // --lib es5,es6.symbol.wellknown 0.ts + assertParseResult(["--lib", "es5,es6.symbol.wellknown", "0.ts"], + { + errors: [], + fileNames: ["0.ts"], + options: { + lib: ["lib.es5.d.ts", "lib.es6.symbol.wellknown.d.ts"] + } + }); + }); + + it("Parse unavailable options of library flags ", () => { + // --lib es5,es7 0.ts + assertParseResult(["--lib", "es5,es8", "0.ts"], + { + errors: [{ + messageText: "", + category: ts.Diagnostics.Arguments_for_library_option_must_be_Colon_0.category, + code: ts.Diagnostics.Arguments_for_library_option_must_be_Colon_0.code, + + file: undefined, + start: undefined, + length: undefined, + }], + fileNames: ["0.ts"], + options: { + lib: ["lib.es5.d.ts"] + } + }); + }); + + it("Parse incorrect form of library flags ", () => { + // --lib es5, es7 0.ts + assertParseResult(["--lib", "es5,", "es7", "0.ts"], + { + errors: [{ + messageText: "", + category: ts.Diagnostics.Arguments_for_library_option_must_be_Colon_0.category, + code: ts.Diagnostics.Arguments_for_library_option_must_be_Colon_0.code, + + file: undefined, + start: undefined, + length: undefined, + }], + fileNames: ["es7", "0.ts"], + options: { + lib: ["lib.es5.d.ts"] + } + }); + }); + + it("Parse multiple compiler flags with input files at the end", () => { + // --lib es5,es6.symbol.wellknown --target es5 0.ts + assertParseResult(["--lib", "es5,es6.symbol.wellknown", "--target", "es5", "0.ts"], + { + errors: [], + fileNames: ["0.ts"], + options: { + lib: ["lib.es5.d.ts", "lib.es6.symbol.wellknown.d.ts"], + target: ts.ScriptTarget.ES5, + } + }); + }); + + it("Parse multiple compiler flags with input files in the middle", () => { + // --module commonjs --target es5 0.ts --lib es5,es6.symbol.wellknown + assertParseResult(["--module", "commonjs", "--target", "es5", "0.ts", "--lib", "es5,es6.symbol.wellknown"], + { + errors: [], + fileNames: ["0.ts"], + options: { + module: ts.ModuleKind.CommonJS, + target: ts.ScriptTarget.ES5, + lib: ["lib.es5.d.ts", "lib.es6.symbol.wellknown.d.ts"], + } + }); + }); + + it("Parse incorrect form of multiple compiler flags with input files in the middle", () => { + // --module commonjs --target es5 0.ts --lib es5, es6.symbol.wellknown + assertParseResult(["--module", "commonjs", "--target", "es5", "0.ts", "--lib", "es5,", "es6.symbol.wellknown"], + { + errors: [{ + messageText: "", + category: ts.Diagnostics.Arguments_for_library_option_must_be_Colon_0.category, + code: ts.Diagnostics.Arguments_for_library_option_must_be_Colon_0.code, + + file: undefined, + start: undefined, + length: undefined, + }], + fileNames: ["0.ts", "es6.symbol.wellknown"], + options: { + module: ts.ModuleKind.CommonJS, + target: ts.ScriptTarget.ES5, + lib: ["lib.es5.d.ts"], + } + }); + }); + + it("Parse multiple library compiler flags ", () => { + // --module commonjs --target es5 --lib es5 0.ts --library es6.array,es6.symbol.wellknown + assertParseResult(["--module", "commonjs", "--target", "es5", "--lib", "es5", "0.ts", "--lib", "es6.array,es6.symbol.wellknown"], + { + errors: [], + fileNames: ["0.ts"], + options: { + module: ts.ModuleKind.CommonJS, + target: ts.ScriptTarget.ES5, + lib: ["lib.es6.array.d.ts", "lib.es6.symbol.wellknown.d.ts"], + } + }); + }); + }); +} diff --git a/tests/cases/unittests/tsconfigParsing.ts b/tests/cases/unittests/tsconfigParsing.ts index 118f15745cb..622c3abfff2 100644 --- a/tests/cases/unittests/tsconfigParsing.ts +++ b/tests/cases/unittests/tsconfigParsing.ts @@ -87,20 +87,20 @@ namespace ts { assertParseResult( `{ "compilerOptions": { - "library": "es5" + "lib": "es5" } - }`, { - config: { compilerOptions: { library: "es5" } } - }); - + }`, { + config: { compilerOptions: { lib: "es5" } } + }); + assertParseResult( `{ "compilerOptions": { - "library": "es5,es6" + "lib": "es5,es6" } - }`, { - config: { compilerOptions: { library: "es5,es6" } } - }); + }`, { + config: { compilerOptions: { lib: "es5,es6" } } + }); }); }); }