From 59d5df0a5664207d895353412f138c66c860f0d4 Mon Sep 17 00:00:00 2001 From: Bill Ticehurst Date: Thu, 10 Mar 2016 10:26:53 -0800 Subject: [PATCH 01/25] AllowJS files in tsserver when no project is given (cherry picked from commit 16d76561603478a3f4648ee483892e7807e88c49) --- src/server/editorServices.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 71907735b91..42a2bded6a5 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -1317,6 +1317,7 @@ namespace ts.server { else { const defaultOpts = ts.getDefaultCompilerOptions(); defaultOpts.allowNonTsExtensions = true; + defaultOpts.allowJs = true; this.setCompilerOptions(defaultOpts); } this.languageService = ts.createLanguageService(this.host, this.documentRegistry); From a75a02cc7b206fe4643d518d9903e036d8c172ae Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 10 Mar 2016 16:59:56 -0800 Subject: [PATCH 02/25] Fix issue writing too many files asynchronuslly --- scripts/ior.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/ior.ts b/scripts/ior.ts index f0c142a266c..eb67e62a275 100644 --- a/scripts/ior.ts +++ b/scripts/ior.ts @@ -76,8 +76,11 @@ module Commands { fs.mkdirSync(directoryPath); } } + function normalizeSlashes(path: string): string { + return path.replace(/\\/g, "/"); + } function transalatePath(outputFolder:string, path: string): string { - return outputFolder + directorySeparator + path.replace(":", ""); + return normalizeSlashes(outputFolder + directorySeparator + path.replace(":", "")); } function fileExists(path: string): boolean { return fs.existsSync(path); @@ -86,7 +89,7 @@ module Commands { var filename = transalatePath(outputFolder, f.path); ensureDirectoriesExist(getDirectoryPath(filename)); console.log("writing filename: " + filename); - fs.writeFile(filename, f.result.contents, (err) => { }); + fs.writeFileSync(filename, f.result.contents); }); console.log("Command: tsc "); From cde06b65858650ed6002e3bbc6ea92cfb42aed62 Mon Sep 17 00:00:00 2001 From: Anil Anar Date: Sun, 6 Mar 2016 16:08:37 +0100 Subject: [PATCH 03/25] Fix #7397: Remove error checks for noEmit and out* compiler options combined. --- src/compiler/program.ts | 19 +------------------ ...ompilerOptionsDeclarationAndNoEmit.symbols | 6 ++++++ .../compilerOptionsDeclarationAndNoEmit.types | 6 ++++++ .../compilerOptionsOutAndNoEmit.symbols | 6 ++++++ .../compilerOptionsOutAndNoEmit.types | 6 ++++++ .../compilerOptionsOutDirAndNoEmit.symbols | 6 ++++++ .../compilerOptionsOutDirAndNoEmit.types | 6 ++++++ .../compilerOptionsOutFileAndNoEmit.symbols | 6 ++++++ .../compilerOptionsOutFileAndNoEmit.types | 6 ++++++ .../compilerOptionsDeclarationAndNoEmit.ts | 6 ++++++ .../compiler/compilerOptionsOutAndNoEmit.ts | 6 ++++++ .../compilerOptionsOutDirAndNoEmit.ts | 6 ++++++ .../compilerOptionsOutFileAndNoEmit.ts | 6 ++++++ 13 files changed, 73 insertions(+), 18 deletions(-) create mode 100644 tests/baselines/reference/compilerOptionsDeclarationAndNoEmit.symbols create mode 100644 tests/baselines/reference/compilerOptionsDeclarationAndNoEmit.types create mode 100644 tests/baselines/reference/compilerOptionsOutAndNoEmit.symbols create mode 100644 tests/baselines/reference/compilerOptionsOutAndNoEmit.types create mode 100644 tests/baselines/reference/compilerOptionsOutDirAndNoEmit.symbols create mode 100644 tests/baselines/reference/compilerOptionsOutDirAndNoEmit.types create mode 100644 tests/baselines/reference/compilerOptionsOutFileAndNoEmit.symbols create mode 100644 tests/baselines/reference/compilerOptionsOutFileAndNoEmit.types create mode 100644 tests/cases/compiler/compilerOptionsDeclarationAndNoEmit.ts create mode 100644 tests/cases/compiler/compilerOptionsOutAndNoEmit.ts create mode 100644 tests/cases/compiler/compilerOptionsOutDirAndNoEmit.ts create mode 100644 tests/cases/compiler/compilerOptionsOutFileAndNoEmit.ts diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 495fbde5a99..60ec5cb4294 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1746,24 +1746,7 @@ namespace ts { } } - if (options.noEmit) { - if (options.out) { - programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noEmit", "out")); - } - - if (options.outFile) { - programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noEmit", "outFile")); - } - - if (options.outDir) { - programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noEmit", "outDir")); - } - - if (options.declaration) { - programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noEmit", "declaration")); - } - } - else if (options.allowJs && options.declaration) { + if (options.allowJs && options.declaration) { programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration")); } diff --git a/tests/baselines/reference/compilerOptionsDeclarationAndNoEmit.symbols b/tests/baselines/reference/compilerOptionsDeclarationAndNoEmit.symbols new file mode 100644 index 00000000000..4448defa95e --- /dev/null +++ b/tests/baselines/reference/compilerOptionsDeclarationAndNoEmit.symbols @@ -0,0 +1,6 @@ +=== tests/cases/compiler/a.ts === + +class c { +>c : Symbol(c, Decl(a.ts, 0, 0)) +} + diff --git a/tests/baselines/reference/compilerOptionsDeclarationAndNoEmit.types b/tests/baselines/reference/compilerOptionsDeclarationAndNoEmit.types new file mode 100644 index 00000000000..6f5caf9d48b --- /dev/null +++ b/tests/baselines/reference/compilerOptionsDeclarationAndNoEmit.types @@ -0,0 +1,6 @@ +=== tests/cases/compiler/a.ts === + +class c { +>c : c +} + diff --git a/tests/baselines/reference/compilerOptionsOutAndNoEmit.symbols b/tests/baselines/reference/compilerOptionsOutAndNoEmit.symbols new file mode 100644 index 00000000000..4448defa95e --- /dev/null +++ b/tests/baselines/reference/compilerOptionsOutAndNoEmit.symbols @@ -0,0 +1,6 @@ +=== tests/cases/compiler/a.ts === + +class c { +>c : Symbol(c, Decl(a.ts, 0, 0)) +} + diff --git a/tests/baselines/reference/compilerOptionsOutAndNoEmit.types b/tests/baselines/reference/compilerOptionsOutAndNoEmit.types new file mode 100644 index 00000000000..6f5caf9d48b --- /dev/null +++ b/tests/baselines/reference/compilerOptionsOutAndNoEmit.types @@ -0,0 +1,6 @@ +=== tests/cases/compiler/a.ts === + +class c { +>c : c +} + diff --git a/tests/baselines/reference/compilerOptionsOutDirAndNoEmit.symbols b/tests/baselines/reference/compilerOptionsOutDirAndNoEmit.symbols new file mode 100644 index 00000000000..4448defa95e --- /dev/null +++ b/tests/baselines/reference/compilerOptionsOutDirAndNoEmit.symbols @@ -0,0 +1,6 @@ +=== tests/cases/compiler/a.ts === + +class c { +>c : Symbol(c, Decl(a.ts, 0, 0)) +} + diff --git a/tests/baselines/reference/compilerOptionsOutDirAndNoEmit.types b/tests/baselines/reference/compilerOptionsOutDirAndNoEmit.types new file mode 100644 index 00000000000..6f5caf9d48b --- /dev/null +++ b/tests/baselines/reference/compilerOptionsOutDirAndNoEmit.types @@ -0,0 +1,6 @@ +=== tests/cases/compiler/a.ts === + +class c { +>c : c +} + diff --git a/tests/baselines/reference/compilerOptionsOutFileAndNoEmit.symbols b/tests/baselines/reference/compilerOptionsOutFileAndNoEmit.symbols new file mode 100644 index 00000000000..4448defa95e --- /dev/null +++ b/tests/baselines/reference/compilerOptionsOutFileAndNoEmit.symbols @@ -0,0 +1,6 @@ +=== tests/cases/compiler/a.ts === + +class c { +>c : Symbol(c, Decl(a.ts, 0, 0)) +} + diff --git a/tests/baselines/reference/compilerOptionsOutFileAndNoEmit.types b/tests/baselines/reference/compilerOptionsOutFileAndNoEmit.types new file mode 100644 index 00000000000..6f5caf9d48b --- /dev/null +++ b/tests/baselines/reference/compilerOptionsOutFileAndNoEmit.types @@ -0,0 +1,6 @@ +=== tests/cases/compiler/a.ts === + +class c { +>c : c +} + diff --git a/tests/cases/compiler/compilerOptionsDeclarationAndNoEmit.ts b/tests/cases/compiler/compilerOptionsDeclarationAndNoEmit.ts new file mode 100644 index 00000000000..41a89011020 --- /dev/null +++ b/tests/cases/compiler/compilerOptionsDeclarationAndNoEmit.ts @@ -0,0 +1,6 @@ +// @declaration: true +// @noEmit: true +// @fileName: a.ts + +class c { +} diff --git a/tests/cases/compiler/compilerOptionsOutAndNoEmit.ts b/tests/cases/compiler/compilerOptionsOutAndNoEmit.ts new file mode 100644 index 00000000000..126043826bd --- /dev/null +++ b/tests/cases/compiler/compilerOptionsOutAndNoEmit.ts @@ -0,0 +1,6 @@ +// @out: outDir +// @noEmit: true +// @fileName: a.ts + +class c { +} diff --git a/tests/cases/compiler/compilerOptionsOutDirAndNoEmit.ts b/tests/cases/compiler/compilerOptionsOutDirAndNoEmit.ts new file mode 100644 index 00000000000..fb701a52661 --- /dev/null +++ b/tests/cases/compiler/compilerOptionsOutDirAndNoEmit.ts @@ -0,0 +1,6 @@ +// @outDir: outDir +// @noEmit: true +// @fileName: a.ts + +class c { +} diff --git a/tests/cases/compiler/compilerOptionsOutFileAndNoEmit.ts b/tests/cases/compiler/compilerOptionsOutFileAndNoEmit.ts new file mode 100644 index 00000000000..2e75c0a976f --- /dev/null +++ b/tests/cases/compiler/compilerOptionsOutFileAndNoEmit.ts @@ -0,0 +1,6 @@ +// @outFile: a.js +// @noEmit: true +// @fileName: a.ts + +class c { +} From 8e35cdd52cda9156d642a5a1de43c97ad6b99061 Mon Sep 17 00:00:00 2001 From: Anil Anar Date: Sat, 12 Mar 2016 21:14:00 +0100 Subject: [PATCH 04/25] add missing conditional check --- src/compiler/program.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 60ec5cb4294..c0f769078e0 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1746,7 +1746,7 @@ namespace ts { } } - if (options.allowJs && options.declaration) { + if (!options.noEmit && options.allowJs && options.declaration) { programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "allowJs", "declaration")); } From e0a79bcd63d3d86f5502b30c4702d61c6ca77005 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Sun, 13 Mar 2016 15:31:55 -0700 Subject: [PATCH 05/25] don't check that return statement has expression in constructors --- src/compiler/checker.ts | 2 +- .../reference/noImplicitReturnInConstructors.js | 14 ++++++++++++++ .../noImplicitReturnInConstructors.symbols | 8 ++++++++ .../reference/noImplicitReturnInConstructors.types | 8 ++++++++ .../compiler/noImplicitReturnInConstructors.ts | 6 ++++++ 5 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/noImplicitReturnInConstructors.js create mode 100644 tests/baselines/reference/noImplicitReturnInConstructors.symbols create mode 100644 tests/baselines/reference/noImplicitReturnInConstructors.types create mode 100644 tests/cases/compiler/noImplicitReturnInConstructors.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cbda24e6a6e..09672f5c09c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13965,7 +13965,7 @@ namespace ts { } } } - else if (compilerOptions.noImplicitReturns && !isUnwrappedReturnTypeVoidOrAny(func, returnType)) { + else if (func.kind !== SyntaxKind.Constructor && compilerOptions.noImplicitReturns && !isUnwrappedReturnTypeVoidOrAny(func, returnType)) { // The function has a return type, but the return statement doesn't have an expression. error(node, Diagnostics.Not_all_code_paths_return_a_value); } diff --git a/tests/baselines/reference/noImplicitReturnInConstructors.js b/tests/baselines/reference/noImplicitReturnInConstructors.js new file mode 100644 index 00000000000..f1c4c8caa60 --- /dev/null +++ b/tests/baselines/reference/noImplicitReturnInConstructors.js @@ -0,0 +1,14 @@ +//// [noImplicitReturnInConstructors.ts] +class C { + constructor() { + return; + } +} + +//// [noImplicitReturnInConstructors.js] +var C = (function () { + function C() { + return; + } + return C; +}()); diff --git a/tests/baselines/reference/noImplicitReturnInConstructors.symbols b/tests/baselines/reference/noImplicitReturnInConstructors.symbols new file mode 100644 index 00000000000..326a390ead8 --- /dev/null +++ b/tests/baselines/reference/noImplicitReturnInConstructors.symbols @@ -0,0 +1,8 @@ +=== tests/cases/compiler/noImplicitReturnInConstructors.ts === +class C { +>C : Symbol(C, Decl(noImplicitReturnInConstructors.ts, 0, 0)) + + constructor() { + return; + } +} diff --git a/tests/baselines/reference/noImplicitReturnInConstructors.types b/tests/baselines/reference/noImplicitReturnInConstructors.types new file mode 100644 index 00000000000..304c7b5db50 --- /dev/null +++ b/tests/baselines/reference/noImplicitReturnInConstructors.types @@ -0,0 +1,8 @@ +=== tests/cases/compiler/noImplicitReturnInConstructors.ts === +class C { +>C : C + + constructor() { + return; + } +} diff --git a/tests/cases/compiler/noImplicitReturnInConstructors.ts b/tests/cases/compiler/noImplicitReturnInConstructors.ts new file mode 100644 index 00000000000..ac6f5145318 --- /dev/null +++ b/tests/cases/compiler/noImplicitReturnInConstructors.ts @@ -0,0 +1,6 @@ +// @noImplicitReturns: true +class C { + constructor() { + return; + } +} \ No newline at end of file From 2b2092b1a22e6c3e8c341b56b670c3ad7c5e4d59 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Mon, 14 Mar 2016 13:30:38 -0700 Subject: [PATCH 06/25] find module augmentations in preprocessor --- src/services/services.ts | 144 ++++++++---- .../unittests/services/preProcessFile.ts | 205 ++++++++++++++++-- 2 files changed, 282 insertions(+), 67 deletions(-) diff --git a/src/services/services.ts b/src/services/services.ts index a562ecf18cf..1c079b84027 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2147,8 +2147,23 @@ namespace ts { export function preProcessFile(sourceText: string, readImportFiles = true, detectJavaScriptImports = false): PreProcessedFileInfo { const referencedFiles: FileReference[] = []; const importedFiles: FileReference[] = []; - let ambientExternalModules: string[]; + let ambientExternalModules: { ref: FileReference, depth: number }[]; let isNoDefaultLib = false; + let braceNesting = 0; + // assume that text represent an external module if it contains at least one top level import/export + // ambient modules that are found inside external modules are interpreted as module augmentations + let externalModule = false; + + function nextToken() { + const token = scanner.scan(); + if (token === SyntaxKind.OpenBraceToken) { + braceNesting++; + } + else if (token === SyntaxKind.CloseBraceToken) { + braceNesting--; + } + return token; + } function processTripleSlashDirectives(): void { const commentRanges = getLeadingCommentRanges(sourceText, 0); @@ -2165,21 +2180,33 @@ namespace ts { }); } + function getFileReference() { + const file = scanner.getTokenValue(); + const pos = scanner.getTokenPos(); + return { + fileName: file, + pos: pos, + end: pos + file.length + }; + } + function recordAmbientExternalModule(): void { if (!ambientExternalModules) { ambientExternalModules = []; } - ambientExternalModules.push(scanner.getTokenValue()); + ambientExternalModules.push({ ref: getFileReference(), depth: braceNesting }); } function recordModuleName() { - const importPath = scanner.getTokenValue(); - const pos = scanner.getTokenPos(); - importedFiles.push({ - fileName: importPath, - pos: pos, - end: pos + importPath.length - }); + importedFiles.push(getFileReference()); + + markAsExternalModuleIfTopLevel(); + } + + function markAsExternalModuleIfTopLevel() { + if (braceNesting === 0) { + externalModule = true; + } } /** @@ -2189,9 +2216,9 @@ namespace ts { let token = scanner.getToken(); if (token === SyntaxKind.DeclareKeyword) { // declare module "mod" - token = scanner.scan(); + token = nextToken(); if (token === SyntaxKind.ModuleKeyword) { - token = scanner.scan(); + token = nextToken(); if (token === SyntaxKind.StringLiteral) { recordAmbientExternalModule(); } @@ -2208,7 +2235,8 @@ namespace ts { function tryConsumeImport(): boolean { let token = scanner.getToken(); if (token === SyntaxKind.ImportKeyword) { - token = scanner.scan(); + + token = nextToken(); if (token === SyntaxKind.StringLiteral) { // import "mod"; recordModuleName(); @@ -2216,9 +2244,9 @@ namespace ts { } else { if (token === SyntaxKind.Identifier || isKeyword(token)) { - token = scanner.scan(); + token = nextToken(); if (token === SyntaxKind.FromKeyword) { - token = scanner.scan(); + token = nextToken(); if (token === SyntaxKind.StringLiteral) { // import d from "mod"; recordModuleName(); @@ -2232,7 +2260,7 @@ namespace ts { } else if (token === SyntaxKind.CommaToken) { // consume comma and keep going - token = scanner.scan(); + token = nextToken(); } else { // unknown syntax @@ -2241,17 +2269,17 @@ namespace ts { } if (token === SyntaxKind.OpenBraceToken) { - token = scanner.scan(); + token = nextToken(); // consume "{ a as B, c, d as D}" clauses // make sure that it stops on EOF while (token !== SyntaxKind.CloseBraceToken && token !== SyntaxKind.EndOfFileToken) { - token = scanner.scan(); + token = nextToken(); } if (token === SyntaxKind.CloseBraceToken) { - token = scanner.scan(); + token = nextToken(); if (token === SyntaxKind.FromKeyword) { - token = scanner.scan(); + token = nextToken(); if (token === SyntaxKind.StringLiteral) { // import {a as A} from "mod"; // import d, {a, b as B} from "mod" @@ -2261,13 +2289,13 @@ namespace ts { } } else if (token === SyntaxKind.AsteriskToken) { - token = scanner.scan(); + token = nextToken(); if (token === SyntaxKind.AsKeyword) { - token = scanner.scan(); + token = nextToken(); if (token === SyntaxKind.Identifier || isKeyword(token)) { - token = scanner.scan(); + token = nextToken(); if (token === SyntaxKind.FromKeyword) { - token = scanner.scan(); + token = nextToken(); if (token === SyntaxKind.StringLiteral) { // import * as NS from "mod" // import d, * as NS from "mod" @@ -2288,19 +2316,20 @@ namespace ts { function tryConsumeExport(): boolean { let token = scanner.getToken(); if (token === SyntaxKind.ExportKeyword) { - token = scanner.scan(); + markAsExternalModuleIfTopLevel(); + token = nextToken(); if (token === SyntaxKind.OpenBraceToken) { - token = scanner.scan(); + token = nextToken(); // consume "{ a as B, c, d as D}" clauses // make sure it stops on EOF while (token !== SyntaxKind.CloseBraceToken && token !== SyntaxKind.EndOfFileToken) { - token = scanner.scan(); + token = nextToken(); } if (token === SyntaxKind.CloseBraceToken) { - token = scanner.scan(); + token = nextToken(); if (token === SyntaxKind.FromKeyword) { - token = scanner.scan(); + token = nextToken(); if (token === SyntaxKind.StringLiteral) { // export {a as A} from "mod"; // export {a, b as B} from "mod" @@ -2310,9 +2339,9 @@ namespace ts { } } else if (token === SyntaxKind.AsteriskToken) { - token = scanner.scan(); + token = nextToken(); if (token === SyntaxKind.FromKeyword) { - token = scanner.scan(); + token = nextToken(); if (token === SyntaxKind.StringLiteral) { // export * from "mod" recordModuleName(); @@ -2320,9 +2349,9 @@ namespace ts { } } else if (token === SyntaxKind.ImportKeyword) { - token = scanner.scan(); + token = nextToken(); if (token === SyntaxKind.Identifier || isKeyword(token)) { - token = scanner.scan(); + token = nextToken(); if (token === SyntaxKind.EqualsToken) { if (tryConsumeRequireCall(/*skipCurrentToken*/ true)) { return true; @@ -2338,11 +2367,11 @@ namespace ts { } function tryConsumeRequireCall(skipCurrentToken: boolean): boolean { - let token = skipCurrentToken ? scanner.scan() : scanner.getToken(); + let token = skipCurrentToken ? nextToken() : scanner.getToken(); if (token === SyntaxKind.RequireKeyword) { - token = scanner.scan(); + token = nextToken(); if (token === SyntaxKind.OpenParenToken) { - token = scanner.scan(); + token = nextToken(); if (token === SyntaxKind.StringLiteral) { // require("mod"); recordModuleName(); @@ -2356,17 +2385,17 @@ namespace ts { function tryConsumeDefine(): boolean { let token = scanner.getToken(); if (token === SyntaxKind.Identifier && scanner.getTokenValue() === "define") { - token = scanner.scan(); + token = nextToken(); if (token !== SyntaxKind.OpenParenToken) { return true; } - token = scanner.scan(); + token = nextToken(); if (token === SyntaxKind.StringLiteral) { // looks like define ("modname", ... - skip string literal and comma - token = scanner.scan(); + token = nextToken(); if (token === SyntaxKind.CommaToken) { - token = scanner.scan(); + token = nextToken(); } else { // unexpected token @@ -2380,7 +2409,7 @@ namespace ts { } // skip open bracket - token = scanner.scan(); + token = nextToken(); let i = 0; // scan until ']' or EOF while (token !== SyntaxKind.CloseBracketToken && token !== SyntaxKind.EndOfFileToken) { @@ -2390,7 +2419,7 @@ namespace ts { i++; } - token = scanner.scan(); + token = nextToken(); } return true; @@ -2400,7 +2429,7 @@ namespace ts { function processImports(): void { scanner.setText(sourceText); - scanner.scan(); + nextToken(); // Look for: // import "mod"; // import d from "mod" @@ -2427,7 +2456,7 @@ namespace ts { continue; } else { - scanner.scan(); + nextToken(); } } @@ -2438,7 +2467,34 @@ namespace ts { processImports(); } processTripleSlashDirectives(); - return { referencedFiles, importedFiles, isLibFile: isNoDefaultLib, ambientExternalModules }; + if (externalModule) { + // for external modules module all nested ambient modules are augmentations + if (ambientExternalModules) { + // move all detected ambient modules to imported files since they need to be resolved + for (const decl of ambientExternalModules) { + importedFiles.push(decl.ref); + } + } + return { referencedFiles, importedFiles, isLibFile: isNoDefaultLib, ambientExternalModules: undefined }; + } + else { + // for global scripts ambient modules still can have augmentations - look for ambient modules with depth > 0 + let ambientModuleNames: string[]; + if (ambientExternalModules) { + for (const decl of ambientExternalModules) { + if (decl.depth === 0) { + if (!ambientModuleNames) { + ambientModuleNames = []; + } + ambientModuleNames.push(decl.ref.fileName); + } + else { + importedFiles.push(decl.ref); + } + } + } + return { referencedFiles, importedFiles, isLibFile: isNoDefaultLib, ambientExternalModules: ambientModuleNames }; + } } /// Helpers diff --git a/tests/cases/unittests/services/preProcessFile.ts b/tests/cases/unittests/services/preProcessFile.ts index d9ddaf0f256..a648a3c4b26 100644 --- a/tests/cases/unittests/services/preProcessFile.ts +++ b/tests/cases/unittests/services/preProcessFile.ts @@ -1,6 +1,10 @@ /// /// +declare namespace chai.assert { + function deepEqual(actual: any, expected: any): void; +} + describe('PreProcessFile:', function () { function test(sourceText: string, readImportFile: boolean, detectJavaScriptImports: boolean, expectedPreProcess: ts.PreProcessedFileInfo): void { var resultPreProcess = ts.preProcessFile(sourceText, readImportFile, detectJavaScriptImports); @@ -15,34 +19,30 @@ describe('PreProcessFile:', function () { assert.equal(resultIsLibFile, expectedIsLibFile, "Pre-processed file has different value for isLibFile. Expected: " + expectedPreProcess + ". Actual: " + resultIsLibFile); - assert.equal(resultImportedFiles.length, expectedImportedFiles.length, - "Array's length of imported files does not match expected. Expected: " + expectedImportedFiles.length + ". Actual: " + resultImportedFiles.length); + checkFileReferenceList("Imported files", expectedImportedFiles, resultImportedFiles); + checkFileReferenceList("Referenced files", expectedReferencedFiles, resultReferencedFiles); - assert.equal(resultReferencedFiles.length, expectedReferencedFiles.length, - "Array's length of referenced files does not match expected. Expected: " + expectedReferencedFiles.length + ". Actual: " + resultReferencedFiles.length); + assert.deepEqual(resultPreProcess.ambientExternalModules, expectedPreProcess.ambientExternalModules); + } - for (var i = 0; i < expectedImportedFiles.length; ++i) { - var resultImportedFile = resultImportedFiles[i]; - var expectedImportedFile = expectedImportedFiles[i]; - - assert.equal(resultImportedFile.fileName, expectedImportedFile.fileName, "Imported file path does not match expected. Expected: " + expectedImportedFile.fileName + ". Actual: " + resultImportedFile.fileName + "."); - - assert.equal(resultImportedFile.pos, expectedImportedFile.pos, "Imported file position does not match expected. Expected: " + expectedImportedFile.pos + ". Actual: " + resultImportedFile.pos + "."); - - assert.equal(resultImportedFile.end, expectedImportedFile.end, "Imported file length does not match expected. Expected: " + expectedImportedFile.end + ". Actual: " + resultImportedFile.end + "."); + function checkFileReferenceList(kind: string, expected: ts.FileReference[], actual: ts.FileReference[]) { + if (expected === actual) { + return; } + if (!expected) { + assert.isTrue(false, `Expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`); + } + assert.equal(actual.length, expected.length, `[${kind}] Actual array's length does not match expected length. Expected files: ${JSON.stringify(expected)}, actual files: ${JSON.stringify(actual)}`); - for (var i = 0; i < expectedReferencedFiles.length; ++i) { - var resultReferencedFile = resultReferencedFiles[i]; - var expectedReferencedFile = expectedReferencedFiles[i]; - - assert.equal(resultReferencedFile.fileName, expectedReferencedFile.fileName, "Referenced file path does not match expected. Expected: " + expectedReferencedFile.fileName + ". Actual: " + resultReferencedFile.fileName + "."); - - assert.equal(resultReferencedFile.pos, expectedReferencedFile.pos, "Referenced file position does not match expected. Expected: " + expectedReferencedFile.pos + ". Actual: " + resultReferencedFile.pos + "."); - - assert.equal(resultReferencedFile.end, expectedReferencedFile.end, "Referenced file length does not match expected. Expected: " + expectedReferencedFile.end + ". Actual: " + resultReferencedFile.end + "."); + for (var i = 0; i < expected.length; ++i) { + var actualReference = actual[i]; + var expectedReference = expected[i]; + assert.equal(actualReference.fileName, expectedReference.fileName, `[${kind}] actual file path does not match expected. Expected: "${expectedReference.fileName}". Actual: "${actualReference.fileName}".`); + assert.equal(actualReference.pos, expectedReference.pos, `[${kind}] actual file start position does not match expected. Expected: "${expectedReference.pos}". Actual: "${actualReference.pos}".`); + assert.equal(actualReference.end, expectedReference.end, `[${kind}] actual file end pos does not match expected. Expected: "${expectedReference.end}". Actual: "${actualReference.end}".`); } } + describe("Test preProcessFiles,", function () { it("Correctly return referenced files from triple slash", function () { test("///" + "\n" + "///" + "\n" + "///" + "\n" + "///", @@ -183,7 +183,7 @@ describe('PreProcessFile:', function () { function foo() { } `, - /* readImports */ false, + /* readImports */ true, /* detectJavaScriptImports */ false, { @@ -262,6 +262,165 @@ describe('PreProcessFile:', function () { isLibFile: false }) }); + it("correctly handles augmentations in external modules - 1", () => { + test(` + declare module "../Observable" { + interface I {} + } + + export {} + `, + /*readImportFile*/ true, + /*detectJavaScriptImports*/ false, + { + referencedFiles: [], + importedFiles: [ + { "fileName": "../Observable", "pos": 28, "end": 41 } + ], + ambientExternalModules: undefined, + isLibFile: false + }) + }); + it("correctly handles augmentations in external modules - 2", () => { + test(` + declare module "../Observable" { + interface I {} + } + + import * as x from "m"; + `, + /*readImportFile*/ true, + /*detectJavaScriptImports*/ false, + { + referencedFiles: [], + importedFiles: [ + { "fileName": "m", "pos": 135, "end": 136 }, + { "fileName": "../Observable", "pos": 28, "end": 41 } + ], + ambientExternalModules: undefined, + isLibFile: false + }) + }); + it("correctly handles augmentations in external modules - 3", () => { + test(` + declare module "../Observable" { + interface I {} + } + + import m = require("m"); + `, + /*readImportFile*/ true, + /*detectJavaScriptImports*/ false, + { + referencedFiles: [], + importedFiles: [ + { "fileName": "m", "pos": 135, "end": 136 }, + { "fileName": "../Observable", "pos": 28, "end": 41 } + ], + ambientExternalModules: undefined, + isLibFile: false + }) + }); + it("correctly handles augmentations in external modules - 4", () => { + test(` + declare module "../Observable" { + interface I {} + } + namespace N {} + export = N; + `, + /*readImportFile*/ true, + /*detectJavaScriptImports*/ false, + { + referencedFiles: [], + importedFiles: [ + { "fileName": "../Observable", "pos": 28, "end": 41 } + ], + ambientExternalModules: undefined, + isLibFile: false + }) + }); + it("correctly handles augmentations in external modules - 5", () => { + test(` + declare module "../Observable" { + interface I {} + } + namespace N {} + export import IN = N; + `, + /*readImportFile*/ true, + /*detectJavaScriptImports*/ false, + { + referencedFiles: [], + importedFiles: [ + { "fileName": "../Observable", "pos": 28, "end": 41 } + ], + ambientExternalModules: undefined, + isLibFile: false + }) + }); + it("correctly handles augmentations in external modules - 6", () => { + test(` + declare module "../Observable" { + interface I {} + } + export let x = 1; + `, + /*readImportFile*/ true, + /*detectJavaScriptImports*/ false, + { + referencedFiles: [], + importedFiles: [ + { "fileName": "../Observable", "pos": 28, "end": 41 } + ], + ambientExternalModules: undefined, + isLibFile: false + }) + }); + it ("correctly handles augmentations in ambient external modules - 1", () => { + test(` + declare module "m1" { + export * from "m2"; + declare module "augmentation" { + interface I {} + } + } + `, + /*readImportFile*/ true, + /*detectJavaScriptImports*/ false, + { + referencedFiles: [], + importedFiles: [ + { "fileName": "m2", "pos": 65, "end": 67 }, + { "fileName": "augmentation", "pos": 102, "end": 114 } + ], + ambientExternalModules: ["m1"], + isLibFile: false + }); + }); + it ("correctly handles augmentations in ambient external modules - 2", () => { + test(` + namespace M { var x; } + import IM = M; + declare module "m1" { + export * from "m2"; + declare module "augmentation" { + interface I {} + } + } + `, + /*readImportFile*/ true, + /*detectJavaScriptImports*/ false, + { + referencedFiles: [], + importedFiles: [ + { "fileName": "m2", "pos": 127, "end": 129 }, + { "fileName": "augmentation", "pos": 164, "end": 176 } + ], + ambientExternalModules: ["m1"], + isLibFile: false + }); + }); }); }); From 3adab0cec3f6139e6513796282d333a1ef312bfe Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 9 Mar 2016 16:35:01 -0800 Subject: [PATCH 07/25] revert --- src/compiler/commandLineParser.ts | 82 +++++++++++++++++-------------- src/compiler/types.ts | 9 +++- 2 files changed, 53 insertions(+), 38 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index cf55f030c33..c0912394491 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -267,6 +267,16 @@ namespace ts { description: Diagnostics.Specifies_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6, error: Diagnostics.Argument_for_moduleResolution_option_must_be_node_or_classic, }, + { + name: "list", + elementType: { + "node": ModuleResolutionKind.NodeJs, + "classic": ModuleResolutionKind.Classic, + }, + type: "list", + description: Diagnostics.Specifies_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6, + error: Diagnostics.Argument_for_moduleResolution_option_must_be_node_or_classic, + }, { name: "allowUnusedLabels", type: "boolean", @@ -391,42 +401,7 @@ namespace ts { } if (hasProperty(optionNameMap, s)) { - const opt = optionNameMap[s]; - - if (opt.isTSConfigOnly) { - errors.push(createCompilerDiagnostic(Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file, opt.name)); - } - else { - // 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)); - } - - switch (opt.type) { - case "number": - options[opt.name] = parseInt(args[i]); - i++; - break; - case "boolean": - options[opt.name] = true; - break; - case "string": - options[opt.name] = args[i] || ""; - i++; - break; - // If not a primitive, the possible types are specified in what is effectively a map of options. - default: - let map = >opt.type; - let key = (args[i] || "").toLowerCase(); - i++; - if (hasProperty(map, key)) { - options[opt.name] = map[key]; - } - else { - errors.push(createCompilerDiagnostic((opt).error)); - } - } - } + parseString(optionNameMap[s], args[i]); } else { errors.push(createCompilerDiagnostic(Diagnostics.Unknown_compiler_option_0, s)); @@ -436,6 +411,41 @@ namespace ts { fileNames.push(s); } } + + function parseString(opt: CommandLineOption, value: string) { + // Check to see if no argument was provided (e.g. "--locale" is the last command-line argument). + if (!value && opt.type !== "boolean") { + errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_expects_an_argument, opt.name)); + } + + switch (opt.type) { + case "number": + options[opt.name] = parseInt(value); + i++; + break; + case "boolean": + options[opt.name] = true; + break; + case "string": + options[opt.name] = value || ""; + i++; + break; + case "list": + forEach((value || "").split(","), s => parseString(opt.name, opti ); + break; + // If not a primitive, the possible types are specified in what is effectively a map of options. + default: + let map = >opt.type; + let key = (value || "").toLowerCase(); + i++; + if (hasProperty(map, key)) { + options[opt.name] = map[key]; + } + else { + errors.push(createCompilerDiagnostic((opt).error)); + } + } + } } function parseResponseFile(fileName: string) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 155f5c1a77f..6273ea990df 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2529,7 +2529,7 @@ namespace ts { /* @internal */ export interface CommandLineOptionBase { name: string; - type: "string" | "number" | "boolean" | "object" | Map; // a value of a primitive type, or an object literal mapping named values to actual values + type: "string" | "number" | "boolean" | "object" | "list" | Map; // a value of a primitive type, or an object literal mapping named values to actual values isFilePath?: boolean; // True if option value is a path or fileName shortName?: string; // A short mnemonic for convenience - for instance, 'h' can be used in place of 'help' description?: DiagnosticMessage; // The message describing what the command line switch does @@ -2554,8 +2554,13 @@ namespace ts { type: "object"; } + export interface CommandlineOptionOfListType extends CommandLineOptionBase { + type: "list", + elementType: Map | "string" | "number"; + } + /* @internal */ - export type CommandLineOption = CommandLineOptionOfCustomType | CommandLineOptionOfPrimitiveType | TsConfigOnlyOption; + export type CommandLineOption = CommandLineOptionOfCustomType | CommandLineOptionOfPrimitiveType | TsConfigOnlyOption | CommandlineOptionOfListType; /* @internal */ export const enum CharacterCodes { From 0735f465f0e30444cda2771db6e3ab063abdd1fa Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 10 Mar 2016 11:14:29 -0800 Subject: [PATCH 08/25] Add support for list types consolidate typings options and commmandline option parsing from json files Fix --- src/compiler/commandLineParser.ts | 271 ++++++++++++++++-------------- src/compiler/types.ts | 13 +- 2 files changed, 149 insertions(+), 135 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index c0912394491..36aef619888 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -186,8 +186,8 @@ namespace ts { name: "rootDir", type: "string", isFilePath: true, - description: Diagnostics.Specifies_the_root_directory_of_input_files_Use_to_control_the_output_directory_structure_with_outDir, paramType: Diagnostics.LOCATION, + description: Diagnostics.Specifies_the_root_directory_of_input_files_Use_to_control_the_output_directory_structure_with_outDir, }, { name: "isolatedModules", @@ -268,14 +268,17 @@ namespace ts { error: Diagnostics.Argument_for_moduleResolution_option_must_be_node_or_classic, }, { - name: "list", - elementType: { - "node": ModuleResolutionKind.NodeJs, - "classic": ModuleResolutionKind.Classic, - }, + name: "lib", type: "list", + element: { + name: "lib", + type: { + "node": ModuleResolutionKind.NodeJs, + "classic": ModuleResolutionKind.Classic, + }, + error: Diagnostics.Argument_for_moduleResolution_option_must_be_node_or_classic, + }, description: Diagnostics.Specifies_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6, - error: Diagnostics.Argument_for_moduleResolution_option_must_be_node_or_classic, }, { name: "allowUnusedLabels", @@ -319,9 +322,13 @@ namespace ts { // this option can only be specified in tsconfig.json // use type = object to copy the value as-is name: "rootDirs", - type: "object", + type: "list", isTSConfigOnly: true, - isFilePath: true + element: { + name: "rootDirs", + type: "string", + isFilePath: true + } }, { name: "traceModuleResolution", @@ -345,6 +352,30 @@ namespace ts { } ]; + /* @internal */ + export let typingOptionDeclarations: CommandLineOption[] = [ + { + name: "enableAutoDiscovery", + type: "boolean", + }, + { + name: "include", + type: "list", + element: { + name: "include", + type: "string" + } + }, + { + name: "exclude", + type: "list", + element: { + name: "include", + type: "string" + } + } + ]; + /* @internal */ export interface OptionNameMap { optionNameMap: Map; @@ -401,7 +432,40 @@ namespace ts { } if (hasProperty(optionNameMap, s)) { - parseString(optionNameMap[s], args[i]); + const opt = optionNameMap[s]; + + if (opt.isTSConfigOnly) { + errors.push(createCompilerDiagnostic(Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file, opt.name)); + } + else { + // 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)); + } + + switch (opt.type) { + case "number": + options[opt.name] = parseInt(args[i]); + i++; + break; + case "boolean": + options[opt.name] = true; + break; + case "string": + options[opt.name] = args[i] || ""; + i++; + break; + case "list": + options[opt.name] = parseListTypeOption(opt, args[i]); + i++; + break; + // If not a primitive, the possible types are specified in what is effectively a map of options. + default: + options[opt.name] = parseCustomTypeOption(opt, args[i]); + i++; + break; + } + } } else { errors.push(createCompilerDiagnostic(Diagnostics.Unknown_compiler_option_0, s)); @@ -410,40 +474,25 @@ namespace ts { else { fileNames.push(s); } - } - function parseString(opt: CommandLineOption, value: string) { - // Check to see if no argument was provided (e.g. "--locale" is the last command-line argument). - if (!value && opt.type !== "boolean") { - errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_expects_an_argument, opt.name)); + function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string) { + const map = >opt.type; + const key = (value || "").toLowerCase(); + if (hasProperty(map, key)) { + return map[key]; + } + else { + errors.push(createCompilerDiagnostic(opt.error)); + } } - switch (opt.type) { - case "number": - options[opt.name] = parseInt(value); - i++; - break; - case "boolean": - options[opt.name] = true; - break; - case "string": - options[opt.name] = value || ""; - i++; - break; - case "list": - forEach((value || "").split(","), s => parseString(opt.name, opti ); - break; - // If not a primitive, the possible types are specified in what is effectively a map of options. - default: - let map = >opt.type; - let key = (value || "").toLowerCase(); - i++; - if (hasProperty(map, key)) { - options[opt.name] = map[key]; - } - else { - errors.push(createCompilerDiagnostic((opt).error)); - } + function parseListTypeOption(opt: CommandLineOptionOfListType, value: string): number[] | string[] { + const values = (value || "").split(","); + 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)); + } } } } @@ -512,7 +561,6 @@ namespace ts { } } - /** * Remove the comments from a json like text. * Comments can be single line comments (starting with # or //) or multiline comments using / * * / @@ -546,18 +594,20 @@ namespace ts { * file to. e.g. outDir */ export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}, configFileName?: string): ParsedCommandLine { - const { options: optionsFromJsonConfigFile, errors } = convertCompilerOptionsFromJson(json["compilerOptions"], basePath, configFileName); - + const errors: Diagnostic[] = []; + const optionsFromJsonConfigFile = convertOptionsFromJson(optionDeclarations, json["compilerOptions"], basePath, configFileName, errors); const options = extend(existingOptions, optionsFromJsonConfigFile); + const typingOptions = convertOptionsFromJson(typingOptionDeclarations, json["typingOptions"], basePath, configFileName, errors); + const fileNames = getFileNames(errors); return { options, - fileNames: getFileNames(), - typingOptions: getTypingOptions(), + fileNames, + typingOptions, errors }; - function getFileNames(): string[] { + function getFileNames(errors: Diagnostic[]): string[] { let fileNames: string[] = []; if (hasProperty(json, "files")) { if (json["files"] instanceof Array) { @@ -618,47 +668,24 @@ namespace ts { } return fileNames; } - - function getTypingOptions(): TypingOptions { - const options: TypingOptions = getBaseFileName(configFileName) === "jsconfig.json" - ? { enableAutoDiscovery: true, include: [], exclude: [] } - : { enableAutoDiscovery: false, include: [], exclude: [] }; - const jsonTypingOptions = json["typingOptions"]; - if (jsonTypingOptions) { - for (const id in jsonTypingOptions) { - if (id === "enableAutoDiscovery") { - if (typeof jsonTypingOptions[id] === "boolean") { - options.enableAutoDiscovery = jsonTypingOptions[id]; - } - else { - errors.push(createCompilerDiagnostic(Diagnostics.Unknown_typing_option_0, id)); - } - } - else if (id === "include") { - options.include = convertJsonOptionToStringArray(id, jsonTypingOptions[id], errors); - } - else if (id === "exclude") { - options.exclude = convertJsonOptionToStringArray(id, jsonTypingOptions[id], errors); - } - else { - errors.push(createCompilerDiagnostic(Diagnostics.Unknown_typing_option_0, id)); - } - } - } - return options; - } } export function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: CompilerOptions, errors: Diagnostic[] } { - const options: CompilerOptions = {}; const errors: Diagnostic[] = []; + const options = convertOptionsFromJson(optionDeclarations, jsonOptions, basePath, configFileName, errors); - if (configFileName && getBaseFileName(configFileName) === "jsconfig.json") { + if (configFileName && getBaseFileName(configFileName) === "jsconfig.json" && typeof options.allowJs === "undefined") { options.allowJs = true; } + return { options, errors }; + } + + function convertOptionsFromJson(optionDeclarations: CommandLineOption[], jsonOptions: any, basePath: string, configFileName: string, errors: Diagnostic[]): T { + const options = {} as T; + if (!jsonOptions) { - return { options, errors }; + return options; } const optionNameMap = arrayToMap(optionDeclarations, opt => opt.name); @@ -666,69 +693,53 @@ namespace ts { for (const id in jsonOptions) { if (hasProperty(optionNameMap, id)) { const opt = optionNameMap[id]; - const optType = opt.type; - let value = jsonOptions[id]; - const expectedType = typeof optType === "string" ? optType : "string"; - if (typeof value === expectedType) { - if (typeof optType !== "string") { - const key = value.toLowerCase(); - if (hasProperty(optType, key)) { - value = optType[key]; - } - else { - errors.push(createCompilerDiagnostic((opt).error)); - value = 0; - } - } - if (opt.isFilePath) { - switch (typeof value) { - case "string": - value = normalizePath(combinePaths(basePath, value)); - break; - case "object": - // "object" options with 'isFilePath' = true expected to be string arrays - value = convertJsonOptionToStringArray(opt.name, value, errors, (element) => normalizePath(combinePaths(basePath, element))); - break; - } - if (value === "") { - value = "."; - } - } - options[opt.name] = value; - } - else { - errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, id, expectedType)); - } + options[opt.name] = convertJsonOption(opt, jsonOptions[id], basePath, errors); } else { errors.push(createCompilerDiagnostic(Diagnostics.Unknown_compiler_option_0, id)); } } - return { options, errors }; + return options; } - function convertJsonOptionToStringArray(optionName: string, optionJson: any, errors: Diagnostic[], func?: (element: string) => string): string[] { - const items: string[] = []; - let invalidOptionType = false; - if (!isArray(optionJson)) { - invalidOptionType = true; + function convertJsonOption(opt: CommandLineOption, value: any, basePath: string, errors: Diagnostic[]): number | string | number[] | string[] { + const optType = opt.type; + const expectedType = typeof optType === "string" ? optType : "string"; + if (optType === "list" && isArray(value)) { + return convertJsonOptionOfListType(opt, value, basePath, errors); } - else { - for (const element of optionJson) { - if (typeof element === "string") { - const item = func ? func(element) : element; - items.push(item); - } - else { - invalidOptionType = true; - break; + else if (typeof value === expectedType) { + if (typeof optType !== "string") { + return convertJsonOptionOfCustomType(opt, value, errors); + } + else { + if (opt.isFilePath) { + value = normalizePath(combinePaths(basePath, value)); + if (value === "") { + value = "."; + } } } + return value; } - if (invalidOptionType) { - errors.push(createCompilerDiagnostic(Diagnostics.Option_0_should_have_array_of_strings_as_a_value, optionName)); + else { + errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, opt.name, expectedType)); } - return items; + } + + function convertJsonOptionOfCustomType(opt: CommandLineOptionOfCustomType, value: string, errors: Diagnostic[]) { + const key = value.toLowerCase(); + if (hasProperty(opt.type, key)) { + return opt.type[key]; + } + else { + errors.push(createCompilerDiagnostic(opt.error)); + return 0; + } + } + + function convertJsonOptionOfListType(option: CommandLineOptionOfListType, values: any[], basePath: string, errors: Diagnostic[]): any[] { + return ts.map(values, v => convertJsonOption(option.element, v, basePath, errors)); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 6273ea990df..2945fac0b09 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2444,7 +2444,9 @@ namespace ts { // Do not perform validation of output file name in transpile scenarios /* @internal */ suppressOutputPathCheck?: boolean; - [option: string]: string | number | boolean | TsConfigOnlyOptions; + list?: string[]; + + [option: string]: string | number | boolean | TsConfigOnlyOptions | string[] | number[]; } export interface TypingOptions { @@ -2554,13 +2556,14 @@ namespace ts { type: "object"; } - export interface CommandlineOptionOfListType extends CommandLineOptionBase { - type: "list", - elementType: Map | "string" | "number"; + /* @internal */ + export interface CommandLineOptionOfListType extends CommandLineOptionBase { + type: "list"; + element: CommandLineOptionOfCustomType | CommandLineOptionOfPrimitiveType; } /* @internal */ - export type CommandLineOption = CommandLineOptionOfCustomType | CommandLineOptionOfPrimitiveType | TsConfigOnlyOption | CommandlineOptionOfListType; + export type CommandLineOption = CommandLineOptionOfCustomType | CommandLineOptionOfPrimitiveType | TsConfigOnlyOption | CommandLineOptionOfListType; /* @internal */ export const enum CharacterCodes { From eb8282469712bb7d9d152370d0f44ea8ab34fcd8 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Mon, 14 Mar 2016 15:49:29 -0700 Subject: [PATCH 09/25] Chagne specifies -> specify --- src/compiler/commandLineParser.ts | 14 +++++++------- src/compiler/diagnosticMessages.json | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 36aef619888..fd0e42e60bf 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -63,7 +63,7 @@ namespace ts { { name: "reactNamespace", type: "string", - description: Diagnostics.Specifies_the_object_invoked_for_createElement_and_spread_when_targeting_react_JSX_emit + description: Diagnostics.Specify_the_object_invoked_for_createElement_and_spread_when_targeting_react_JSX_emit }, { name: "listFiles", @@ -77,7 +77,7 @@ namespace ts { name: "mapRoot", type: "string", isFilePath: true, - description: Diagnostics.Specifies_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations, + description: Diagnostics.Specify_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations, paramType: Diagnostics.LOCATION, }, { @@ -102,7 +102,7 @@ namespace ts { "crlf": NewLineKind.CarriageReturnLineFeed, "lf": NewLineKind.LineFeed }, - description: Diagnostics.Specifies_the_end_of_line_sequence_to_be_used_when_emitting_files_Colon_CRLF_dos_or_LF_unix, + description: Diagnostics.Specify_the_end_of_line_sequence_to_be_used_when_emitting_files_Colon_CRLF_dos_or_LF_unix, paramType: Diagnostics.NEWLINE, error: Diagnostics.Argument_for_newLine_option_must_be_CRLF_or_LF }, @@ -187,7 +187,7 @@ namespace ts { type: "string", isFilePath: true, paramType: Diagnostics.LOCATION, - description: Diagnostics.Specifies_the_root_directory_of_input_files_Use_to_control_the_output_directory_structure_with_outDir, + description: Diagnostics.Specify_the_root_directory_of_input_files_Use_to_control_the_output_directory_structure_with_outDir, }, { name: "isolatedModules", @@ -202,7 +202,7 @@ namespace ts { name: "sourceRoot", type: "string", isFilePath: true, - description: Diagnostics.Specifies_the_location_where_debugger_should_locate_TypeScript_files_instead_of_source_locations, + description: Diagnostics.Specify_the_location_where_debugger_should_locate_TypeScript_files_instead_of_source_locations, paramType: Diagnostics.LOCATION, }, { @@ -231,7 +231,7 @@ namespace ts { "es6": ScriptTarget.ES6, "es2015": ScriptTarget.ES2015, }, - description: Diagnostics.Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES2015_experimental, + description: Diagnostics.Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES2015, paramType: Diagnostics.VERSION, error: Diagnostics.Argument_for_target_option_must_be_ES3_ES5_or_ES2015 }, @@ -264,7 +264,7 @@ namespace ts { "node": ModuleResolutionKind.NodeJs, "classic": ModuleResolutionKind.Classic, }, - description: Diagnostics.Specifies_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6, + description: Diagnostics.Specify_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6, error: Diagnostics.Argument_for_moduleResolution_option_must_be_node_or_classic, }, { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 15a3a4e5ef4..a264285d95f 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2240,11 +2240,11 @@ "category": "Message", "code": 6002 }, - "Specifies the location where debugger should locate map files instead of generated locations.": { + "Specify the location where debugger should locate map files instead of generated locations.": { "category": "Message", "code": 6003 }, - "Specifies the location where debugger should locate TypeScript files instead of source locations.": { + "Specify the location where debugger should locate TypeScript files instead of source locations.": { "category": "Message", "code": 6004 }, @@ -2276,7 +2276,7 @@ "category": "Message", "code": 6011 }, - "Specify ECMAScript target version: 'ES3' (default), 'ES5', or 'ES2015' (experimental)": { + "Specify ECMAScript target version: 'ES3' (default), 'ES5', or 'ES2015'": { "category": "Message", "code": 6015 }, @@ -2408,7 +2408,7 @@ "category": "Message", "code": 6056 }, - "Specifies the root directory of input files. Use to control the output directory structure with --outDir.": { + "Specify the root directory of input files. Use to control the output directory structure with --outDir.": { "category": "Message", "code": 6058 }, @@ -2416,7 +2416,7 @@ "category": "Error", "code": 6059 }, - "Specifies the end of line sequence to be used when emitting files: 'CRLF' (dos) or 'LF' (unix).": { + "Specify the end of line sequence to be used when emitting files: 'CRLF' (dos) or 'LF' (unix).": { "category": "Message", "code": 6060 }, @@ -2448,7 +2448,7 @@ "category": "Message", "code": 6068 }, - "Specifies module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6).": { + "Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6).": { "category": "Message", "code": 6069 }, @@ -2504,7 +2504,7 @@ "category": "Message", "code": 6083 }, - "Specifies the object invoked for createElement and __spread when targeting 'react' JSX emit": { + "Specify the object invoked for createElement and __spread when targeting 'react' JSX emit": { "category": "Message", "code": 6084 }, From be0592da3bff1a144d1918ea63265b84ad73ffe8 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Mon, 14 Mar 2016 15:53:42 -0700 Subject: [PATCH 10/25] Add correct options for --lib --- src/compiler/commandLineParser.ts | 53 +++++++++++++++++++++++++--- src/compiler/diagnosticMessages.json | 9 ++++- src/compiler/types.ts | 4 +-- 3 files changed, 58 insertions(+), 8 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index fd0e42e60bf..ad0a8e7b3d1 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -273,12 +273,33 @@ namespace ts { element: { name: "lib", type: { - "node": ModuleResolutionKind.NodeJs, - "classic": ModuleResolutionKind.Classic, + // JavaScript only + "es5": "lib.es5.d.ts", + "es6": "lib.es6.d.ts", + "es7": "lib.es7.d.ts", + // Host only + "dom": "lib.dom.d.ts", + "webworker": "lib.webworker.d.ts", + "scripthost": "lib.scripthost.d.ts", + // ES6 Or ESNext By-feature options + "es6.array": "lib.es6.array.d.ts", + "es6.collection": "lib.es6.collection.d.ts", + "es6.function": "lib.es6.function.d.ts", + "es6.iterable": "lib.es6.iterable.d.ts", + "es6.math": "lib.es6.math.d.ts", + "es6.number": "lib.es6.number.d.ts", + "es6.object": "lib.es6.object.d.ts", + "es6.promise": "lib.es6.promise.d.ts", + "es6.proxy": "lib.es6.proxy.d.ts", + "es6.reflect": "lib.es6.reflect.d.ts", + "es6.regexp": "lib.es6.regexp.d.ts", + "es6.symbol": "lib.es6.symbol.d.ts", + "es6.symbol.wellknown": "lib.es6.symbol.wellknown.d.ts", + "es7.array.include": "lib.es7.array.include.d.ts" }, - error: Diagnostics.Argument_for_moduleResolution_option_must_be_node_or_classic, + error: Diagnostics.Arguments_for_library_option_must_be_Colon_0, }, - description: Diagnostics.Specifies_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6, + description: Diagnostics.Specify_library_to_be_included_in_the_compilation_Colon, }, { name: "allowUnusedLabels", @@ -402,6 +423,27 @@ namespace ts { return optionNameMapCache; } + // Cache between the name of commandline which is a custom type and a list of all possible custom types + const namesOfCustomTypeMapCache: Map = {}; + + /* @internal */ + export function getNamesOfCustomTypeFromCommandLineOptionsOfCustomType(opt: CommandLineOptionOfCustomType): string[] { + if (hasProperty(namesOfCustomTypeMapCache, opt.name)) { + return namesOfCustomTypeMapCache[opt.name]; + } + + const type = opt.type; + const namesOfType: string[] = []; + for (const typeName in type) { + if (hasProperty(type, typeName)) { + namesOfType.push(typeName); + } + } + + namesOfCustomTypeMapCache[opt.name] = namesOfType; + return namesOfCustomTypeMapCache[opt.name]; + } + export function parseCommandLine(commandLine: string[], readFile?: (path: string) => string): ParsedCommandLine { const options: CompilerOptions = {}; const fileNames: string[] = []; @@ -482,7 +524,8 @@ namespace ts { return map[key]; } else { - errors.push(createCompilerDiagnostic(opt.error)); + const suggestedOption = getNamesOfCustomTypeFromCommandLineOptionsOfCustomType(opt); + errors.push(createCompilerDiagnostic(opt.error, suggestedOption ? suggestedOption : undefined)); } } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index a264285d95f..c655faf4f3c 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2620,7 +2620,14 @@ "category": "Message", "code": 6112 }, - + "Specify library to be included in the compilation:": { + "category": "Message", + "code": 6113 + }, + "Arguments for library option must be: {0}": { + "category": "Error", + "code": 6114 + }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", "code": 7005 diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 2945fac0b09..b1efda95a30 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2531,7 +2531,7 @@ namespace ts { /* @internal */ export interface CommandLineOptionBase { name: string; - type: "string" | "number" | "boolean" | "object" | "list" | Map; // a value of a primitive type, or an object literal mapping named values to actual values + type: "string" | "number" | "boolean" | "object" | "list" | Map; // a value of a primitive type, or an object literal mapping named values to actual values isFilePath?: boolean; // True if option value is a path or fileName shortName?: string; // A short mnemonic for convenience - for instance, 'h' can be used in place of 'help' description?: DiagnosticMessage; // The message describing what the command line switch does @@ -2547,7 +2547,7 @@ namespace ts { /* @internal */ export interface CommandLineOptionOfCustomType extends CommandLineOptionBase { - type: Map; // an object literal mapping named values to actual values + type: Map; // an object literal mapping named values to actual values error: DiagnosticMessage; // The error given when the argument does not fit a customized 'type' } From c7df7770cd474bd884ca57b4f7450e1c02fcf6f2 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Fri, 4 Mar 2016 16:52:31 -0800 Subject: [PATCH 11/25] Add unittest for parsing --lib in tsconfig --- tests/cases/unittests/tsconfigParsing.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/tests/cases/unittests/tsconfigParsing.ts b/tests/cases/unittests/tsconfigParsing.ts index 3603d22f314..118f15745cb 100644 --- a/tests/cases/unittests/tsconfigParsing.ts +++ b/tests/cases/unittests/tsconfigParsing.ts @@ -82,5 +82,25 @@ namespace ts { it("returns object with error when json is invalid", () => { assertParseError("invalid"); }); + + it("returns object when users correctly specify library", () => { + assertParseResult( + `{ + "compilerOptions": { + "library": "es5" + } + }`, { + config: { compilerOptions: { library: "es5" } } + }); + + assertParseResult( + `{ + "compilerOptions": { + "library": "es5,es6" + } + }`, { + config: { compilerOptions: { library: "es5,es6" } } + }); + }); }); } From 1bc9157b764e019229e4bc41016a7c8147328f1e Mon Sep 17 00:00:00 2001 From: Bill Ticehurst Date: Fri, 11 Mar 2016 08:48:00 -0800 Subject: [PATCH 12/25] Port NavBar for JS improvements --- src/services/navigationBar.ts | 226 ++++++++++++++++++++++++++++++++-- 1 file changed, 217 insertions(+), 9 deletions(-) diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index f2e77fa69d3..effaa53bc10 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -3,6 +3,12 @@ /* @internal */ namespace ts.NavigationBar { export function getNavigationBarItems(sourceFile: SourceFile, compilerOptions: CompilerOptions): ts.NavigationBarItem[] { + // TODO: Handle JS files differently in 'navbar' calls for now, but ideally we should unify + // the 'navbar' and 'navto' logic for TypeScript and JavaScript. + if (isSourceFileJavaScript(sourceFile)) { + return getJsNavigationBarItems(sourceFile, compilerOptions); + } + // If the source file has any child items, then it included in the tree // and takes lexical ownership of all other top-level items. let hasGlobalNode = false; @@ -130,7 +136,7 @@ namespace ts.NavigationBar { return topLevelNodes; } - + function sortNodes(nodes: Node[]): Node[] { return nodes.slice(0).sort((n1: Declaration, n2: Declaration) => { if (n1.name && n2.name) { @@ -147,7 +153,7 @@ namespace ts.NavigationBar { } }); } - + function addTopLevelNodes(nodes: Node[], topLevelNodes: Node[]): void { nodes = sortNodes(nodes); @@ -178,8 +184,8 @@ namespace ts.NavigationBar { function isTopLevelFunctionDeclaration(functionDeclaration: FunctionLikeDeclaration) { if (functionDeclaration.kind === SyntaxKind.FunctionDeclaration) { - // A function declaration is 'top level' if it contains any function declarations - // within it. + // A function declaration is 'top level' if it contains any function declarations + // within it. if (functionDeclaration.body && functionDeclaration.body.kind === SyntaxKind.Block) { // Proper function declarations can only have identifier names if (forEach((functionDeclaration.body).statements, @@ -198,7 +204,7 @@ namespace ts.NavigationBar { return false; } - + function getItemsWorker(nodes: Node[], createItem: (n: Node) => ts.NavigationBarItem): ts.NavigationBarItem[] { let items: ts.NavigationBarItem[] = []; @@ -395,19 +401,19 @@ namespace ts.NavigationBar { let result: string[] = []; result.push(moduleDeclaration.name.text); - + while (moduleDeclaration.body && moduleDeclaration.body.kind === SyntaxKind.ModuleDeclaration) { moduleDeclaration = moduleDeclaration.body; result.push(moduleDeclaration.name.text); - } + } return result.join("."); } function createModuleItem(node: ModuleDeclaration): NavigationBarItem { let moduleName = getModuleName(node); - + let childItems = getItemsWorker(getChildNodes((getInnermostModule(node).body).statements), createChildItem); return getNavigationBarItem(moduleName, @@ -534,4 +540,206 @@ namespace ts.NavigationBar { return getTextOfNodeFromSourceText(sourceFile.text, node); } } -} \ No newline at end of file + + export function getJsNavigationBarItems(sourceFile: SourceFile, compilerOptions: CompilerOptions): NavigationBarItem[] { + const anonFnText = ""; + const anonClassText = ""; + let indent = 0; + + let rootName = isExternalModule(sourceFile) ? + "\"" + escapeString(getBaseFileName(removeFileExtension(normalizePath(sourceFile.fileName)))) + "\"" + : ""; + + let sourceFileItem = getNavBarItem(rootName, ScriptElementKind.moduleElement, [getNodeSpan(sourceFile)]); + let topItem = sourceFileItem; + + // Walk the whole file, because we want to also find function expressions - which may be in variable initializer, + // call arguments, expressions, etc... + forEachChild(sourceFile, visitNode); + + function visitNode(node: Node) { + const newItem = createNavBarItem(node); + + if (newItem) { + topItem.childItems.push(newItem); + } + + // Add a level if traversing into a container + if (newItem && (isFunctionLike(node) || isClassLike(node))) { + const lastTop = topItem; + indent++; + topItem = newItem; + forEachChild(node, visitNode); + topItem = lastTop; + indent--; + + // If the last item added was an anonymous function expression, and it had no children, discard it. + if (newItem && newItem.text === anonFnText && newItem.childItems.length === 0) { + topItem.childItems.pop(); + } + } + else { + forEachChild(node, visitNode); + } + } + + function createNavBarItem(node: Node) : NavigationBarItem { + switch (node.kind) { + case SyntaxKind.VariableDeclaration: + // Only add to the navbar if at the top-level of the file + // Note: "const" and "let" are also SyntaxKind.VariableDeclarations + if(node.parent/*VariableDeclarationList*/.parent/*VariableStatement*/ + .parent/*SourceFile*/.kind !== SyntaxKind.SourceFile) { + return undefined; + } + // If it is initialized with a function expression, handle it when we reach the function expression node + const varDecl = node as VariableDeclaration; + if (varDecl.initializer && (varDecl.initializer.kind === SyntaxKind.FunctionExpression || + varDecl.initializer.kind === SyntaxKind.ArrowFunction || + varDecl.initializer.kind === SyntaxKind.ClassExpression)) { + return undefined; + } + // Fall through + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + // "export default function().." looks just like a regular function/class declaration, except with the 'default' flag + const name = node.flags && (node.flags & NodeFlags.Default) && !(node as (Declaration)).name ? "default" : + node.kind === SyntaxKind.Constructor ? "constructor" : + declarationNameToString((node as (Declaration)).name); + return getNavBarItem(name, getScriptKindForElementKind(node.kind), [getNodeSpan(node)]); + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.ClassExpression: + return getDefineModuleItem(node) || getFunctionOrClassExpressionItem(node); + case SyntaxKind.MethodDeclaration: + const methodDecl = node as MethodDeclaration; + return getNavBarItem(declarationNameToString(methodDecl.name), + ScriptElementKind.memberFunctionElement, + [getNodeSpan(node)]); + case SyntaxKind.ExportAssignment: + // e.g. "export default " + return getNavBarItem("default", ScriptElementKind.variableElement, [getNodeSpan(node)]); + case SyntaxKind.ImportClause: // e.g. 'def' in: import def from 'mod' (in ImportDeclaration) + if (!(node as ImportClause).name) { + // No default import (this node is still a parent of named & namespace imports, which are handled below) + return undefined; + } + // fall through + case SyntaxKind.ImportSpecifier: // e.g. 'id' in: import {id} from 'mod' (in NamedImports, in ImportClause) + case SyntaxKind.NamespaceImport: // e.g. '* as ns' in: import * as ns from 'mod' (in ImportClause) + case SyntaxKind.ExportSpecifier: // e.g. 'a' or 'b' in: export {a, foo as b} from 'mod' + // Export specifiers are only interesting if they are reexports from another module, or renamed, else they are already globals + if (node.kind === SyntaxKind.ExportSpecifier) { + if (!(node.parent.parent as ExportDeclaration).moduleSpecifier && !(node as ExportSpecifier).propertyName) { + return undefined; + } + } + const decl = node as (ImportSpecifier | ImportClause | NamespaceImport | ExportSpecifier); + if (!decl.name) { + return undefined; + } + const declName = declarationNameToString(decl.name); + return getNavBarItem(declName, ScriptElementKind.constElement, [getNodeSpan(node)]); + default: + return undefined; + } + } + + function getNavBarItem(text: string, kind: string, spans: TextSpan[], kindModifiers = ScriptElementKindModifier.none): NavigationBarItem { + return { + text, kind, kindModifiers, spans, childItems: [], indent, bolded: false, grayed: false + } + } + + function getDefineModuleItem(node: Node): NavigationBarItem { + if (node.kind !== SyntaxKind.FunctionExpression && node.kind !== SyntaxKind.ArrowFunction) { + return undefined; + } + + // No match if this is not a call expression to an identifier named 'define' + if (node.parent.kind !== SyntaxKind.CallExpression) { + return undefined; + } + const callExpr = node.parent as CallExpression; + if (callExpr.expression.kind !== SyntaxKind.Identifier || callExpr.expression.getText() !== 'define') { + return undefined; + } + + // Return a module of either the given text in the first argument, or of the source file path + let defaultName = node.getSourceFile().fileName; + if (callExpr.arguments[0].kind === SyntaxKind.StringLiteral) { + defaultName = ((callExpr.arguments[0]) as StringLiteral).text; + } + return getNavBarItem(defaultName, ScriptElementKind.moduleElement, [getNodeSpan(node.parent)]); + } + + function getFunctionOrClassExpressionItem(node: Node): NavigationBarItem { + if (node.kind !== SyntaxKind.FunctionExpression && + node.kind !== SyntaxKind.ArrowFunction && + node.kind !== SyntaxKind.ClassExpression) { + return undefined; + } + + const fnExpr = node as FunctionExpression | ArrowFunction | ClassExpression; + let fnName: string; + if (fnExpr.name && getFullWidth(fnExpr.name) > 0) { + // The expression has an identifier, so use that as the name + fnName = declarationNameToString(fnExpr.name); + } + else { + // See if it is a var initializer. If so, use the var name. + if (fnExpr.parent.kind === SyntaxKind.VariableDeclaration) { + fnName = declarationNameToString((fnExpr.parent as VariableDeclaration).name); + } + // See if it is of the form " = function(){...}". If so, use the text from the left-hand side. + else if (fnExpr.parent.kind === SyntaxKind.BinaryExpression && + (fnExpr.parent as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) { + fnName = (fnExpr.parent as BinaryExpression).left.getText(); + if (fnName.length > 20) { + fnName = fnName.substring(0, 17) + "..."; + } + } + // See if it is a property assignment, and if so use the property name + else if (fnExpr.parent.kind === SyntaxKind.PropertyAssignment && + (fnExpr.parent as PropertyAssignment).name) { + fnName = (fnExpr.parent as PropertyAssignment).name.getText(); + } + else { + fnName = node.kind === SyntaxKind.ClassExpression ? anonClassText : anonFnText; + } + } + const scriptKind = node.kind === SyntaxKind.ClassExpression ? ScriptElementKind.classElement : ScriptElementKind.functionElement; + return getNavBarItem(fnName, scriptKind, [getNodeSpan(node)]); + } + + function getNodeSpan(node: Node) { + return node.kind === SyntaxKind.SourceFile + ? createTextSpanFromBounds(node.getFullStart(), node.getEnd()) + : createTextSpanFromBounds(node.getStart(), node.getEnd()); + } + + function getScriptKindForElementKind(kind: SyntaxKind) { + switch (kind) { + case SyntaxKind.VariableDeclaration: + return ScriptElementKind.variableElement; + case SyntaxKind.FunctionDeclaration: + return ScriptElementKind.functionElement; + case SyntaxKind.ClassDeclaration: + return ScriptElementKind.classElement; + case SyntaxKind.Constructor: + return ScriptElementKind.constructorImplementationElement; + case SyntaxKind.GetAccessor: + return ScriptElementKind.memberGetAccessorElement; + case SyntaxKind.SetAccessor: + return ScriptElementKind.memberSetAccessorElement; + default: + return "unknown"; + } + } + + return sourceFileItem.childItems; + } +} From 157b8e7456a7a34faca007883bb620c8b599173b Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 15 Mar 2016 11:44:33 -0700 Subject: [PATCH 13/25] 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" } } + }); }); }); } From f4e920e2c16209258dc9c4a341f9448ddbf2aed8 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 15 Mar 2016 11:45:21 -0700 Subject: [PATCH 14/25] Add unittest for testing convert compiler-options and typing-options --- Jakefile.js | 6 +- src/compiler/commandLineParser.ts | 21 ++--- .../convertCompilerOptionsFromJson.ts | 78 +++++++++++++++++++ .../unittests/convertTypingOptionsFromJson.ts | 44 +++++++++++ 4 files changed, 131 insertions(+), 18 deletions(-) create mode 100644 tests/cases/unittests/convertCompilerOptionsFromJson.ts create mode 100644 tests/cases/unittests/convertTypingOptionsFromJson.ts diff --git a/Jakefile.js b/Jakefile.js index 8932e6d976a..299ce1c77c4 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -146,12 +146,14 @@ var harnessSources = harnessCoreSources.concat([ "session.ts", "versionCache.ts", "convertToBase64.ts", - "transpile.ts", + "transpile.ts", "reuseProgramStructure.ts", "cachingInServerLSHost.ts", "moduleResolution.ts", "tsconfigParsing.ts", - "commandLineParsing.ts" + "commandLineParsing.ts", + "convertCompilerOptionsFromJson.ts", + "convertTypingOptionsFromJson.ts" ].map(function (f) { return path.join(unittestsDirectory, f); })).concat([ diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 024a202b2f9..d7d60fd2304 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -656,7 +656,7 @@ namespace ts { function getFileNames(errors: Diagnostic[]): string[] { let fileNames: string[] = []; if (hasProperty(json, "files")) { - if (json["files"] instanceof Array) { + if (isArray(json["files"])) { fileNames = map(json["files"], s => combinePaths(basePath, s)); } else { @@ -667,7 +667,7 @@ namespace ts { const filesSeen: Map = {}; let exclude: string[] = []; - if (json["exclude"] instanceof Array) { + if (isArray(json["exclude"])) { exclude = json["exclude"]; } else { @@ -716,18 +716,8 @@ namespace ts { } } - export function convertCompilerOptionsFromJson(jsonOptions: any, basePath: string, configFileName?: string): { options: CompilerOptions, errors: Diagnostic[] } { - const errors: Diagnostic[] = []; - const options = convertOptionsFromJson(optionDeclarations, jsonOptions, basePath, configFileName, errors); - - if (configFileName && getBaseFileName(configFileName) === "jsconfig.json" && typeof options.allowJs === "undefined") { - options.allowJs = true; - } - - return { options, errors }; - } - - function convertOptionsFromJson(optionDeclarations: CommandLineOption[], jsonOptions: any, basePath: string, configFileName: string, errors: Diagnostic[]): T { + /* @internal */ + export function convertOptionsFromJson(optionDeclarations: CommandLineOption[], jsonOptions: any, basePath: string, configFileName: string, errors: Diagnostic[]): T { const options = {} as T; if (!jsonOptions) { @@ -781,11 +771,10 @@ namespace ts { } else { errors.push(createCompilerDiagnostic(opt.error)); - return 0; } } function convertJsonOptionOfListType(option: CommandLineOptionOfListType, values: any[], basePath: string, errors: Diagnostic[]): any[] { - return ts.map(values, v => convertJsonOption(option.element, v, basePath, errors)); + return ts.map(values, v => convertJsonOption(option.element, v, basePath, errors)).filter(v => { return v != undefined; }); } } diff --git a/tests/cases/unittests/convertCompilerOptionsFromJson.ts b/tests/cases/unittests/convertCompilerOptionsFromJson.ts new file mode 100644 index 00000000000..bd572757631 --- /dev/null +++ b/tests/cases/unittests/convertCompilerOptionsFromJson.ts @@ -0,0 +1,78 @@ +/// +/// + +namespace ts { + describe('convertCompilerOptionsFromJson', () => { + function assertCompilerOptions(json: any, expectedResult: { compilerOptions: CompilerOptions, errors: Diagnostic[] }) { + const actualErrors: Diagnostic[] = []; + const actualCompilerOptions = convertOptionsFromJson(optionDeclarations, json["compilerOptions"], "/apath/", "tsconfig.json", actualErrors); + + const parsedCompilerOptions = JSON.stringify(actualCompilerOptions); + const expectedCompilerOptions = JSON.stringify(expectedResult.compilerOptions); + assert.equal(parsedCompilerOptions, expectedCompilerOptions); + + const expectedErrors = expectedResult.errors; + assert.isTrue(expectedResult.errors.length === actualErrors.length, `Expected error: ${JSON.stringify(expectedResult.errors)}. Actual error: ${JSON.stringify(actualErrors)}.`); + for (let i = 0; i < actualErrors.length; ++i) { + const actualError = actualErrors[i]; + const expectedError = expectedErrors[i]; + assert.equal(actualError.code, expectedError.code, `Expected error-code: ${JSON.stringify(expectedError.code)}. Actual error-code: ${JSON.stringify(actualError.code)}.`); + assert.equal(actualError.category, expectedError.category, `Expected error-category: ${JSON.stringify(expectedError.category)}. Actual error-category: ${JSON.stringify(actualError.category)}.`); + } + } + + const correctFormatOptions = { + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "noImplicitAny": false, + "sourceMap": false, + "lib": ["es5", "es6.array", "es6.symbol"] + } + } + + const incorrectLibOption = { + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "noImplicitAny": false, + "sourceMap": false, + "lib": ["es5", "es6.array", "es8"] + } + } + + it("Convert correctly format JSON to compiler-options ", () => { + assertCompilerOptions(correctFormatOptions, { + compilerOptions: { + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, + noImplicitAny: false, + sourceMap: false, + lib: ["lib.es5.d.ts", "lib.es6.array.d.ts", "lib.es6.symbol.d.ts"] + }, + errors: [] + }); + }); + + it("Convert incorrectly option of libs to compiler-options ", () => { + debugger; + assertCompilerOptions(incorrectLibOption, { + compilerOptions: { + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, + noImplicitAny: false, + sourceMap: false, + lib: ["lib.es5.d.ts", "lib.es6.array.d.ts"] + }, + errors: [{ + file: undefined, + start: 0, + length: 0, + messageText: "", + code: Diagnostics.Arguments_for_library_option_must_be_Colon_0.code, + category: Diagnostics.Arguments_for_library_option_must_be_Colon_0.category + }] + }); + }); + }); +} diff --git a/tests/cases/unittests/convertTypingOptionsFromJson.ts b/tests/cases/unittests/convertTypingOptionsFromJson.ts new file mode 100644 index 00000000000..89a44836e45 --- /dev/null +++ b/tests/cases/unittests/convertTypingOptionsFromJson.ts @@ -0,0 +1,44 @@ +/// +/// + +namespace ts { + describe('convertTypingOptionsFromJson', () => { + function assertTypingOptions(json: any, expectedResult: { typingOptions: TypingOptions, errors: Diagnostic[] }) { + const actualErrors: Diagnostic[] = []; + const actualTypingOptions = convertOptionsFromJson(typingOptionDeclarations, json["typingOptions"], "/apath/", "tsconfig.json", actualErrors); + + const parsedTypingOptions = JSON.stringify(actualTypingOptions); + const expectedTypingOptions = JSON.stringify(expectedResult.typingOptions); + assert.equal(parsedTypingOptions, parsedTypingOptions); + + const expectedErrors = expectedResult.errors; + assert.isTrue(expectedResult.errors.length === actualErrors.length, `Expected error: ${JSON.stringify(expectedResult.errors)}. Actual error: ${JSON.stringify(actualErrors)}.`); + for (let i = 0; i < actualErrors.length; ++i) { + const actualError = actualErrors[i]; + const expectedError = expectedErrors[i]; + assert.equal(actualError.code, expectedError.code, `Expected error-code: ${JSON.stringify(expectedError.code)}. Actual error-code: ${JSON.stringify(actualError.code)}.`); + assert.equal(actualError.category, expectedError.category, `Expected error-category: ${JSON.stringify(expectedError.category)}. Actual error-category: ${JSON.stringify(actualError.category)}.`); + } + } + + const correctFormatOptions = { + "typingOptions": { + "enableAutoDiscovery": true, + "include": ["0.d.ts", "1.d.ts"], + "exclude": ["0.js", "1.js"] + } + } + + it("Convert correctly format JSON to compiler-options ", () => { + debugger; + assertTypingOptions(correctFormatOptions, { + typingOptions: { + enableAutoDiscovery: true, + include: ["/apath/0.d.ts", "/apath/1.d.ts"], + exclude: ["/apath/0.js", "/apath/1.js"] + }, + errors: [] + }); + }); + }); +} From 821723b83958d3e1799e40e9918f8c7b95af5ccb Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 15 Mar 2016 12:18:17 -0700 Subject: [PATCH 15/25] RWC runner fixes for reading json files --- src/harness/harness.ts | 2 +- src/harness/rwcRunner.ts | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 4020bcd821b..ddaca642094 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -876,7 +876,7 @@ namespace Harness { useCaseSensitiveFileNames: () => useCaseSensitiveFileNames, getNewLine: () => newLine, fileExists: fileName => getSourceFile(fileName, ts.ScriptTarget.ES5) !== undefined, - readFile: (fileName: string): string => { throw new Error("NotYetImplemented"); } + readFile: (fileName: string): string => { return Harness.IO.readFile(fileName); } }; } diff --git a/src/harness/rwcRunner.ts b/src/harness/rwcRunner.ts index ce570a7d6ad..11ed5e7a680 100644 --- a/src/harness/rwcRunner.ts +++ b/src/harness/rwcRunner.ts @@ -31,22 +31,20 @@ namespace RWC { let otherFiles: Harness.Compiler.TestFile[] = []; let compilerResult: Harness.Compiler.CompilerResult; let compilerOptions: ts.CompilerOptions; - let baselineOpts: Harness.Baseline.BaselineOptions = { + const baselineOpts: Harness.Baseline.BaselineOptions = { Subfolder: "rwc", Baselinefolder: "internal/baselines" }; - let baseName = /(.*)\/(.*).json/.exec(ts.normalizeSlashes(jsonPath))[2]; + const baseName = /(.*)\/(.*).json/.exec(ts.normalizeSlashes(jsonPath))[2]; let currentDirectory: string; let useCustomLibraryFile: boolean; after(() => { // Mocha holds onto the closure environment of the describe callback even after the test is done. // Therefore we have to clean out large objects after the test is done. - inputFiles = undefined; - otherFiles = undefined; + inputFiles = []; + otherFiles = []; compilerResult = undefined; compilerOptions = undefined; - baselineOpts = undefined; - baseName = undefined; currentDirectory = undefined; // useCustomLibraryFile is a flag specified in the json object to indicate whether to use built/local/lib.d.ts // or to use lib.d.ts inside the json object. If the flag is true, use the lib.d.ts inside json file From 8bf9da614f80246211e4b0fc5f65fa1df95edd57 Mon Sep 17 00:00:00 2001 From: Chuck Jazdzewski Date: Tue, 15 Mar 2016 13:25:18 -0700 Subject: [PATCH 16/25] Adding sourceFiles to the Program emit callback This implements #7438 --- src/compiler/emitter.ts | 8 ++++---- src/compiler/program.ts | 2 +- src/compiler/types.ts | 2 +- src/compiler/utilities.ts | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 14f0e5bdf94..e5498d24576 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -604,7 +604,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge write(`//# sourceMappingURL=${sourceMappingURL}`); } - writeEmittedFiles(writer.getText(), jsFilePath, sourceMapFilePath, /*writeByteOrderMark*/ compilerOptions.emitBOM); + writeEmittedFiles(writer.getText(), jsFilePath, sourceMapFilePath, /*writeByteOrderMark*/ compilerOptions.emitBOM, sourceFiles); // reset the state sourceMap.reset(); @@ -748,16 +748,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge } /** Write emitted output to disk */ - function writeEmittedFiles(emitOutput: string, jsFilePath: string, sourceMapFilePath: string, writeByteOrderMark: boolean) { + function writeEmittedFiles(emitOutput: string, jsFilePath: string, sourceMapFilePath: string, writeByteOrderMark: boolean, sourceFiles: SourceFile[]) { if (compilerOptions.sourceMap && !compilerOptions.inlineSourceMap) { - writeFile(host, emitterDiagnostics, sourceMapFilePath, sourceMap.getText(), /*writeByteOrderMark*/ false); + writeFile(host, emitterDiagnostics, sourceMapFilePath, sourceMap.getText(), /*writeByteOrderMark*/ false, sourceFiles); } if (sourceMapDataList) { sourceMapDataList.push(sourceMap.getSourceMapData()); } - writeFile(host, emitterDiagnostics, jsFilePath, emitOutput, writeByteOrderMark); + writeFile(host, emitterDiagnostics, jsFilePath, emitOutput, writeByteOrderMark, sourceFiles); } // Create a temporary variable with a unique unused name. diff --git a/src/compiler/program.ts b/src/compiler/program.ts index c0f769078e0..b528143384e 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -931,7 +931,7 @@ namespace ts { getSourceFile: program.getSourceFile, getSourceFiles: program.getSourceFiles, writeFile: writeFileCallback || ( - (fileName, data, writeByteOrderMark, onError) => host.writeFile(fileName, data, writeByteOrderMark, onError)), + (fileName, data, writeByteOrderMark, onError, sourceFiles) => host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles)), isEmitBlocked, }; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 155f5c1a77f..d86bc87ce53 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1584,7 +1584,7 @@ namespace ts { } export interface WriteFileCallback { - (fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void): void; + (fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void, sourceFiles?: SourceFile[]): void; } export class OperationCanceledException { } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index de10d469c87..6b120b745fe 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2110,10 +2110,10 @@ namespace ts { return combinePaths(newDirPath, sourceFilePath); } - export function writeFile(host: EmitHost, diagnostics: DiagnosticCollection, fileName: string, data: string, writeByteOrderMark: boolean) { + export function writeFile(host: EmitHost, diagnostics: DiagnosticCollection, fileName: string, data: string, writeByteOrderMark: boolean, sourceFiles?: SourceFile[]) { host.writeFile(fileName, data, writeByteOrderMark, hostErrorMessage => { diagnostics.add(createCompilerDiagnostic(Diagnostics.Could_not_write_file_0_Colon_1, fileName, hostErrorMessage)); - }); + }, sourceFiles); } export function getLineOfLocalPosition(currentSourceFile: SourceFile, pos: number) { From 95b43dac2920e653918794c3fd102c7c90e09037 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 15 Mar 2016 16:30:11 -0700 Subject: [PATCH 17/25] Handle default compiler-options and typing-options --- src/compiler/commandLineParser.ts | 38 ++- .../convertCompilerOptionsFromJson.ts | 280 ++++++++++++++---- .../unittests/convertTypingOptionsFromJson.ts | 186 ++++++++++-- 3 files changed, 422 insertions(+), 82 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index d7d60fd2304..a9f40ab053c 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -641,9 +641,10 @@ namespace ts { */ export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}, configFileName?: string): ParsedCommandLine { const errors: Diagnostic[] = []; - const optionsFromJsonConfigFile = convertOptionsFromJson(optionDeclarations, json["compilerOptions"], basePath, configFileName, errors); - const options = extend(existingOptions, optionsFromJsonConfigFile); - const typingOptions = convertOptionsFromJson(typingOptionDeclarations, json["typingOptions"], basePath, configFileName, errors); + const compilerOptions: CompilerOptions = convertCompilerOptionsFromJson(optionDeclarations, json["compilerOptions"], basePath, configFileName, errors); + const options = extend(existingOptions, compilerOptions); + const typingOptions: TypingOptions = convertTypingOptionsFromJson(typingOptionDeclarations, json["typingOptions"], basePath, configFileName, errors); + const fileNames = getFileNames(errors); return { @@ -717,11 +718,30 @@ namespace ts { } /* @internal */ - export function convertOptionsFromJson(optionDeclarations: CommandLineOption[], jsonOptions: any, basePath: string, configFileName: string, errors: Diagnostic[]): T { - const options = {} as T; + export function convertCompilerOptionsFromJson(optionsDeclarations: CommandLineOption[], jsonOptions: any, basePath: string, + configFileName: string, errors: Diagnostic[]): CompilerOptions { + + const options: CompilerOptions = getBaseFileName(configFileName) === "jsconfig.json" ? { allowJs: true } : {}; + convertOptionsFromJson(optionDeclarations, jsonOptions, basePath, configFileName, options, Diagnostics.Unknown_compiler_option_0, errors); + return options; + } + + /* @internal */ + export function convertTypingOptionsFromJson(optionsDeclarations: CommandLineOption[], jsonOptions: any, basePath: string, + configFileName: string, errors: Diagnostic[]): TypingOptions { + + const options: TypingOptions = getBaseFileName(configFileName) === "jsconfig.json" + ? { enableAutoDiscovery: true, include: [], exclude: [] } + : { enableAutoDiscovery: false, include: [], exclude: [] }; + convertOptionsFromJson(typingOptionDeclarations, jsonOptions, basePath, configFileName, options, Diagnostics.Unknown_typing_option_0, errors); + return options; + } + + function convertOptionsFromJson(optionDeclarations: CommandLineOption[], jsonOptions: any, basePath: string, + configFileName: string, defaultOptions: T, diagnosticMessage: DiagnosticMessage, errors: Diagnostic[]) { if (!jsonOptions) { - return options; + return ; } const optionNameMap = arrayToMap(optionDeclarations, opt => opt.name); @@ -729,14 +749,12 @@ namespace ts { for (const id in jsonOptions) { if (hasProperty(optionNameMap, id)) { const opt = optionNameMap[id]; - options[opt.name] = convertJsonOption(opt, jsonOptions[id], basePath, errors); + defaultOptions[opt.name] = convertJsonOption(opt, jsonOptions[id], basePath, errors); } else { - errors.push(createCompilerDiagnostic(Diagnostics.Unknown_compiler_option_0, id)); + errors.push(createCompilerDiagnostic(diagnosticMessage, id)); } } - - return options; } function convertJsonOption(opt: CommandLineOption, value: any, basePath: string, errors: Diagnostic[]): number | string | number[] | string[] { diff --git a/tests/cases/unittests/convertCompilerOptionsFromJson.ts b/tests/cases/unittests/convertCompilerOptionsFromJson.ts index bd572757631..14674e18e3f 100644 --- a/tests/cases/unittests/convertCompilerOptionsFromJson.ts +++ b/tests/cases/unittests/convertCompilerOptionsFromJson.ts @@ -3,9 +3,9 @@ namespace ts { describe('convertCompilerOptionsFromJson', () => { - function assertCompilerOptions(json: any, expectedResult: { compilerOptions: CompilerOptions, errors: Diagnostic[] }) { + function assertCompilerOptions(json: any, configFileName: string, expectedResult: { compilerOptions: CompilerOptions, errors: Diagnostic[] }) { const actualErrors: Diagnostic[] = []; - const actualCompilerOptions = convertOptionsFromJson(optionDeclarations, json["compilerOptions"], "/apath/", "tsconfig.json", actualErrors); + const actualCompilerOptions: CompilerOptions = convertCompilerOptionsFromJson(optionDeclarations, json["compilerOptions"], "/apath/", configFileName, actualErrors); const parsedCompilerOptions = JSON.stringify(actualCompilerOptions); const expectedCompilerOptions = JSON.stringify(expectedResult.compilerOptions); @@ -21,58 +21,236 @@ namespace ts { } } - const correctFormatOptions = { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "noImplicitAny": false, - "sourceMap": false, - "lib": ["es5", "es6.array", "es6.symbol"] - } - } - - const incorrectLibOption = { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "noImplicitAny": false, - "sourceMap": false, - "lib": ["es5", "es6.array", "es8"] - } - } - - it("Convert correctly format JSON to compiler-options ", () => { - assertCompilerOptions(correctFormatOptions, { - compilerOptions: { - module: ModuleKind.CommonJS, - target: ScriptTarget.ES5, - noImplicitAny: false, - sourceMap: false, - lib: ["lib.es5.d.ts", "lib.es6.array.d.ts", "lib.es6.symbol.d.ts"] - }, - errors: [] - }); + // tsconfig.json tests + it("Convert correctly format tsconfig.json to compiler-options ", () => { + assertCompilerOptions( + { + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "noImplicitAny": false, + "sourceMap": false, + "lib": ["es5", "es6.array", "es6.symbol"] + } + }, "tsconfig.json", + { + compilerOptions: { + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, + noImplicitAny: false, + sourceMap: false, + lib: ["lib.es5.d.ts", "lib.es6.array.d.ts", "lib.es6.symbol.d.ts"] + }, + errors: [] + } + ); + }); + + it("Convert correctly format tsconfig.json with allowJs is false to compiler-options ", () => { + assertCompilerOptions( + { + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "noImplicitAny": false, + "sourceMap": false, + "allowJs": false, + "lib": ["es5", "es6.array", "es6.symbol"] + } + }, "tsconfig.json", + { + compilerOptions: { + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, + noImplicitAny: false, + sourceMap: false, + allowJs: false, + lib: ["lib.es5.d.ts", "lib.es6.array.d.ts", "lib.es6.symbol.d.ts"] + }, + errors: [] + } + ); }); it("Convert incorrectly option of libs to compiler-options ", () => { - debugger; - assertCompilerOptions(incorrectLibOption, { - compilerOptions: { - module: ModuleKind.CommonJS, - target: ScriptTarget.ES5, - noImplicitAny: false, - sourceMap: false, - lib: ["lib.es5.d.ts", "lib.es6.array.d.ts"] - }, - errors: [{ - file: undefined, - start: 0, - length: 0, - messageText: "", - code: Diagnostics.Arguments_for_library_option_must_be_Colon_0.code, - category: Diagnostics.Arguments_for_library_option_must_be_Colon_0.category - }] - }); + assertCompilerOptions( + { + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "noImplicitAny": false, + "sourceMap": false, + "lib": ["es5", "es6.array", "es8"] + } + }, "tsconfig.json", + { + compilerOptions: { + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, + noImplicitAny: false, + sourceMap: false, + lib: ["lib.es5.d.ts", "lib.es6.array.d.ts"] + }, + errors: [{ + file: undefined, + start: 0, + length: 0, + messageText: "", + code: Diagnostics.Arguments_for_library_option_must_be_Colon_0.code, + category: Diagnostics.Arguments_for_library_option_must_be_Colon_0.category + }] + } + ); + }); + + it("Convert incorrectly format tsconfig.json to compiler-options ", () => { + assertCompilerOptions( + { + "compilerOptions": { + "modu": "commonjs", + } + }, "tsconfig.json", + { + compilerOptions: {}, + errors: [{ + file: undefined, + start: 0, + length: 0, + messageText: "", + code: Diagnostics.Unknown_compiler_option_0.code, + category: Diagnostics.Unknown_compiler_option_0.category + }] + } + ); + }); + + it("Convert default tsconfig.json to compiler-options ", () => { + assertCompilerOptions({}, "tsconfig.json", + { + compilerOptions: {} as CompilerOptions, + errors: [] + } + ); + }); + + // jsconfig.json + it("Convert correctly format jsconfig.json to compiler-options ", () => { + assertCompilerOptions( + { + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "noImplicitAny": false, + "sourceMap": false, + "lib": ["es5", "es6.array", "es6.symbol"] + } + }, "jsconfig.json", + { + compilerOptions: { + allowJs: true, + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, + noImplicitAny: false, + sourceMap: false, + lib: ["lib.es5.d.ts", "lib.es6.array.d.ts", "lib.es6.symbol.d.ts"] + }, + errors: [] + } + ); + }); + + it("Convert correctly format jsconfig.json with allowJs is false to compiler-options ", () => { + assertCompilerOptions( + { + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "noImplicitAny": false, + "sourceMap": false, + "allowJs": false, + "lib": ["es5", "es6.array", "es6.symbol"] + } + }, "jsconfig.json", + { + compilerOptions: { + allowJs: false, + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, + noImplicitAny: false, + sourceMap: false, + lib: ["lib.es5.d.ts", "lib.es6.array.d.ts", "lib.es6.symbol.d.ts"] + }, + errors: [] + } + ); + }); + + it("Convert incorrectly option of libs to compiler-options ", () => { + assertCompilerOptions( + { + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "noImplicitAny": false, + "sourceMap": false, + "lib": ["es5", "es6.array", "es8"] + } + }, "jsconfig.json", + { + compilerOptions: { + allowJs: true, + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, + noImplicitAny: false, + sourceMap: false, + lib: ["lib.es5.d.ts", "lib.es6.array.d.ts"] + }, + errors: [{ + file: undefined, + start: 0, + length: 0, + messageText: "", + code: Diagnostics.Arguments_for_library_option_must_be_Colon_0.code, + category: Diagnostics.Arguments_for_library_option_must_be_Colon_0.category + }] + } + ); + }); + + it("Convert incorrectly format jsconfig.json to compiler-options ", () => { + assertCompilerOptions( + { + "compilerOptions": { + "modu": "commonjs", + } + }, "jsconfig.json", + { + compilerOptions: + { + allowJs: true + }, + errors: [{ + file: undefined, + start: 0, + length: 0, + messageText: "", + code: Diagnostics.Unknown_compiler_option_0.code, + category: Diagnostics.Unknown_compiler_option_0.category + }] + } + ); + }); + + it("Convert default jsconfig.json to compiler-options ", () => { + assertCompilerOptions({}, "jsconfig.json", + { + compilerOptions: + { + allowJs: true + }, + errors: [] + } + ); }); }); } diff --git a/tests/cases/unittests/convertTypingOptionsFromJson.ts b/tests/cases/unittests/convertTypingOptionsFromJson.ts index 89a44836e45..898dee0a18b 100644 --- a/tests/cases/unittests/convertTypingOptionsFromJson.ts +++ b/tests/cases/unittests/convertTypingOptionsFromJson.ts @@ -3,13 +3,12 @@ namespace ts { describe('convertTypingOptionsFromJson', () => { - function assertTypingOptions(json: any, expectedResult: { typingOptions: TypingOptions, errors: Diagnostic[] }) { + function assertTypingOptions(json: any, configFileName: string, expectedResult: { typingOptions: TypingOptions, errors: Diagnostic[] }) { const actualErrors: Diagnostic[] = []; - const actualTypingOptions = convertOptionsFromJson(typingOptionDeclarations, json["typingOptions"], "/apath/", "tsconfig.json", actualErrors); - + const actualTypingOptions = convertTypingOptionsFromJson(typingOptionDeclarations, json["typingOptions"], "/apath/", configFileName, actualErrors); const parsedTypingOptions = JSON.stringify(actualTypingOptions); const expectedTypingOptions = JSON.stringify(expectedResult.typingOptions); - assert.equal(parsedTypingOptions, parsedTypingOptions); + assert.equal(parsedTypingOptions, expectedTypingOptions); const expectedErrors = expectedResult.errors; assert.isTrue(expectedResult.errors.length === actualErrors.length, `Expected error: ${JSON.stringify(expectedResult.errors)}. Actual error: ${JSON.stringify(actualErrors)}.`); @@ -20,25 +19,170 @@ namespace ts { assert.equal(actualError.category, expectedError.category, `Expected error-category: ${JSON.stringify(expectedError.category)}. Actual error-category: ${JSON.stringify(actualError.category)}.`); } } - - const correctFormatOptions = { - "typingOptions": { - "enableAutoDiscovery": true, - "include": ["0.d.ts", "1.d.ts"], - "exclude": ["0.js", "1.js"] - } - } - - it("Convert correctly format JSON to compiler-options ", () => { - debugger; - assertTypingOptions(correctFormatOptions, { - typingOptions: { - enableAutoDiscovery: true, - include: ["/apath/0.d.ts", "/apath/1.d.ts"], - exclude: ["/apath/0.js", "/apath/1.js"] + + // tsconfig.json + it("Convert correctly format tsconfig.json to typing-options ", () => { + assertTypingOptions( + { + "typingOptions": + { + "enableAutoDiscovery": true, + "include": ["0.d.ts", "1.d.ts"], + "exclude": ["0.js", "1.js"] + } }, - errors: [] + "tsconfig.json", + { + typingOptions: + { + enableAutoDiscovery: true, + include: ["0.d.ts", "1.d.ts"], + exclude: ["0.js", "1.js"] + }, + errors: [] }); }); + + it("Convert incorrect format tsconfig.json to typing-options ", () => { + assertTypingOptions( + { + "typingOptions": + { + "enableAutoDiscovy": true, + } + }, "tsconfig.json", + { + typingOptions: + { + enableAutoDiscovery: false, + include: [], + exclude: [] + }, + errors: [ + { + category: Diagnostics.Unknown_typing_option_0.category, + code: Diagnostics.Unknown_typing_option_0.code, + file: undefined, + start: 0, + length: 0, + messageText: undefined + } + ] + }); + }); + + it("Convert default tsconfig.json to typing-options ", () => { + assertTypingOptions({}, "tsconfig.json", + { + typingOptions: + { + enableAutoDiscovery: false, + include: [], + exclude: [] + }, + errors: [] + }); + }); + + it("Convert tsconfig.json with only enableAutoDiscovery property to typing-options ", () => { + assertTypingOptions( + { + "typingOptions": + { + "enableAutoDiscovery": true + } + }, "tsconfig.json", + { + typingOptions: + { + enableAutoDiscovery: true, + include: [], + exclude: [] + }, + errors: [] + }); + }); + + // jsconfig.json + it("Convert jsconfig.json to typing-options ", () => { + assertTypingOptions( + { + "typingOptions": + { + "enableAutoDiscovery": false, + "include": ["0.d.ts"], + "exclude": ["0.js"] + } + }, "jsconfig.json", + { + typingOptions: + { + enableAutoDiscovery: false, + include: ["0.d.ts"], + exclude: ["0.js"] + }, + errors: [] + }); + }); + + it("Convert default jsconfig.json to typing-options ", () => { + assertTypingOptions({ }, "jsconfig.json", + { + typingOptions: + { + enableAutoDiscovery: true, + include: [], + exclude: [] + }, + errors: [] + }); + }); + + it("Convert incorrect format jsconfig.json to typing-options ", () => { + assertTypingOptions( + { + "typingOptions": + { + "enableAutoDiscovy": true, + } + }, "jsconfig.json", + { + typingOptions: + { + enableAutoDiscovery: true, + include: [], + exclude: [] + }, + errors: [ + { + category: Diagnostics.Unknown_compiler_option_0.category, + code: Diagnostics.Unknown_typing_option_0.code, + file: undefined, + start: 0, + length: 0, + messageText: undefined + } + ] + }); + }); + + it("Convert jsconfig.json with only enableAutoDiscovery property to typing-options ", () => { + assertTypingOptions( + { + "typingOptions": + { + "enableAutoDiscovery": false + } + }, "jsconfig.json", + { + typingOptions: + { + enableAutoDiscovery: false, + include: [], + exclude: [] + }, + errors: [] + }); + }); }); } From 4d915e59d9e60996ae56482d5287d9e8d4195c02 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 15 Mar 2016 17:04:18 -0700 Subject: [PATCH 18/25] Using ts.filter instead of just .filter --- src/compiler/commandLineParser.ts | 6 +++--- tests/cases/unittests/commandLineParsing.ts | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index a9f40ab053c..cd05bb0b2c8 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -530,14 +530,14 @@ namespace ts { } function parseListTypeOption(opt: CommandLineOptionOfListType, value: string): (number | string)[] { - const values = (value || "").split(",").filter(v => { return v != undefined; }); + const values = (value.trim() || "").split(","); 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)).filter(v => { return v != undefined; }); + return ts.filter(ts.map(values, v => parseCustomTypeOption(opt.element, v)), v => !!v); } } } @@ -793,6 +793,6 @@ namespace ts { } function convertJsonOptionOfListType(option: CommandLineOptionOfListType, values: any[], basePath: string, errors: Diagnostic[]): any[] { - return ts.map(values, v => convertJsonOption(option.element, v, basePath, errors)).filter(v => { return v != undefined; }); + return ts.filter(ts.map(values, v => convertJsonOption(option.element, v, basePath, errors)), v => !!v); } } diff --git a/tests/cases/unittests/commandLineParsing.ts b/tests/cases/unittests/commandLineParsing.ts index a77d1e56494..275bba54f01 100644 --- a/tests/cases/unittests/commandLineParsing.ts +++ b/tests/cases/unittests/commandLineParsing.ts @@ -94,6 +94,26 @@ namespace ts { }); }); + it("Parse incorrect form of library flags with trailing white-space ", () => { + // --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"], From 92bee6a533ed621602af5e550366bf80c88700c0 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Wed, 16 Mar 2016 13:49:36 -0700 Subject: [PATCH 19/25] Unify error message for custom-type compiler option --- src/compiler/commandLineParser.ts | 35 +- src/compiler/diagnosticMessages.json | 10 +- src/compiler/types.ts | 1 - tests/cases/unittests/commandLineParsing.ts | 195 +++++++++-- .../convertCompilerOptionsFromJson.ts | 304 +++++++++++++++--- 5 files changed, 451 insertions(+), 94 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index cd05bb0b2c8..edac2891a58 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -58,7 +58,6 @@ namespace ts { }, paramType: Diagnostics.KIND, description: Diagnostics.Specify_JSX_code_generation_Colon_preserve_or_react, - error: Diagnostics.Argument_for_jsx_must_be_preserve_or_react }, { name: "reactNamespace", @@ -94,7 +93,6 @@ namespace ts { }, description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_system_umd_or_es2015, paramType: Diagnostics.KIND, - error: Diagnostics.Argument_for_module_option_must_be_commonjs_amd_system_umd_es2015_or_none }, { name: "newLine", @@ -104,7 +102,6 @@ namespace ts { }, description: Diagnostics.Specify_the_end_of_line_sequence_to_be_used_when_emitting_files_Colon_CRLF_dos_or_LF_unix, paramType: Diagnostics.NEWLINE, - error: Diagnostics.Argument_for_newLine_option_must_be_CRLF_or_LF }, { name: "noEmit", @@ -233,7 +230,6 @@ namespace ts { }, description: Diagnostics.Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES2015, paramType: Diagnostics.VERSION, - error: Diagnostics.Argument_for_target_option_must_be_ES3_ES5_or_ES2015 }, { name: "version", @@ -265,7 +261,6 @@ namespace ts { "classic": ModuleResolutionKind.Classic, }, description: Diagnostics.Specify_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6, - error: Diagnostics.Argument_for_moduleResolution_option_must_be_node_or_classic, }, { name: "lib", @@ -297,7 +292,6 @@ namespace ts { "es6.symbol.wellknown": "lib.es6.symbol.wellknown.d.ts", "es7.array.include": "lib.es7.array.include.d.ts" }, - error: Diagnostics.Arguments_for_library_option_must_be_Colon_0, }, description: Diagnostics.Specify_library_to_be_included_in_the_compilation_Colon, }, @@ -423,25 +417,15 @@ namespace ts { return optionNameMapCache; } - // Cache between the name of commandline which is a custom type and a list of all possible custom types - const namesOfCustomTypeMapCache: Map = {}; - /* @internal */ - export function getNamesOfCustomTypeFromCommandLineOptionsOfCustomType(opt: CommandLineOptionOfCustomType): string[] { - if (hasProperty(namesOfCustomTypeMapCache, opt.name)) { - return namesOfCustomTypeMapCache[opt.name]; - } + export function createCompilerDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType): Diagnostic { - const type = opt.type; const namesOfType: string[] = []; - for (const typeName in type) { - if (hasProperty(type, typeName)) { - namesOfType.push(typeName); - } - } + ts.forEachKey(opt.type, key => { + namesOfType.push(` '${key}'`); + }); - namesOfCustomTypeMapCache[opt.name] = namesOfType; - return namesOfCustomTypeMapCache[opt.name]; + return createCompilerDiagnostic(Diagnostics.Argument_for_0_option_must_be_Colon_1, `--${opt.name}`, namesOfType); } export function parseCommandLine(commandLine: string[], readFile?: (path: string) => string): ParsedCommandLine { @@ -518,19 +502,18 @@ namespace ts { } function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string) { + const key = (value || "").trim().toLowerCase(); const map = opt.type; - const key = (value || "").toLowerCase(); if (hasProperty(map, key)) { return map[key]; } else { - const suggestedOption = getNamesOfCustomTypeFromCommandLineOptionsOfCustomType(opt); - errors.push(createCompilerDiagnostic(opt.error, suggestedOption ? suggestedOption : undefined)); + errors.push(createCompilerDiagnosticForInvalidCustomType(opt)); } } function parseListTypeOption(opt: CommandLineOptionOfListType, value: string): (number | string)[] { - const values = (value.trim() || "").split(","); + const values = (value || "").trim().split(","); switch (opt.element.type) { case "number": return ts.map(values, parseInt); @@ -788,7 +771,7 @@ namespace ts { return opt.type[key]; } else { - errors.push(createCompilerDiagnostic(opt.error)); + errors.push(createCompilerDiagnosticForInvalidCustomType(opt)); } } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index c655faf4f3c..1abcc7a8d0a 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2364,14 +2364,10 @@ "category": "Error", "code": 6045 }, - "Argument for '--module' option must be 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'none'.": { + "Argument for '{0}' option must be: {1}": { "category": "Error", "code": 6046 }, - "Argument for '--target' option must be 'ES3', 'ES5', or 'ES2015'.": { - "category": "Error", - "code": 6047 - }, "Locale must be of the form or -. For example '{0}' or '{1}'.": { "category": "Error", "code": 6048 @@ -2424,10 +2420,6 @@ "category": "Message", "code": 6061 }, - "Argument for '--newLine' option must be 'CRLF' or 'LF'.": { - "category": "Error", - "code": 6062 - }, "Argument for '--moduleResolution' option must be 'node' or 'classic'.": { "category": "Error", "code": 6063 diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 85febc5e968..0fdcc6300b8 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2549,7 +2549,6 @@ namespace ts { /* @internal */ export interface CommandLineOptionOfCustomType extends CommandLineOptionBase { type: Map; // an object literal mapping named values to actual values - error: DiagnosticMessage; // The error given when the argument does not fit a customized 'type' } /* @internal */ diff --git a/tests/cases/unittests/commandLineParsing.ts b/tests/cases/unittests/commandLineParsing.ts index 275bba54f01..5476ec0a5b9 100644 --- a/tests/cases/unittests/commandLineParsing.ts +++ b/tests/cases/unittests/commandLineParsing.ts @@ -16,8 +16,9 @@ namespace ts { 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)}.`); + assert.equal(parsedError.code, expectedError.code); + assert.equal(parsedError.category, expectedError.category); + assert.equal(parsedError.messageText, expectedError.messageText); } const parsedFileNames = parsed.fileNames; @@ -26,7 +27,7 @@ namespace ts { 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)}.`); + assert.equal(parsedFileName, expectedFileName); } } @@ -59,9 +60,9 @@ namespace 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, + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es7', 'dom', 'webworker', 'scripthost', 'es6.array', 'es6.collection', 'es6.function', 'es6.iterable', 'es6.math', 'es6.number', 'es6.object', 'es6.promise', 'es6.proxy', 'es6.reflect', 'es6.regexp', 'es6.symbol', 'es6.symbol.wellknown', 'es7.array.include'", + category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, + code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, file: undefined, start: undefined, @@ -74,14 +75,172 @@ namespace ts { }); }); - it("Parse incorrect form of library flags ", () => { + it("Parse empty options of --jsx ", () => { + // 0.ts --lib + assertParseResult(["0.ts", "--jsx"], + { + errors: [{ + messageText: "Compiler option 'jsx' expects an argument.", + category: ts.Diagnostics.Compiler_option_0_expects_an_argument.category, + code: ts.Diagnostics.Compiler_option_0_expects_an_argument.code, + + file: undefined, + start: undefined, + length: undefined, + }, { + messageText: "Argument for '--jsx' option must be: 'preserve', 'react'", + category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, + code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + + file: undefined, + start: undefined, + length: undefined, + }], + fileNames: ["0.ts"], + options: {} + }); + }); + + it("Parse empty options of --module ", () => { + // 0.ts --lib + assertParseResult(["0.ts", "--module"], + { + errors: [{ + messageText: "Compiler option 'module' expects an argument.", + category: ts.Diagnostics.Compiler_option_0_expects_an_argument.category, + code: ts.Diagnostics.Compiler_option_0_expects_an_argument.code, + + file: undefined, + start: undefined, + length: undefined, + }, { + messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'", + category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, + code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + + file: undefined, + start: undefined, + length: undefined, + }], + fileNames: ["0.ts"], + options: {} + }); + }); + + it("Parse empty options of --newLine ", () => { + // 0.ts --lib + assertParseResult(["0.ts", "--newLine"], + { + errors: [{ + messageText: "Compiler option 'newLine' expects an argument.", + category: ts.Diagnostics.Compiler_option_0_expects_an_argument.category, + code: ts.Diagnostics.Compiler_option_0_expects_an_argument.code, + + file: undefined, + start: undefined, + length: undefined, + }, { + messageText: "Argument for '--newLine' option must be: 'crlf', 'lf'", + category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, + code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + + file: undefined, + start: undefined, + length: undefined, + }], + fileNames: ["0.ts"], + options: {} + }); + }); + + it("Parse empty options of --target ", () => { + // 0.ts --lib + assertParseResult(["0.ts", "--target"], + { + errors: [{ + messageText: "Compiler option 'target' expects an argument.", + category: ts.Diagnostics.Compiler_option_0_expects_an_argument.category, + code: ts.Diagnostics.Compiler_option_0_expects_an_argument.code, + + file: undefined, + start: undefined, + length: undefined, + }, { + messageText: "Argument for '--target' option must be: 'es3', 'es5', 'es6', 'es2015'", + category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, + code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + + file: undefined, + start: undefined, + length: undefined, + }], + fileNames: ["0.ts"], + options: {} + }); + }); + + it("Parse empty options of --moduleResolution ", () => { + // 0.ts --lib + assertParseResult(["0.ts", "--moduleResolution"], + { + errors: [{ + messageText: "Compiler option 'moduleResolution' expects an argument.", + category: ts.Diagnostics.Compiler_option_0_expects_an_argument.category, + code: ts.Diagnostics.Compiler_option_0_expects_an_argument.code, + + file: undefined, + start: undefined, + length: undefined, + }, { + messageText: "Argument for '--moduleResolution' option must be: 'node', 'classic'", + category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, + code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + + file: undefined, + start: undefined, + length: undefined, + }], + fileNames: ["0.ts"], + options: {} + }); + }); + + it("Parse empty options of --lib ", () => { + // 0.ts --lib + assertParseResult(["0.ts", "--lib"], + { + errors: [{ + messageText: "Compiler option 'lib' expects an argument.", + category: ts.Diagnostics.Compiler_option_0_expects_an_argument.category, + code: ts.Diagnostics.Compiler_option_0_expects_an_argument.code, + + file: undefined, + start: undefined, + length: undefined, + }, { + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es7', 'dom', 'webworker', 'scripthost', 'es6.array', 'es6.collection', 'es6.function', 'es6.iterable', 'es6.math', 'es6.number', 'es6.object', 'es6.promise', 'es6.proxy', 'es6.reflect', 'es6.regexp', 'es6.symbol', 'es6.symbol.wellknown', 'es7.array.include'", + category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, + code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + + file: undefined, + start: undefined, + length: undefined, + }], + fileNames: ["0.ts"], + options: { + lib: [] + } + }); + }); + + it("Parse --lib option with extra comma ", () => { // --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, + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es7', 'dom', 'webworker', 'scripthost', 'es6.array', 'es6.collection', 'es6.function', 'es6.iterable', 'es6.math', 'es6.number', 'es6.object', 'es6.promise', 'es6.proxy', 'es6.reflect', 'es6.regexp', 'es6.symbol', 'es6.symbol.wellknown', 'es7.array.include'", + category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, + code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, file: undefined, start: undefined, @@ -94,14 +253,14 @@ namespace ts { }); }); - it("Parse incorrect form of library flags with trailing white-space ", () => { + it("Parse --lib option with trailing white-space ", () => { // --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, + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es7', 'dom', 'webworker', 'scripthost', 'es6.array', 'es6.collection', 'es6.function', 'es6.iterable', 'es6.math', 'es6.number', 'es6.object', 'es6.promise', 'es6.proxy', 'es6.reflect', 'es6.regexp', 'es6.symbol', 'es6.symbol.wellknown', 'es7.array.include'", + category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, + code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, file: undefined, start: undefined, @@ -141,14 +300,14 @@ namespace ts { }); }); - it("Parse incorrect form of multiple compiler flags with input files in the middle", () => { + it("Parse --lib as the last arguments", () => { // --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, + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es7', 'dom', 'webworker', 'scripthost', 'es6.array', 'es6.collection', 'es6.function', 'es6.iterable', 'es6.math', 'es6.number', 'es6.object', 'es6.promise', 'es6.proxy', 'es6.reflect', 'es6.regexp', 'es6.symbol', 'es6.symbol.wellknown', 'es7.array.include'", + category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, + code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, file: undefined, start: undefined, diff --git a/tests/cases/unittests/convertCompilerOptionsFromJson.ts b/tests/cases/unittests/convertCompilerOptionsFromJson.ts index 14674e18e3f..5c172e33af1 100644 --- a/tests/cases/unittests/convertCompilerOptionsFromJson.ts +++ b/tests/cases/unittests/convertCompilerOptionsFromJson.ts @@ -16,8 +16,9 @@ namespace ts { for (let i = 0; i < actualErrors.length; ++i) { const actualError = actualErrors[i]; const expectedError = expectedErrors[i]; - assert.equal(actualError.code, expectedError.code, `Expected error-code: ${JSON.stringify(expectedError.code)}. Actual error-code: ${JSON.stringify(actualError.code)}.`); - assert.equal(actualError.category, expectedError.category, `Expected error-category: ${JSON.stringify(expectedError.category)}. Actual error-category: ${JSON.stringify(actualError.category)}.`); + assert.equal(actualError.code, expectedError.code); + assert.equal(actualError.category, expectedError.category); + assert.equal(actualError.messageText, expectedError.messageText); } } @@ -71,7 +72,145 @@ namespace ts { } ); }); - + + it("Convert incorrectly option of jsx to compiler-options ", () => { + assertCompilerOptions( + { + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "noImplicitAny": false, + "sourceMap": false, + "jsx": "" + } + }, "tsconfig.json", + { + compilerOptions: { + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, + noImplicitAny: false, + sourceMap: false, + }, + errors: [{ + file: undefined, + start: 0, + length: 0, + messageText: "Argument for '--jsx' option must be: 'preserve', 'react'", + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category + }] + } + ); + }); + + it("Convert incorrectly option of module to compiler-options ", () => { + assertCompilerOptions( + { + "compilerOptions": { + "module": "", + "target": "es5", + "noImplicitAny": false, + "sourceMap": false, + } + }, "tsconfig.json", + { + compilerOptions: { + target: ScriptTarget.ES5, + noImplicitAny: false, + sourceMap: false, + }, + errors: [{ + file: undefined, + start: 0, + length: 0, + messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'", + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category + }] + } + ); + }); + + it("Convert incorrectly option of newLine to compiler-options ", () => { + assertCompilerOptions( + { + "compilerOptions": { + "newLine": "", + "target": "es5", + "noImplicitAny": false, + "sourceMap": false, + } + }, "tsconfig.json", + { + compilerOptions: { + target: ScriptTarget.ES5, + noImplicitAny: false, + sourceMap: false, + }, + errors: [{ + file: undefined, + start: 0, + length: 0, + messageText: "Argument for '--newLine' option must be: 'crlf', 'lf'", + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category + }] + } + ); + }); + + it("Convert incorrectly option of target to compiler-options ", () => { + assertCompilerOptions( + { + "compilerOptions": { + "target": "", + "noImplicitAny": false, + "sourceMap": false, + } + }, "tsconfig.json", + { + compilerOptions: { + noImplicitAny: false, + sourceMap: false, + }, + errors: [{ + file: undefined, + start: 0, + length: 0, + messageText: "Argument for '--target' option must be: 'es3', 'es5', 'es6', 'es2015'", + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category + }] + } + ); + }); + + it("Convert incorrectly option of module-resolution to compiler-options ", () => { + assertCompilerOptions( + { + "compilerOptions": { + "moduleResolution": "", + "noImplicitAny": false, + "sourceMap": false, + } + }, "tsconfig.json", + { + compilerOptions: { + noImplicitAny: false, + sourceMap: false, + }, + errors: [{ + file: undefined, + start: 0, + length: 0, + messageText: "Argument for '--moduleResolution' option must be: 'node', 'classic'", + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category + }] + } + ); + }); + it("Convert incorrectly option of libs to compiler-options ", () => { assertCompilerOptions( { @@ -95,14 +234,131 @@ namespace ts { file: undefined, start: 0, length: 0, - messageText: "", - code: Diagnostics.Arguments_for_library_option_must_be_Colon_0.code, - category: Diagnostics.Arguments_for_library_option_must_be_Colon_0.category + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es7', 'dom', 'webworker', 'scripthost', 'es6.array', 'es6.collection', 'es6.function', 'es6.iterable', 'es6.math', 'es6.number', 'es6.object', 'es6.promise', 'es6.proxy', 'es6.reflect', 'es6.regexp', 'es6.symbol', 'es6.symbol.wellknown', 'es7.array.include'", + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category }] } ); }); + it("Convert empty string option of libs to compiler-options ", () => { + assertCompilerOptions( + { + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "noImplicitAny": false, + "sourceMap": false, + "lib": ["es5", ""] + } + }, "tsconfig.json", + { + compilerOptions: { + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, + noImplicitAny: false, + sourceMap: false, + lib: ["lib.es5.d.ts"] + }, + errors: [{ + file: undefined, + start: 0, + length: 0, + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es7', 'dom', 'webworker', 'scripthost', 'es6.array', 'es6.collection', 'es6.function', 'es6.iterable', 'es6.math', 'es6.number', 'es6.object', 'es6.promise', 'es6.proxy', 'es6.reflect', 'es6.regexp', 'es6.symbol', 'es6.symbol.wellknown', 'es7.array.include'", + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category + }] + } + ); + }); + + it("Convert empty string option of libs to compiler-options ", () => { + assertCompilerOptions( + { + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "noImplicitAny": false, + "sourceMap": false, + "lib": [""] + } + }, "tsconfig.json", + { + compilerOptions: { + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, + noImplicitAny: false, + sourceMap: false, + lib: [] + }, + errors: [{ + file: undefined, + start: 0, + length: 0, + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es7', 'dom', 'webworker', 'scripthost', 'es6.array', 'es6.collection', 'es6.function', 'es6.iterable', 'es6.math', 'es6.number', 'es6.object', 'es6.promise', 'es6.proxy', 'es6.reflect', 'es6.regexp', 'es6.symbol', 'es6.symbol.wellknown', 'es7.array.include'", + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category + }] + } + ); + }); + + it("Convert trailing-whitespace string option of libs to compiler-options ", () => { + assertCompilerOptions( + { + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "noImplicitAny": false, + "sourceMap": false, + "lib": [" "] + } + }, "tsconfig.json", + { + compilerOptions: { + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, + noImplicitAny: false, + sourceMap: false, + lib: [] + }, + errors: [{ + file: undefined, + start: 0, + length: 0, + messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es7', 'dom', 'webworker', 'scripthost', 'es6.array', 'es6.collection', 'es6.function', 'es6.iterable', 'es6.math', 'es6.number', 'es6.object', 'es6.promise', 'es6.proxy', 'es6.reflect', 'es6.regexp', 'es6.symbol', 'es6.symbol.wellknown', 'es7.array.include'", + code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, + category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category + }] + } + ); + }); + + it("Convert empty option of libs to compiler-options ", () => { + assertCompilerOptions( + { + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "noImplicitAny": false, + "sourceMap": false, + "lib": [] + } + }, "tsconfig.json", + { + compilerOptions: { + module: ModuleKind.CommonJS, + target: ScriptTarget.ES5, + noImplicitAny: false, + sourceMap: false, + lib: [] + }, + errors: [] + } + ); + }); + it("Convert incorrectly format tsconfig.json to compiler-options ", () => { assertCompilerOptions( { @@ -116,7 +372,7 @@ namespace ts { file: undefined, start: 0, length: 0, - messageText: "", + messageText: "Unknown compiler option 'modu'.", code: Diagnostics.Unknown_compiler_option_0.code, category: Diagnostics.Unknown_compiler_option_0.category }] @@ -185,38 +441,6 @@ namespace ts { ); }); - it("Convert incorrectly option of libs to compiler-options ", () => { - assertCompilerOptions( - { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "noImplicitAny": false, - "sourceMap": false, - "lib": ["es5", "es6.array", "es8"] - } - }, "jsconfig.json", - { - compilerOptions: { - allowJs: true, - module: ModuleKind.CommonJS, - target: ScriptTarget.ES5, - noImplicitAny: false, - sourceMap: false, - lib: ["lib.es5.d.ts", "lib.es6.array.d.ts"] - }, - errors: [{ - file: undefined, - start: 0, - length: 0, - messageText: "", - code: Diagnostics.Arguments_for_library_option_must_be_Colon_0.code, - category: Diagnostics.Arguments_for_library_option_must_be_Colon_0.category - }] - } - ); - }); - it("Convert incorrectly format jsconfig.json to compiler-options ", () => { assertCompilerOptions( { @@ -233,7 +457,7 @@ namespace ts { file: undefined, start: 0, length: 0, - messageText: "", + messageText: "Unknown compiler option 'modu'.", code: Diagnostics.Unknown_compiler_option_0.code, category: Diagnostics.Unknown_compiler_option_0.category }] From f7a55fa5a232c87cb0178db50be2ff35cd58d0f8 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Wed, 16 Mar 2016 14:08:49 -0700 Subject: [PATCH 20/25] Remove --lib --- src/compiler/commandLineParser.ts | 35 +--- tests/cases/unittests/commandLineParsing.ts | 170 ++---------------- .../convertCompilerOptionsFromJson.ts | 156 ---------------- 3 files changed, 12 insertions(+), 349 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index edac2891a58..67176e05980 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -262,39 +262,6 @@ namespace ts { }, description: Diagnostics.Specify_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6, }, - { - name: "lib", - type: "list", - element: { - name: "lib", - type: { - // JavaScript only - "es5": "lib.es5.d.ts", - "es6": "lib.es6.d.ts", - "es7": "lib.es7.d.ts", - // Host only - "dom": "lib.dom.d.ts", - "webworker": "lib.webworker.d.ts", - "scripthost": "lib.scripthost.d.ts", - // ES6 Or ESNext By-feature options - "es6.array": "lib.es6.array.d.ts", - "es6.collection": "lib.es6.collection.d.ts", - "es6.function": "lib.es6.function.d.ts", - "es6.iterable": "lib.es6.iterable.d.ts", - "es6.math": "lib.es6.math.d.ts", - "es6.number": "lib.es6.number.d.ts", - "es6.object": "lib.es6.object.d.ts", - "es6.promise": "lib.es6.promise.d.ts", - "es6.proxy": "lib.es6.proxy.d.ts", - "es6.reflect": "lib.es6.reflect.d.ts", - "es6.regexp": "lib.es6.regexp.d.ts", - "es6.symbol": "lib.es6.symbol.d.ts", - "es6.symbol.wellknown": "lib.es6.symbol.wellknown.d.ts", - "es7.array.include": "lib.es7.array.include.d.ts" - }, - }, - description: Diagnostics.Specify_library_to_be_included_in_the_compilation_Colon, - }, { name: "allowUnusedLabels", type: "boolean", @@ -385,7 +352,7 @@ namespace ts { name: "exclude", type: "list", element: { - name: "include", + name: "exclude", type: "string" } } diff --git a/tests/cases/unittests/commandLineParsing.ts b/tests/cases/unittests/commandLineParsing.ts index 5476ec0a5b9..2b6b470a3b3 100644 --- a/tests/cases/unittests/commandLineParsing.ts +++ b/tests/cases/unittests/commandLineParsing.ts @@ -31,52 +31,8 @@ namespace ts { } } - 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: "Argument for '--lib' option must be: 'es5', 'es6', 'es7', 'dom', 'webworker', 'scripthost', 'es6.array', 'es6.collection', 'es6.function', 'es6.iterable', 'es6.math', 'es6.number', 'es6.object', 'es6.promise', 'es6.proxy', 'es6.reflect', 'es6.regexp', 'es6.symbol', 'es6.symbol.wellknown', 'es7.array.include'", - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, - - file: undefined, - start: undefined, - length: undefined, - }], - fileNames: ["0.ts"], - options: { - lib: ["lib.es5.d.ts"] - } - }); - }); - it("Parse empty options of --jsx ", () => { - // 0.ts --lib + // 0.ts --jsx assertParseResult(["0.ts", "--jsx"], { errors: [{ @@ -102,7 +58,7 @@ namespace ts { }); it("Parse empty options of --module ", () => { - // 0.ts --lib + // 0.ts -- assertParseResult(["0.ts", "--module"], { errors: [{ @@ -128,7 +84,7 @@ namespace ts { }); it("Parse empty options of --newLine ", () => { - // 0.ts --lib + // 0.ts --newLine assertParseResult(["0.ts", "--newLine"], { errors: [{ @@ -154,7 +110,7 @@ namespace ts { }); it("Parse empty options of --target ", () => { - // 0.ts --lib + // 0.ts --target assertParseResult(["0.ts", "--target"], { errors: [{ @@ -180,7 +136,7 @@ namespace ts { }); it("Parse empty options of --moduleResolution ", () => { - // 0.ts --lib + // 0.ts --moduleResolution assertParseResult(["0.ts", "--moduleResolution"], { errors: [{ @@ -205,133 +161,29 @@ namespace ts { }); }); - it("Parse empty options of --lib ", () => { - // 0.ts --lib - assertParseResult(["0.ts", "--lib"], - { - errors: [{ - messageText: "Compiler option 'lib' expects an argument.", - category: ts.Diagnostics.Compiler_option_0_expects_an_argument.category, - code: ts.Diagnostics.Compiler_option_0_expects_an_argument.code, - - file: undefined, - start: undefined, - length: undefined, - }, { - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es7', 'dom', 'webworker', 'scripthost', 'es6.array', 'es6.collection', 'es6.function', 'es6.iterable', 'es6.math', 'es6.number', 'es6.object', 'es6.promise', 'es6.proxy', 'es6.reflect', 'es6.regexp', 'es6.symbol', 'es6.symbol.wellknown', 'es7.array.include'", - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, - - file: undefined, - start: undefined, - length: undefined, - }], - fileNames: ["0.ts"], - options: { - lib: [] - } - }); - }); - - it("Parse --lib option with extra comma ", () => { - // --lib es5, es7 0.ts - assertParseResult(["--lib", "es5,", "es7", "0.ts"], - { - errors: [{ - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es7', 'dom', 'webworker', 'scripthost', 'es6.array', 'es6.collection', 'es6.function', 'es6.iterable', 'es6.math', 'es6.number', 'es6.object', 'es6.promise', 'es6.proxy', 'es6.reflect', 'es6.regexp', 'es6.symbol', 'es6.symbol.wellknown', 'es7.array.include'", - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code, - - file: undefined, - start: undefined, - length: undefined, - }], - fileNames: ["es7", "0.ts"], - options: { - lib: ["lib.es5.d.ts"] - } - }); - }); - - it("Parse --lib option with trailing white-space ", () => { - // --lib es5, es7 0.ts - assertParseResult(["--lib", "es5, ", "es7", "0.ts"], - { - errors: [{ - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es7', 'dom', 'webworker', 'scripthost', 'es6.array', 'es6.collection', 'es6.function', 'es6.iterable', 'es6.math', 'es6.number', 'es6.object', 'es6.promise', 'es6.proxy', 'es6.reflect', 'es6.regexp', 'es6.symbol', 'es6.symbol.wellknown', 'es7.array.include'", - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.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"], + // --module commonjs --target es5 0.ts + assertParseResult(["--module", "commonjs", "--target", "es5", "0.ts"], { errors: [], fileNames: ["0.ts"], options: { - lib: ["lib.es5.d.ts", "lib.es6.symbol.wellknown.d.ts"], + module: ts.ModuleKind.CommonJS, 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"], + // --module commonjs --target es5 0.ts --noImplicitAny + assertParseResult(["--module", "commonjs", "--target", "es5", "0.ts", "--noImplicitAny"], { 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 --lib as the last arguments", () => { - // --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: "Argument for '--lib' option must be: 'es5', 'es6', 'es7', 'dom', 'webworker', 'scripthost', 'es6.array', 'es6.collection', 'es6.function', 'es6.iterable', 'es6.math', 'es6.number', 'es6.object', 'es6.promise', 'es6.proxy', 'es6.reflect', 'es6.regexp', 'es6.symbol', 'es6.symbol.wellknown', 'es7.array.include'", - category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category, - code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.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"], + noImplicitAny: true, } }); }); diff --git a/tests/cases/unittests/convertCompilerOptionsFromJson.ts b/tests/cases/unittests/convertCompilerOptionsFromJson.ts index 5c172e33af1..c68d8b97271 100644 --- a/tests/cases/unittests/convertCompilerOptionsFromJson.ts +++ b/tests/cases/unittests/convertCompilerOptionsFromJson.ts @@ -31,7 +31,6 @@ namespace ts { "target": "es5", "noImplicitAny": false, "sourceMap": false, - "lib": ["es5", "es6.array", "es6.symbol"] } }, "tsconfig.json", { @@ -40,7 +39,6 @@ namespace ts { target: ScriptTarget.ES5, noImplicitAny: false, sourceMap: false, - lib: ["lib.es5.d.ts", "lib.es6.array.d.ts", "lib.es6.symbol.d.ts"] }, errors: [] } @@ -56,7 +54,6 @@ namespace ts { "noImplicitAny": false, "sourceMap": false, "allowJs": false, - "lib": ["es5", "es6.array", "es6.symbol"] } }, "tsconfig.json", { @@ -66,7 +63,6 @@ namespace ts { noImplicitAny: false, sourceMap: false, allowJs: false, - lib: ["lib.es5.d.ts", "lib.es6.array.d.ts", "lib.es6.symbol.d.ts"] }, errors: [] } @@ -211,154 +207,6 @@ namespace ts { ); }); - it("Convert incorrectly option of libs to compiler-options ", () => { - assertCompilerOptions( - { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "noImplicitAny": false, - "sourceMap": false, - "lib": ["es5", "es6.array", "es8"] - } - }, "tsconfig.json", - { - compilerOptions: { - module: ModuleKind.CommonJS, - target: ScriptTarget.ES5, - noImplicitAny: false, - sourceMap: false, - lib: ["lib.es5.d.ts", "lib.es6.array.d.ts"] - }, - errors: [{ - file: undefined, - start: 0, - length: 0, - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es7', 'dom', 'webworker', 'scripthost', 'es6.array', 'es6.collection', 'es6.function', 'es6.iterable', 'es6.math', 'es6.number', 'es6.object', 'es6.promise', 'es6.proxy', 'es6.reflect', 'es6.regexp', 'es6.symbol', 'es6.symbol.wellknown', 'es7.array.include'", - code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, - category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category - }] - } - ); - }); - - it("Convert empty string option of libs to compiler-options ", () => { - assertCompilerOptions( - { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "noImplicitAny": false, - "sourceMap": false, - "lib": ["es5", ""] - } - }, "tsconfig.json", - { - compilerOptions: { - module: ModuleKind.CommonJS, - target: ScriptTarget.ES5, - noImplicitAny: false, - sourceMap: false, - lib: ["lib.es5.d.ts"] - }, - errors: [{ - file: undefined, - start: 0, - length: 0, - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es7', 'dom', 'webworker', 'scripthost', 'es6.array', 'es6.collection', 'es6.function', 'es6.iterable', 'es6.math', 'es6.number', 'es6.object', 'es6.promise', 'es6.proxy', 'es6.reflect', 'es6.regexp', 'es6.symbol', 'es6.symbol.wellknown', 'es7.array.include'", - code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, - category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category - }] - } - ); - }); - - it("Convert empty string option of libs to compiler-options ", () => { - assertCompilerOptions( - { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "noImplicitAny": false, - "sourceMap": false, - "lib": [""] - } - }, "tsconfig.json", - { - compilerOptions: { - module: ModuleKind.CommonJS, - target: ScriptTarget.ES5, - noImplicitAny: false, - sourceMap: false, - lib: [] - }, - errors: [{ - file: undefined, - start: 0, - length: 0, - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es7', 'dom', 'webworker', 'scripthost', 'es6.array', 'es6.collection', 'es6.function', 'es6.iterable', 'es6.math', 'es6.number', 'es6.object', 'es6.promise', 'es6.proxy', 'es6.reflect', 'es6.regexp', 'es6.symbol', 'es6.symbol.wellknown', 'es7.array.include'", - code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, - category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category - }] - } - ); - }); - - it("Convert trailing-whitespace string option of libs to compiler-options ", () => { - assertCompilerOptions( - { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "noImplicitAny": false, - "sourceMap": false, - "lib": [" "] - } - }, "tsconfig.json", - { - compilerOptions: { - module: ModuleKind.CommonJS, - target: ScriptTarget.ES5, - noImplicitAny: false, - sourceMap: false, - lib: [] - }, - errors: [{ - file: undefined, - start: 0, - length: 0, - messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es7', 'dom', 'webworker', 'scripthost', 'es6.array', 'es6.collection', 'es6.function', 'es6.iterable', 'es6.math', 'es6.number', 'es6.object', 'es6.promise', 'es6.proxy', 'es6.reflect', 'es6.regexp', 'es6.symbol', 'es6.symbol.wellknown', 'es7.array.include'", - code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code, - category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category - }] - } - ); - }); - - it("Convert empty option of libs to compiler-options ", () => { - assertCompilerOptions( - { - "compilerOptions": { - "module": "commonjs", - "target": "es5", - "noImplicitAny": false, - "sourceMap": false, - "lib": [] - } - }, "tsconfig.json", - { - compilerOptions: { - module: ModuleKind.CommonJS, - target: ScriptTarget.ES5, - noImplicitAny: false, - sourceMap: false, - lib: [] - }, - errors: [] - } - ); - }); - it("Convert incorrectly format tsconfig.json to compiler-options ", () => { assertCompilerOptions( { @@ -398,7 +246,6 @@ namespace ts { "target": "es5", "noImplicitAny": false, "sourceMap": false, - "lib": ["es5", "es6.array", "es6.symbol"] } }, "jsconfig.json", { @@ -408,7 +255,6 @@ namespace ts { target: ScriptTarget.ES5, noImplicitAny: false, sourceMap: false, - lib: ["lib.es5.d.ts", "lib.es6.array.d.ts", "lib.es6.symbol.d.ts"] }, errors: [] } @@ -424,7 +270,6 @@ namespace ts { "noImplicitAny": false, "sourceMap": false, "allowJs": false, - "lib": ["es5", "es6.array", "es6.symbol"] } }, "jsconfig.json", { @@ -434,7 +279,6 @@ namespace ts { target: ScriptTarget.ES5, noImplicitAny: false, sourceMap: false, - lib: ["lib.es5.d.ts", "lib.es6.array.d.ts", "lib.es6.symbol.d.ts"] }, errors: [] } From 03bf75bf0604ae076eafdbe80ad4b6e95328c624 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Wed, 16 Mar 2016 14:09:02 -0700 Subject: [PATCH 21/25] Remove unused error message --- src/compiler/diagnosticMessages.json | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 1abcc7a8d0a..68ce847148f 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2612,14 +2612,6 @@ "category": "Message", "code": 6112 }, - "Specify library to be included in the compilation:": { - "category": "Message", - "code": 6113 - }, - "Arguments for library option must be: {0}": { - "category": "Error", - "code": 6114 - }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", "code": 7005 From 120c6eba25c59d7f74b463790ae6fc4d86748afe Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Wed, 16 Mar 2016 14:09:45 -0700 Subject: [PATCH 22/25] Remove trailing whitespace --- Jakefile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jakefile.js b/Jakefile.js index 299ce1c77c4..a6570c3c710 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -146,7 +146,7 @@ var harnessSources = harnessCoreSources.concat([ "session.ts", "versionCache.ts", "convertToBase64.ts", - "transpile.ts", + "transpile.ts", "reuseProgramStructure.ts", "cachingInServerLSHost.ts", "moduleResolution.ts", From 9a5542b1fde2ea5f304db78211429f3443b2ee16 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Wed, 16 Mar 2016 14:21:20 -0700 Subject: [PATCH 23/25] Remove unused error message --- src/compiler/diagnosticMessages.json | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 68ce847148f..b8dd62efa8e 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2420,10 +2420,6 @@ "category": "Message", "code": 6061 }, - "Argument for '--moduleResolution' option must be 'node' or 'classic'.": { - "category": "Error", - "code": 6063 - }, "Option '{0}' can only be specified in 'tsconfig.json' file.": { "category": "Error", "code": 6064 @@ -2484,10 +2480,6 @@ "category": "Message", "code": 6080 }, - "Argument for '--jsx' must be 'preserve' or 'react'.": { - "category": "Message", - "code": 6081 - }, "Only 'amd' and 'system' modules are supported alongside --{0}.": { "category": "Error", "code": 6082 From 266a92b1f348005260e7770c06af65b72b3b63dc Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Wed, 16 Mar 2016 15:29:13 -0700 Subject: [PATCH 24/25] Address PR --- src/compiler/commandLineParser.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 67176e05980..221ef5b87a8 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -386,9 +386,8 @@ namespace ts { /* @internal */ export function createCompilerDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType): Diagnostic { - const namesOfType: string[] = []; - ts.forEachKey(opt.type, key => { + forEachKey(opt.type, key => { namesOfType.push(` '${key}'`); }); @@ -487,7 +486,7 @@ namespace ts { case "string": return ts.map(values, v => v || ""); default: - return ts.filter(ts.map(values, v => parseCustomTypeOption(opt.element, v)), v => !!v); + return filter(map(values, v => parseCustomTypeOption(opt.element, v)), v => !!v); } } } @@ -743,6 +742,6 @@ namespace ts { } function convertJsonOptionOfListType(option: CommandLineOptionOfListType, values: any[], basePath: string, errors: Diagnostic[]): any[] { - return ts.filter(ts.map(values, v => convertJsonOption(option.element, v, basePath, errors)), v => !!v); + return filter(map(values, v => convertJsonOption(option.element, v, basePath, errors)), v => !!v); } } From 9e2df0459eb1c144b15d8c2b6e02705886495675 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Wed, 16 Mar 2016 16:35:51 -0700 Subject: [PATCH 25/25] Address PR --- src/compiler/commandLineParser.ts | 22 +++++++++---------- src/compiler/types.ts | 4 +++- .../convertCompilerOptionsFromJson.ts | 2 +- .../unittests/convertTypingOptionsFromJson.ts | 2 +- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 221ef5b87a8..2f10a8103c4 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -478,7 +478,7 @@ namespace ts { } } - function parseListTypeOption(opt: CommandLineOptionOfListType, value: string): (number | string)[] { + function parseListTypeOption(opt: CommandLineOptionOfListType, value: string): (string | number)[] { const values = (value || "").trim().split(","); switch (opt.element.type) { case "number": @@ -590,9 +590,9 @@ namespace ts { */ export function parseJsonConfigFileContent(json: any, host: ParseConfigHost, basePath: string, existingOptions: CompilerOptions = {}, configFileName?: string): ParsedCommandLine { const errors: Diagnostic[] = []; - const compilerOptions: CompilerOptions = convertCompilerOptionsFromJson(optionDeclarations, json["compilerOptions"], basePath, configFileName, errors); + const compilerOptions: CompilerOptions = convertCompilerOptionsFromJson(optionDeclarations, json["compilerOptions"], basePath, errors, configFileName); const options = extend(existingOptions, compilerOptions); - const typingOptions: TypingOptions = convertTypingOptionsFromJson(typingOptionDeclarations, json["typingOptions"], basePath, configFileName, errors); + const typingOptions: TypingOptions = convertTypingOptionsFromJson(typingOptionDeclarations, json["typingOptions"], basePath, errors, configFileName); const fileNames = getFileNames(errors); @@ -667,27 +667,27 @@ namespace ts { } /* @internal */ - export function convertCompilerOptionsFromJson(optionsDeclarations: CommandLineOption[], jsonOptions: any, basePath: string, - configFileName: string, errors: Diagnostic[]): CompilerOptions { + export function convertCompilerOptionsFromJson(optionsDeclarations: CommandLineOption[], jsonOptions: any, + basePath: string, errors: Diagnostic[], configFileName?: string): CompilerOptions { const options: CompilerOptions = getBaseFileName(configFileName) === "jsconfig.json" ? { allowJs: true } : {}; - convertOptionsFromJson(optionDeclarations, jsonOptions, basePath, configFileName, options, Diagnostics.Unknown_compiler_option_0, errors); + convertOptionsFromJson(optionDeclarations, jsonOptions, basePath, options, Diagnostics.Unknown_compiler_option_0, errors); return options; } /* @internal */ - export function convertTypingOptionsFromJson(optionsDeclarations: CommandLineOption[], jsonOptions: any, basePath: string, - configFileName: string, errors: Diagnostic[]): TypingOptions { + export function convertTypingOptionsFromJson(optionsDeclarations: CommandLineOption[], jsonOptions: any, + basePath: string, errors: Diagnostic[], configFileName?: string): TypingOptions { const options: TypingOptions = getBaseFileName(configFileName) === "jsconfig.json" ? { enableAutoDiscovery: true, include: [], exclude: [] } : { enableAutoDiscovery: false, include: [], exclude: [] }; - convertOptionsFromJson(typingOptionDeclarations, jsonOptions, basePath, configFileName, options, Diagnostics.Unknown_typing_option_0, errors); + convertOptionsFromJson(typingOptionDeclarations, jsonOptions, basePath, options, Diagnostics.Unknown_typing_option_0, errors); return options; } function convertOptionsFromJson(optionDeclarations: CommandLineOption[], jsonOptions: any, basePath: string, - configFileName: string, defaultOptions: T, diagnosticMessage: DiagnosticMessage, errors: Diagnostic[]) { + defaultOptions: T, diagnosticMessage: DiagnosticMessage, errors: Diagnostic[]) { if (!jsonOptions) { return ; @@ -706,7 +706,7 @@ namespace ts { } } - function convertJsonOption(opt: CommandLineOption, value: any, basePath: string, errors: Diagnostic[]): number | string | number[] | string[] { + function convertJsonOption(opt: CommandLineOption, value: any, basePath: string, errors: Diagnostic[]): CompilerOptionsValue { const optType = opt.type; const expectedType = typeof optType === "string" ? optType : "string"; if (optType === "list" && isArray(value)) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 0fdcc6300b8..3fc172e39fd 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2381,6 +2381,8 @@ namespace ts { export type PathSubstitutions = Map; export type TsConfigOnlyOptions = RootPaths | PathSubstitutions; + export type CompilerOptionsValue = string | number | boolean | (string | number)[] | TsConfigOnlyOptions; + export interface CompilerOptions { allowNonTsExtensions?: boolean; charset?: string; @@ -2447,7 +2449,7 @@ namespace ts { list?: string[]; - [option: string]: string | number | boolean | TsConfigOnlyOptions | (string | number)[]; + [option: string]: CompilerOptionsValue; } export interface TypingOptions { diff --git a/tests/cases/unittests/convertCompilerOptionsFromJson.ts b/tests/cases/unittests/convertCompilerOptionsFromJson.ts index c68d8b97271..4edc3bdd200 100644 --- a/tests/cases/unittests/convertCompilerOptionsFromJson.ts +++ b/tests/cases/unittests/convertCompilerOptionsFromJson.ts @@ -5,7 +5,7 @@ namespace ts { describe('convertCompilerOptionsFromJson', () => { function assertCompilerOptions(json: any, configFileName: string, expectedResult: { compilerOptions: CompilerOptions, errors: Diagnostic[] }) { const actualErrors: Diagnostic[] = []; - const actualCompilerOptions: CompilerOptions = convertCompilerOptionsFromJson(optionDeclarations, json["compilerOptions"], "/apath/", configFileName, actualErrors); + const actualCompilerOptions: CompilerOptions = convertCompilerOptionsFromJson(optionDeclarations, json["compilerOptions"], "/apath/", actualErrors, configFileName); const parsedCompilerOptions = JSON.stringify(actualCompilerOptions); const expectedCompilerOptions = JSON.stringify(expectedResult.compilerOptions); diff --git a/tests/cases/unittests/convertTypingOptionsFromJson.ts b/tests/cases/unittests/convertTypingOptionsFromJson.ts index 898dee0a18b..92b450555a9 100644 --- a/tests/cases/unittests/convertTypingOptionsFromJson.ts +++ b/tests/cases/unittests/convertTypingOptionsFromJson.ts @@ -5,7 +5,7 @@ namespace ts { describe('convertTypingOptionsFromJson', () => { function assertTypingOptions(json: any, configFileName: string, expectedResult: { typingOptions: TypingOptions, errors: Diagnostic[] }) { const actualErrors: Diagnostic[] = []; - const actualTypingOptions = convertTypingOptionsFromJson(typingOptionDeclarations, json["typingOptions"], "/apath/", configFileName, actualErrors); + const actualTypingOptions = convertTypingOptionsFromJson(typingOptionDeclarations, json["typingOptions"], "/apath/", actualErrors, configFileName); const parsedTypingOptions = JSON.stringify(actualTypingOptions); const expectedTypingOptions = JSON.stringify(expectedResult.typingOptions); assert.equal(parsedTypingOptions, expectedTypingOptions);