From 684acffd19dba9d70fd063408e62da01dcdd562d Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Mon, 27 Jul 2015 19:52:25 +0800 Subject: [PATCH 1/9] Adds JSON with comments and trailing comma tests --- .../jsonWithCommentsAndTrailingCommas.ts | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 tests/cases/unittests/jsonWithCommentsAndTrailingCommas.ts diff --git a/tests/cases/unittests/jsonWithCommentsAndTrailingCommas.ts b/tests/cases/unittests/jsonWithCommentsAndTrailingCommas.ts new file mode 100644 index 0000000000000..2a3304e9baba2 --- /dev/null +++ b/tests/cases/unittests/jsonWithCommentsAndTrailingCommas.ts @@ -0,0 +1,72 @@ +/// +/// + +module ts { + describe("JSON with comments and trailing commas", () => { + it("should parse JSON with single line comments @jsonWithCommentsAndTrailingCommas", () => { + let json = +`{ + "a": { + // comment + "b": true + } +}`; + expect(parseConfigFileText("file.ts", json).config).to.be.deep.equal({ + a: { b: true } + }); + }); + + + it("should parse JSON with multiline line comments @jsonWithCommentsAndTrailingCommas", () => { + let json = +`{ + "a": { + /* + * comment + */ + "b": true + } +}`; + expect(parseConfigFileText("file.ts", json).config).to.be.deep.equal({ + a: { b: true } + }); + }); + + it("should parse JSON with trailing commas in an object @jsonWithCommentsAndTrailingCommas", () => { + let json = +`{ + "a": { + "b": true, + } +}`; + expect(parseConfigFileText("file.ts", json).config).to.be.deep.equal({ + a: { b: true } + }); + }); + + it("should parse JSON with trailing commas in an array @jsonWithCommentsAndTrailingCommas", () => { + let json = +`{ + "a": [ + "b", + ] +}`; + expect(parseConfigFileText("file.ts", json).config).to.be.deep.equal({ + a: [ "b" ] + }); + }); + + it("should parse JSON with escape characters @jsonWithCommentsAndTrailingCommas", () => { + let json = +`{ + "a": [ + "b\\\"\\\\", + ] +}`; + expect(parseConfigFileText("file.ts", json).config).to.be.deep.equal({ + a: [ "b\"\\" ] + }); + }); + }); +} + From e3d3cc920fbf478d53e36806ffb4b87d2d32c5c0 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Mon, 27 Jul 2015 19:52:39 +0800 Subject: [PATCH 2/9] Adds project init tests --- tests/cases/unittests/projectInit.ts | 180 +++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 tests/cases/unittests/projectInit.ts diff --git a/tests/cases/unittests/projectInit.ts b/tests/cases/unittests/projectInit.ts new file mode 100644 index 0000000000000..77ca3492819b2 --- /dev/null +++ b/tests/cases/unittests/projectInit.ts @@ -0,0 +1,180 @@ +/// +/// +/// + +module ts { + describe('Project initializer', () => { + interface ExpectedCompilerOptionsOutput { + [option: string]: string | boolean; + } + + function assertConfigFile( + compilerOptions: CompilerOptions, + fileNames: string[], + excludes: string[], + expectedCompilerOptionOutput: ExpectedCompilerOptionsOutput): void { + + let writer = createTextWriter("\n"); + let optionNameMap = getOptionNameMap().optionNameMap; + + buildConfigFile(writer, compilerOptions, fileNames, excludes); + + let expectedOutput = `{\n "compilerOptions": {\n`; + for (let option in expectedCompilerOptionOutput) { + let lowerCaseOption = option.toLowerCase() + if (optionNameMap[lowerCaseOption].description && + optionNameMap[lowerCaseOption].description.key) { + + expectedOutput += ` // ${optionNameMap[lowerCaseOption].description.key}\n`; + } + + expectedOutput += ` "${option}": `; + if (typeof expectedCompilerOptionOutput[option] === "string") { + expectedOutput += `"${expectedCompilerOptionOutput[option]}",\n`; + } + else { + expectedOutput += expectedCompilerOptionOutput[option].toString() + ",\n"; + } + } + expectedOutput += " }"; + + if (fileNames) { + expectedOutput += ",\n"; + expectedOutput += ` "files": [\n`; + for (let fileName of fileNames) { + expectedOutput += ` "${fileName}",\n`; + } + expectedOutput += " ]"; + } + + if (excludes) { + expectedOutput += ",\n"; + expectedOutput += ` "exclude": [\n`; + for (let exclude of excludes) { + expectedOutput += ` "${exclude}",\n`; + } + expectedOutput += " ]"; + } + expectedOutput += "\n}"; + + expect(writer.getText()).to.equal(expectedOutput); + } + + it("should generate default compiler options @projectInit", () => { + assertConfigFile( + {}, + null, + null, + { + module: "commonjs", + target: "es3", + noImplicitAny: true, + outDir: "built", + rootDir: ".", + sourceMap: false, + }); + }); + + it("should override default compiler options @projectInit", () => { + assertConfigFile( + { + module: ModuleKind.AMD, + target: ScriptTarget.ES5, + }, + null, + null, + { + module: "amd", // overrides commonjs + target: "es5", // overrides es3 + noImplicitAny: true, + outDir: "built", + rootDir: ".", + sourceMap: false, + }); + }); + + it("should be able to generate newline option @projectInit", () => { + assertConfigFile( + { + newLine: NewLineKind.CarriageReturnLineFeed + }, + null, + null, + { + newLine: "CRLF", + module: "commonjs", + target: "es3", + noImplicitAny: true, + outDir: "built", + rootDir: ".", + sourceMap: false, + }); + + assertConfigFile( + { + newLine: NewLineKind.LineFeed + }, + null, + null, + { + newLine: "LF", + module: "commonjs", + target: "es3", + noImplicitAny: true, + outDir: "built", + rootDir: ".", + sourceMap: false, + }); + }); + + it("should generate a `files` property @projectInit", () => { + assertConfigFile( + {}, + ["file1.ts", "file2.ts"], + null, + { + module: "commonjs", + target: "es3", + noImplicitAny: true, + outDir: "built", + rootDir: ".", + sourceMap: false + }); + }); + + it("should generete exclude options @projectInit", () => { + assertConfigFile( + {}, + null, + ["node_modules"], + { + module: "commonjs", + target: "es3", + noImplicitAny: true, + outDir: "built", + rootDir: ".", + sourceMap: false + }); + }); + + it("should not genereate compiler options for `version`, `watch`, `init` and `help` @projectInit", () => { + assertConfigFile( + { + version: true, + watch: true, + init: true, + help: true, + }, + null, + null, + { + module: "commonjs", + target: "es3", + noImplicitAny: true, + outDir: "built", + rootDir: ".", + sourceMap: false + }); + }); + }); +} \ No newline at end of file From 38f4c2dc8dd3244859a135bbe92c32fa4ac723b7 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Mon, 27 Jul 2015 19:52:57 +0800 Subject: [PATCH 3/9] Adds project init --- Jakefile.js | 20 +- src/compiler/commandLineParser.ts | 138 +++++++- .../diagnosticInformationMap.generated.ts | 2 + src/compiler/diagnosticMessages.json | 10 +- src/compiler/emitter.ts | 312 ++++++++++++++---- src/compiler/program.ts | 6 + src/compiler/tsc.ts | 11 + src/compiler/types.ts | 12 +- 8 files changed, 422 insertions(+), 89 deletions(-) diff --git a/Jakefile.js b/Jakefile.js index 8fbefe1b2ccad..e3f2e8c22c727 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -141,7 +141,9 @@ var harnessSources = harnessCoreSources.concat([ "session.ts", "versionCache.ts", "convertToBase64.ts", - "transpile.ts" + "transpile.ts", + "projectInit.ts", + "jsonWithCommentsAndTrailingCommas.ts" ].map(function (f) { return path.join(unittestsDirectory, f); })).concat([ @@ -339,10 +341,10 @@ file(diagnosticInfoMapTs, [processDiagnosticMessagesJs, diagnosticMessagesJson], complete(); }); ex.run(); -}, {async: true}); +}, {async: true}); desc("Generates a diagnostic file in TypeScript based on an input JSON file"); -task("generate-diagnostics", [diagnosticInfoMapTs]); +task("generate-diagnostics", [diagnosticInfoMapTs]); // Publish nightly @@ -479,11 +481,11 @@ file(specMd, [word2mdJs, specWord], function () { child_process.exec(cmd, function () { complete(); }); -}, {async: true}); +}, {async: true}); desc("Generates a Markdown version of the Language Specification"); -task("generate-spec", [specMd]); +task("generate-spec", [specMd]); // Makes a new LKG. This target does not build anything, but errors if not all the outputs are present in the built/local directory @@ -615,7 +617,7 @@ task("runtests", ["tests", builtLocalDirectory], function() { exec(cmd, deleteTemporaryProjectOutput); }, {async: true}); -desc("Generates code coverage data via instanbul"); +desc("Generates code coverage data via instanbul"); task("generate-code-coverage", ["tests", builtLocalDirectory], function () { var cmd = 'istanbul cover node_modules/mocha/bin/_mocha -- -R min -t ' + testTimeout + ' ' + run; console.log(cmd); @@ -658,7 +660,7 @@ task("runtests-browser", ["tests", "browserify", builtLocalDirectory], function( function getDiffTool() { var program = process.env['DIFF'] if (!program) { - fail("Add the 'DIFF' environment variable to the path of the program you want to use."); + fail("Add the 'DIFF' environment variable to the path of the program you want to use."); } return program; } @@ -667,14 +669,14 @@ function getDiffTool() { desc("Diffs the compiler baselines using the diff tool specified by the 'DIFF' environment variable"); task('diff', function () { var cmd = '"' + getDiffTool() + '" ' + refBaseline + ' ' + localBaseline; - console.log(cmd); + console.log(cmd); exec(cmd); }, {async: true}); desc("Diffs the RWC baselines using the diff tool specified by the 'DIFF' environment variable"); task('diff-rwc', function () { var cmd = '"' + getDiffTool() + '" ' + refRwcBaseline + ' ' + localRwcBaseline; - console.log(cmd); + console.log(cmd); exec(cmd); }, {async: true}); diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index ba7d8ca9ce347..6ba05473b7cb8 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -30,6 +30,11 @@ namespace ts { type: "boolean", description: Diagnostics.Print_this_message, }, + { + name: "init", + type: "boolean", + description: Diagnostics.Initializes_a_TypeScript_project_and_creates_a_tsconfig_json_file, + }, { name: "inlineSourceMap", type: "boolean", @@ -221,19 +226,36 @@ namespace ts { } ]; - export function parseCommandLine(commandLine: string[]): ParsedCommandLine { - let options: CompilerOptions = {}; - let fileNames: string[] = []; - let errors: Diagnostic[] = []; - let shortOptionNames: Map = {}; - let optionNameMap: Map = {}; + export interface OptionNameMap { + optionNameMap: Map; + shortOptionNames: Map; + } + + let optionNameMapCache: OptionNameMap; + export function getOptionNameMap(): OptionNameMap { + if (optionNameMapCache) { + return optionNameMapCache; + } + let optionNameMap: Map = {}; + let shortOptionNames: Map = {}; forEach(optionDeclarations, option => { optionNameMap[option.name.toLowerCase()] = option; if (option.shortName) { shortOptionNames[option.shortName] = option.name; } }); + + optionNameMapCache = { optionNameMap, shortOptionNames }; + return optionNameMapCache; + } + + export function parseCommandLine(commandLine: string[]): ParsedCommandLine { + let options: CompilerOptions = {}; + let fileNames: string[] = []; + let errors: Diagnostic[] = []; + let { optionNameMap, shortOptionNames } = getOptionNameMap(); + parseStrings(commandLine); return { options, @@ -345,6 +367,107 @@ namespace ts { return parseConfigFileText(fileName, text); } + /** + * Remove whitespace, comments and trailing commas from JSON text. + * @param text JSON text string. + */ + function stripJsonTrivia(text: string): string { + let ch: number; + let pos = 0; + let end = text.length - 1; + let result = ''; + let pendingCommaInsertion = false; + + while (pos <= end) { + ch = text.charCodeAt(pos); + + if(isWhiteSpace(ch) || isLineBreak(ch)) { + pos++; + continue; + } + + if(ch === CharacterCodes.slash) { + if (text.charCodeAt(pos + 1) === CharacterCodes.slash) { + pos += 2; + + while (pos <= end) { + if (isLineBreak(text.charCodeAt(pos))) { + break; + } + pos++; + } + continue; + } + else if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) { + pos += 2; + + while (pos <= end) { + ch = text.charCodeAt(pos); + + if (ch === CharacterCodes.asterisk && + text.charCodeAt(pos + 1) === CharacterCodes.slash) { + + pos += 2; + break; + } + pos++; + } + continue; + } + } + + if (pendingCommaInsertion) { + if (ch !== CharacterCodes.closeBracket && + ch !== CharacterCodes.closeBrace) { + + result += ','; + } + pendingCommaInsertion = false; + } + + switch (ch) { + case CharacterCodes.comma: + pendingCommaInsertion = true; + break; + + case CharacterCodes.doubleQuote: + result += text[pos]; + pos++; + + while (pos <= end) { + ch = text.charCodeAt(pos); + if (ch === CharacterCodes.backslash) { + switch (text.charCodeAt(pos + 1)) { + case CharacterCodes.doubleQuote: + result += "\\\""; + pos += 2; + continue; + case CharacterCodes.backslash: + result += "\\\\"; + pos += 2; + continue; + } + pos++; + } + result += text[pos]; + + if (ch === CharacterCodes.doubleQuote) { + break; + } + + pos++; + } + break; + + default: + result += text[pos]; + } + + pos++; + } + return result; + } + /** * Parse the text of the tsconfig.json file * @param fileName The path to the config file @@ -352,6 +475,7 @@ namespace ts { */ export function parseConfigFileText(fileName: string, jsonText: string): { config?: any; error?: Diagnostic } { try { + jsonText = stripJsonTrivia(jsonText); return { config: /\S/.test(jsonText) ? JSON.parse(jsonText) : {} }; } catch (e) { @@ -425,7 +549,7 @@ namespace ts { } else { let exclude = json["exclude"] instanceof Array ? map(json["exclude"], normalizeSlashes) : undefined; - let sysFiles = host.readDirectory(basePath, ".ts", exclude).concat(host.readDirectory(basePath, ".tsx", exclude)); + let sysFiles = host.readDirectory(basePath, ".ts", exclude).concat(host.readDirectory(basePath, ".tsx", exclude)); for (let i = 0; i < sysFiles.length; i++) { let name = sysFiles[i]; if (fileExtensionIs(name, ".d.ts")) { diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index ecea3a766730c..c2fe4c57b2172 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -517,6 +517,7 @@ namespace ts { Option_sourceRoot_cannot_be_specified_with_option_inlineSourceMap: { code: 5049, category: DiagnosticCategory.Error, key: "Option 'sourceRoot' cannot be specified with option 'inlineSourceMap'." }, Option_mapRoot_cannot_be_specified_with_option_inlineSourceMap: { code: 5050, category: DiagnosticCategory.Error, key: "Option 'mapRoot' cannot be specified with option 'inlineSourceMap'." }, Option_inlineSources_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided: { code: 5051, category: DiagnosticCategory.Error, key: "Option 'inlineSources' can only be used when either option '--inlineSourceMap' or option '--sourceMap' is provided." }, + You_already_have_a_tsconfig_json_file_defined: { code: 5052, category: DiagnosticCategory.Error, key: "You already have a tsconfig.json file defined." }, Concatenate_and_emit_output_to_single_file: { code: 6001, category: DiagnosticCategory.Message, key: "Concatenate and emit output to single file." }, Generates_corresponding_d_ts_file: { code: 6002, category: DiagnosticCategory.Message, key: "Generates corresponding '.d.ts' file." }, Specifies_the_location_where_debugger_should_locate_map_files_instead_of_generated_locations: { code: 6003, category: DiagnosticCategory.Message, key: "Specifies the location where debugger should locate map files instead of generated locations." }, @@ -572,6 +573,7 @@ namespace ts { Enables_experimental_support_for_emitting_type_metadata_for_decorators: { code: 6066, category: DiagnosticCategory.Message, key: "Enables experimental support for emitting type metadata for decorators." }, Option_experimentalAsyncFunctions_cannot_be_specified_when_targeting_ES5_or_lower: { code: 6067, category: DiagnosticCategory.Message, key: "Option 'experimentalAsyncFunctions' cannot be specified when targeting ES5 or lower." }, Enables_experimental_support_for_ES7_async_functions: { code: 6068, category: DiagnosticCategory.Message, key: "Enables experimental support for ES7 async functions." }, + Initializes_a_TypeScript_project_and_creates_a_tsconfig_json_file: { code: 6069, category: DiagnosticCategory.Message, key: "Initializes a TypeScript project and creates a tsconfig.json file." }, Variable_0_implicitly_has_an_1_type: { code: 7005, category: DiagnosticCategory.Error, key: "Variable '{0}' implicitly has an '{1}' type." }, Parameter_0_implicitly_has_an_1_type: { code: 7006, category: DiagnosticCategory.Error, key: "Parameter '{0}' implicitly has an '{1}' type." }, Member_0_implicitly_has_an_1_type: { code: 7008, category: DiagnosticCategory.Error, key: "Member '{0}' implicitly has an '{1}' type." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 2765d04f4003e..b59fb2313749f 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -161,7 +161,7 @@ }, "Type '{0}' is not a valid async function return type.": { "category": "Error", - "code": 1055 + "code": 1055 }, "Accessors are only available when targeting ECMAScript 5 and higher.": { "category": "Error", @@ -2057,6 +2057,10 @@ "category": "Error", "code": 5051 }, + "You already have a tsconfig.json file defined.": { + "category": "Error", + "code": 5052 + }, "Concatenate and emit output to single file.": { "category": "Message", @@ -2278,6 +2282,10 @@ "category": "Message", "code": 6068 }, + "Initializes a TypeScript project and creates a tsconfig.json file.": { + "category": "Message", + "code": 6069 + }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index e97ece5bf0022..8f1d39379dd2c 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -3,6 +3,190 @@ /* @internal */ namespace ts { + export const defaultInitCompilerOptions: CompilerOptions = { + module: ModuleKind.CommonJS, + target: ScriptTarget.ES3, + noImplicitAny: true, + outDir: "built", + rootDir: ".", + sourceMap: false, + } + + export function buildConfigFile(writer: EmitTextWriter, compilerOptions: CompilerOptions, fileNames?: string[], excludes?: string[]) { + compilerOptions = extend(compilerOptions, defaultInitCompilerOptions); + let { write, writeLine, increaseIndent, decreaseIndent } = writer; + let { optionNameMap } = getOptionNameMap(); + writeTsConfigDotJsonFile(); + + function writeTsConfigDotJsonFile() { + write("{"); + writeLine(); + increaseIndent(); + writeCompilerOptions(); + if (fileNames) { + write(","); + writeLine(); + writeFileNames(); + } + if (excludes) { + write(","); + writeLine(); + writeExcludeOptions(); + } + writeLine(); + decreaseIndent(); + write("}"); + } + + function writeCompilerOptions() { + write(`"compilerOptions": {`); + writeLine(); + increaseIndent(); + + for (var option in compilerOptions) { + switch (option) { + case "init": + case "watch": + case "help": + case "version": + continue; + + case "module": + case "target": + case "newLine": + writeComplexCompilerOption(option); + break; + + default: + writeSimpleCompilerOption(option); + } + } + + decreaseIndent(); + write("}"); + } + + function writeOptionalOptionDescription(option: string) { + option = option.toLowerCase(); + if (optionNameMap[option].description && + optionNameMap[option].description.key) { + + write(`// ${optionNameMap[option].description.key}`); + writeLine(); + } + } + + /** + * Write simple compiler option. A simple compiler option is an option + * with boolean or non string set value. + */ + function writeSimpleCompilerOption(option: string) { + writeOptionalOptionDescription(option); + + write(`"${option}": `); + if (typeof compilerOptions[option] === "string") { + write(`"${compilerOptions[option]}",`); + writeLine(); + } + else { + if (compilerOptions[option]) { + write("true,"); + } + else { + write("false,"); + } + writeLine(); + } + } + + function writeComplexCompilerOption(option: string) { + writeOptionalOptionDescription(option); + + outer: switch (option) { + case "module": + var moduleValue: string; + switch (compilerOptions.module) { + case ModuleKind.None: + break outer; + case ModuleKind.CommonJS: + moduleValue = "commonjs"; + break; + case ModuleKind.System: + moduleValue = "system"; + break; + case ModuleKind.UMD: + moduleValue = "umd"; + break; + default: + moduleValue = "amd"; + break; + } + write(`"module": "${moduleValue}",`); + writeLine(); + break; + + case "target": + var targetValue: string; + switch (compilerOptions.target) { + case ScriptTarget.ES5: + targetValue = "es5"; + break; + case ScriptTarget.ES6: + targetValue = "es6"; + break; + default: + targetValue = "es3"; + break; + } + write(`"target": "${targetValue}",`); + writeLine(); + break; + + case "newLine": + var newlineValue: string; + switch (compilerOptions.newLine) { + case NewLineKind.CarriageReturnLineFeed: + newlineValue = "CRLF"; + break; + default: + newlineValue = "LF"; + break; + } + write(`"newLine": "${newlineValue}",`); + writeLine(); + break; + } + } + + function writeFileNames() { + write(`"files": [`); + writeLine(); + increaseIndent(); + + for (let fileName of fileNames) { + write(`"${fileName}",`); + writeLine(); + } + + decreaseIndent(); + write("]"); + } + + function writeExcludeOptions() { + write(`"exclude": [`); + writeLine(); + increaseIndent(); + + for (let exclude of excludes) { + write(`"${exclude}",`); + writeLine(); + } + + decreaseIndent(); + write("]"); + } + } + export function isExternalModuleOrDeclarationFile(sourceFile: SourceFile) { return isExternalModule(sourceFile) || isDeclarationFile(sourceFile); } @@ -124,11 +308,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi function emitJavaScript(jsFilePath: string, root?: SourceFile) { let writer = createTextWriter(newLine); - let write = writer.write; - let writeTextOfNode = writer.writeTextOfNode; - let writeLine = writer.writeLine; - let increaseIndent = writer.increaseIndent; - let decreaseIndent = writer.decreaseIndent; + let { write, writeTextOfNode, writeLine, increaseIndent, decreaseIndent } = writer; let currentSourceFile: SourceFile; // name of an exporter function if file is a System external module @@ -2070,7 +2250,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emit(node.name); decreaseIndentIf(indentedBeforeDot, indentedAfterDot); } - + function emitQualifiedName(node: QualifiedName) { emit(node.left); write("."); @@ -2093,12 +2273,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi else { emitEntityNameAsExpression(node.left, /*useFallback*/ false); } - + write("."); emitNodeWithoutSourceMap(node.right); } - - function emitEntityNameAsExpression(node: EntityName, useFallback: boolean) { + + function emitEntityNameAsExpression(node: EntityName, useFallback: boolean) { switch (node.kind) { case SyntaxKind.Identifier: if (useFallback) { @@ -2106,10 +2286,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi emitExpressionIdentifier(node); write(" !== 'undefined' && "); } - + emitExpressionIdentifier(node); break; - + case SyntaxKind.QualifiedName: emitQualifiedNameAsExpression(node, useFallback); break; @@ -3020,7 +3200,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi if (compilerOptions.module === ModuleKind.CommonJS || compilerOptions.module === ModuleKind.AMD || compilerOptions.module === ModuleKind.UMD) { if (!currentSourceFile.symbol.exports["___esModule"]) { if (languageVersion === ScriptTarget.ES5) { - // default value of configurable, enumerable, writable are `false`. + // default value of configurable, enumerable, writable are `false`. write("Object.defineProperty(exports, \"__esModule\", { value: true });"); writeLine(); } @@ -4250,7 +4430,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi if (ctor) { // Emit all the directive prologues (like "use strict"). These have to come before // any other preamble code we write (like parameter initializers). - startIndex = emitDirectivePrologues(ctor.body.statements, /*startWithNewLine*/ true); + startIndex = emitDirectivePrologues(ctor.body.statements, /*startWithNewLine*/ true); emitDetachedComments(ctor.body.statements); } emitCaptureThisForNodeIfNecessary(node); @@ -4821,7 +5001,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } return false; } - + /** Serializes the type of a declaration to an appropriate JS constructor value. Used by the __metadata decorator for a class member. */ function emitSerializedTypeOfNode(node: Node) { // serialization of the type of a declaration uses the following rules: @@ -4832,39 +5012,39 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi // * The serialized type of an AccessorDeclaration is the serialized type of the return type annotation of its getter or parameter type annotation of its setter. // * The serialized type of any other FunctionLikeDeclaration is "Function". // * The serialized type of any other node is "void 0". - // + // // For rules on serializing type annotations, see `serializeTypeNode`. switch (node.kind) { case SyntaxKind.ClassDeclaration: write("Function"); return; - - case SyntaxKind.PropertyDeclaration: + + case SyntaxKind.PropertyDeclaration: emitSerializedTypeNode((node).type); return; - - case SyntaxKind.Parameter: + + case SyntaxKind.Parameter: emitSerializedTypeNode((node).type); return; - - case SyntaxKind.GetAccessor: + + case SyntaxKind.GetAccessor: emitSerializedTypeNode((node).type); return; - - case SyntaxKind.SetAccessor: + + case SyntaxKind.SetAccessor: emitSerializedTypeNode(getSetAccessorTypeAnnotationNode(node)); return; - + } - + if (isFunctionLike(node)) { write("Function"); return; } - + write("void 0"); } - + function emitSerializedTypeNode(node: TypeNode) { switch (node.kind) { case SyntaxKind.VoidKeyword: @@ -4874,17 +5054,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi case SyntaxKind.ParenthesizedType: emitSerializedTypeNode((node).type); return; - + case SyntaxKind.FunctionType: case SyntaxKind.ConstructorType: write("Function"); return; - + case SyntaxKind.ArrayType: case SyntaxKind.TupleType: write("Array"); return; - + case SyntaxKind.TypePredicate: case SyntaxKind.BooleanKeyword: write("Boolean"); @@ -4894,11 +5074,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi case SyntaxKind.StringLiteral: write("String"); return; - + case SyntaxKind.NumberKeyword: write("Number"); return; - + case SyntaxKind.SymbolKeyword: write("Symbol"); return; @@ -4906,22 +5086,22 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi case SyntaxKind.TypeReference: emitSerializedTypeReferenceNode(node); return; - + case SyntaxKind.TypeQuery: case SyntaxKind.TypeLiteral: case SyntaxKind.UnionType: case SyntaxKind.IntersectionType: case SyntaxKind.AnyKeyword: break; - + default: Debug.fail("Cannot serialize unexpected type node."); break; } - + write("Object"); } - + /** Serializes a TypeReferenceNode to an appropriate JS constructor value. Used by the __metadata decorator. */ function emitSerializedTypeReferenceNode(node: TypeReferenceNode) { let typeName = node.typeName; @@ -4941,27 +5121,27 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi case TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue: emitEntityNameAsExpression(typeName, /*useFallback*/ false); break; - + case TypeReferenceSerializationKind.VoidType: write("void 0"); break; - + case TypeReferenceSerializationKind.BooleanType: write("Boolean"); break; - + case TypeReferenceSerializationKind.NumberLikeType: write("Number"); break; - + case TypeReferenceSerializationKind.StringLikeType: write("String"); break; - + case TypeReferenceSerializationKind.ArrayLikeType: write("Array"); break; - + case TypeReferenceSerializationKind.ESSymbolType: if (languageVersion < ScriptTarget.ES6) { write("typeof Symbol === 'function' ? Symbol : Object"); @@ -4970,24 +5150,24 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write("Symbol"); } break; - + case TypeReferenceSerializationKind.TypeWithCallSignature: write("Function"); break; - + case TypeReferenceSerializationKind.ObjectType: write("Object"); break; } } - + /** Serializes the parameter types of a function or the constructor of a class. Used by the __metadata decorator for a method or set accessor. */ function emitSerializedParameterTypesOfNode(node: Node) { // serialization of parameter types uses the following rules: // // * If the declaration is a class, the parameters of the first constructor with a body are used. // * If the declaration is function-like and has a body, the parameters of the function are used. - // + // // For the rules on serializing the type of each parameter declaration, see `serializeTypeOfDeclaration`. if (node) { var valueDeclaration: FunctionLikeDeclaration; @@ -4997,7 +5177,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi else if (isFunctionLike(node) && nodeIsPresent((node).body)) { valueDeclaration = node; } - + if (valueDeclaration) { var parameters = valueDeclaration.parameters; var parameterCount = parameters.length; @@ -5006,7 +5186,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi if (i > 0) { write(", "); } - + if (parameters[i].dotDotDotToken) { var parameterType = parameters[i].type; if (parameterType.kind === SyntaxKind.ArrayType) { @@ -5018,7 +5198,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi else { parameterType = undefined; } - + emitSerializedTypeNode(parameterType); } else { @@ -5029,18 +5209,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } } } - + /** Serializes the return type of function. Used by the __metadata decorator for a method. */ function emitSerializedReturnTypeOfNode(node: Node): string | string[] { if (node && isFunctionLike(node)) { emitSerializedTypeNode((node).type); return; } - + write("void 0"); } - - + + function emitSerializedTypeMetadata(node: Declaration, writeComma: boolean): number { // This method emits the serialized type metadata for a decorator target. // The caller should have already tested whether the node has decorators. @@ -5070,7 +5250,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi if (writeComma || argumentsWritten) { write(", "); } - + writeLine(); write("__metadata('design:returntype', "); emitSerializedReturnTypeOfNode(node); @@ -5078,10 +5258,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi argumentsWritten++; } } - + return argumentsWritten; } - + function emitInterfaceDeclaration(node: InterfaceDeclaration) { emitOnlyPinnedOrTripleSlashComments(node); } @@ -5430,18 +5610,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi (!isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportEqualsWithEntityName(node))) { emitLeadingComments(node); emitStart(node); - + // variable declaration for import-equals declaration can be hoisted in system modules // in this case 'var' should be omitted and emit should contain only initialization let variableDeclarationIsHoisted = shouldHoistVariable(node, /*checkIfSourceFileLevelDecl*/ true); - + // is it top level export import v = a.b.c in system module? // if yes - it needs to be rewritten as exporter('v', v = a.b.c) let isExported = isSourceFileLevelDeclarationInSystemJsModule(node, /*isExported*/ true); - + if (!variableDeclarationIsHoisted) { Debug.assert(!isExported); - + if (isES6ExportedDeclaration(node)) { write("export "); write("var "); @@ -5450,8 +5630,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi write("var "); } } - - + + if (isExported) { write(`${exportFunctionForFile}("`); emitNodeWithoutSourceMap(node.name); @@ -5465,8 +5645,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi if (isExported) { write(")"); } - - write(";"); + + write(";"); emitEnd(node); emitExportImportAssignments(node); emitTrailingComments(node); @@ -5992,12 +6172,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi } return; } - + if (isInternalModuleImportEqualsDeclaration(node)) { if (!hoistedVars) { hoistedVars = []; } - + hoistedVars.push(node.name); return; } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 4b1f10eb649bc..ce6dac19f91f9 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -26,6 +26,12 @@ namespace ts { return undefined; } + export function writeConfigFile(file: string, compilerOptions: CompilerOptions, fileNames: string[]): void { + let writer = createTextWriter("\n"); + buildConfigFile(writer, compilerOptions, fileNames, ["node_modules"]); + sys.writeFile(file, writer.getText()); + } + export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost { let currentDirectory: string; let existingDirectories: Map = {}; diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index a657cc8c314b9..676538a6859b4 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -144,6 +144,17 @@ namespace ts { let hostGetSourceFile: typeof compilerHost.getSourceFile; // getSourceFile method from default host let timerHandle: number; // Handle for 0.25s wait timer + if (commandLine.options.init) { + let file = `${sys.getCurrentDirectory()}/tsconfig.json`; + if (sys.fileExists(file)) { + reportDiagnostic(createCompilerDiagnostic(Diagnostics.You_already_have_a_tsconfig_json_file_defined)); + } + else { + writeConfigFile(file, commandLine.options, commandLine.fileNames); + } + return sys.exit(ExitStatus.Success); + } + if (commandLine.options.locale) { if (!isJSONSupported()) { reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--locale")); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 21eed30c24432..7735f84c74d2d 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1529,8 +1529,8 @@ namespace ts { export interface SymbolAccessiblityResult extends SymbolVisibilityResult { errorModuleName?: string; // If the symbol is not visible from module, module's name } - - /** Indicates how to serialize the name for a TypeReferenceNode when emitting decorator + + /** Indicates how to serialize the name for a TypeReferenceNode when emitting decorator * metadata */ /* @internal */ export enum TypeReferenceSerializationKind { @@ -1574,7 +1574,7 @@ namespace ts { getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number; getBlockScopedVariableId(node: Identifier): number; getReferencedValueDeclaration(reference: Identifier): Declaration; - getTypeReferenceSerializationKind(node: TypeReferenceNode): TypeReferenceSerializationKind; + getTypeReferenceSerializationKind(node: TypeReferenceNode): TypeReferenceSerializationKind; } export const enum SymbolFlags { @@ -1777,10 +1777,10 @@ namespace ts { StringLike = String | StringLiteral, NumberLike = Number | Enum, ObjectType = Class | Interface | Reference | Tuple | Anonymous, - UnionOrIntersection = Union | Intersection, + UnionOrIntersection = Union | Intersection, StructuredType = ObjectType | Union | Intersection, /* @internal */ - RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral + RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral } // Properties common to all types @@ -1989,6 +1989,7 @@ namespace ts { diagnostics?: boolean; emitBOM?: boolean; help?: boolean; + init?: boolean; inlineSourceMap?: boolean; inlineSources?: boolean; jsx?: JsxEmit; @@ -2073,7 +2074,6 @@ namespace ts { errors: Diagnostic[]; } - /* @internal */ export interface CommandLineOption { name: string; type: string | Map; // "string", "number", "boolean", or an object literal mapping named values to actual values From 5daf3f11018c239c2e479818d7cdc9085d43de81 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Mon, 27 Jul 2015 20:18:21 +0800 Subject: [PATCH 4/9] Defaults to no files property --- src/compiler/emitter.ts | 2 +- tests/cases/unittests/projectInit.ts | 62 ++++++++++++++++++++++------ 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 8f1d39379dd2c..46a44d7b26885 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -23,7 +23,7 @@ namespace ts { writeLine(); increaseIndent(); writeCompilerOptions(); - if (fileNames) { + if (fileNames && fileNames.length > 0) { write(","); writeLine(); writeFileNames(); diff --git a/tests/cases/unittests/projectInit.ts b/tests/cases/unittests/projectInit.ts index 77ca3492819b2..a0334c7ff1663 100644 --- a/tests/cases/unittests/projectInit.ts +++ b/tests/cases/unittests/projectInit.ts @@ -12,7 +12,9 @@ module ts { compilerOptions: CompilerOptions, fileNames: string[], excludes: string[], - expectedCompilerOptionOutput: ExpectedCompilerOptionsOutput): void { + expectedCompilerOptionOutput: ExpectedCompilerOptionsOutput, + expectedFileNames: string[], + expectedExcludes: string[]): void { let writer = createTextWriter("\n"); let optionNameMap = getOptionNameMap().optionNameMap; @@ -38,10 +40,10 @@ module ts { } expectedOutput += " }"; - if (fileNames) { + if (expectedFileNames) { expectedOutput += ",\n"; expectedOutput += ` "files": [\n`; - for (let fileName of fileNames) { + for (let fileName of expectedFileNames) { expectedOutput += ` "${fileName}",\n`; } expectedOutput += " ]"; @@ -72,7 +74,9 @@ module ts { outDir: "built", rootDir: ".", sourceMap: false, - }); + }, + null, + null); }); it("should override default compiler options @projectInit", () => { @@ -90,7 +94,9 @@ module ts { outDir: "built", rootDir: ".", sourceMap: false, - }); + }, + null, + null); }); it("should be able to generate newline option @projectInit", () => { @@ -108,7 +114,9 @@ module ts { outDir: "built", rootDir: ".", sourceMap: false, - }); + }, + null, + null); assertConfigFile( { @@ -124,7 +132,9 @@ module ts { outDir: "built", rootDir: ".", sourceMap: false, - }); + }, + null, + null); }); it("should generate a `files` property @projectInit", () => { @@ -139,10 +149,12 @@ module ts { outDir: "built", rootDir: ".", sourceMap: false - }); + }, + ["file1.ts", "file2.ts"], + null); }); - it("should generete exclude options @projectInit", () => { + it("should generate exclude options @projectInit", () => { assertConfigFile( {}, null, @@ -154,10 +166,12 @@ module ts { outDir: "built", rootDir: ".", sourceMap: false - }); + }, + null, + ["node_modules"]); }); - it("should not genereate compiler options for `version`, `watch`, `init` and `help` @projectInit", () => { + it("should not generate compiler options for `version`, `watch`, `init` and `help` @projectInit", () => { assertConfigFile( { version: true, @@ -174,7 +188,31 @@ module ts { outDir: "built", rootDir: ".", sourceMap: false - }); + }, + null, + null); + }); + + it("should not generate a files property if the files length is zero @projectInit", () => { + assertConfigFile( + { + version: true, + watch: true, + init: true, + help: true, + }, + [], + null, + { + module: "commonjs", + target: "es3", + noImplicitAny: true, + outDir: "built", + rootDir: ".", + sourceMap: false + }, + null, + null); }); }); } \ No newline at end of file From db6e46df120bbec4fa9325315e5887e1d256143a Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Wed, 29 Jul 2015 10:26:18 +0800 Subject: [PATCH 5/9] Removes trailing comma logic and fixes default values --- Jakefile.js | 2 +- src/compiler/commandLineParser.ts | 56 ++--- src/compiler/emitter.ts | 184 --------------- src/compiler/program.ts | 218 +++++++++++++++++- src/compiler/tsc.ts | 4 +- ...dTrailingCommas.ts => jsonWithComments.ts} | 24 -- tests/cases/unittests/projectInit.ts | 46 ++-- 7 files changed, 268 insertions(+), 266 deletions(-) rename tests/cases/unittests/{jsonWithCommentsAndTrailingCommas.ts => jsonWithComments.ts} (65%) diff --git a/Jakefile.js b/Jakefile.js index e3f2e8c22c727..4f922dd3ab880 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -143,7 +143,7 @@ var harnessSources = harnessCoreSources.concat([ "convertToBase64.ts", "transpile.ts", "projectInit.ts", - "jsonWithCommentsAndTrailingCommas.ts" + "jsonWithComments.ts" ].map(function (f) { return path.join(unittestsDirectory, f); })).concat([ diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 6ba05473b7cb8..38faf0a43fbb2 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -386,49 +386,35 @@ namespace ts { continue; } - if(ch === CharacterCodes.slash) { - if (text.charCodeAt(pos + 1) === CharacterCodes.slash) { - pos += 2; + switch (ch) { + case CharacterCodes.slash: + if (text.charCodeAt(pos + 1) === CharacterCodes.slash) { + pos += 2; - while (pos <= end) { - if (isLineBreak(text.charCodeAt(pos))) { - break; + while (pos <= end) { + if (isLineBreak(text.charCodeAt(pos))) { + break; + } + pos++; } - pos++; + break; } - continue; - } - else if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) { - pos += 2; + else if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) { + pos += 2; - while (pos <= end) { - ch = text.charCodeAt(pos); + while (pos <= end) { + ch = text.charCodeAt(pos); - if (ch === CharacterCodes.asterisk && - text.charCodeAt(pos + 1) === CharacterCodes.slash) { + if (ch === CharacterCodes.asterisk && + text.charCodeAt(pos + 1) === CharacterCodes.slash) { - pos += 2; - break; + pos += 2; + break; + } + pos++; } - pos++; + break; } - continue; - } - } - - if (pendingCommaInsertion) { - if (ch !== CharacterCodes.closeBracket && - ch !== CharacterCodes.closeBrace) { - - result += ','; - } - pendingCommaInsertion = false; - } - - switch (ch) { - case CharacterCodes.comma: - pendingCommaInsertion = true; - break; case CharacterCodes.doubleQuote: result += text[pos]; diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 46a44d7b26885..b707fc7789491 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -3,190 +3,6 @@ /* @internal */ namespace ts { - export const defaultInitCompilerOptions: CompilerOptions = { - module: ModuleKind.CommonJS, - target: ScriptTarget.ES3, - noImplicitAny: true, - outDir: "built", - rootDir: ".", - sourceMap: false, - } - - export function buildConfigFile(writer: EmitTextWriter, compilerOptions: CompilerOptions, fileNames?: string[], excludes?: string[]) { - compilerOptions = extend(compilerOptions, defaultInitCompilerOptions); - let { write, writeLine, increaseIndent, decreaseIndent } = writer; - let { optionNameMap } = getOptionNameMap(); - writeTsConfigDotJsonFile(); - - function writeTsConfigDotJsonFile() { - write("{"); - writeLine(); - increaseIndent(); - writeCompilerOptions(); - if (fileNames && fileNames.length > 0) { - write(","); - writeLine(); - writeFileNames(); - } - if (excludes) { - write(","); - writeLine(); - writeExcludeOptions(); - } - writeLine(); - decreaseIndent(); - write("}"); - } - - function writeCompilerOptions() { - write(`"compilerOptions": {`); - writeLine(); - increaseIndent(); - - for (var option in compilerOptions) { - switch (option) { - case "init": - case "watch": - case "help": - case "version": - continue; - - case "module": - case "target": - case "newLine": - writeComplexCompilerOption(option); - break; - - default: - writeSimpleCompilerOption(option); - } - } - - decreaseIndent(); - write("}"); - } - - function writeOptionalOptionDescription(option: string) { - option = option.toLowerCase(); - if (optionNameMap[option].description && - optionNameMap[option].description.key) { - - write(`// ${optionNameMap[option].description.key}`); - writeLine(); - } - } - - /** - * Write simple compiler option. A simple compiler option is an option - * with boolean or non string set value. - */ - function writeSimpleCompilerOption(option: string) { - writeOptionalOptionDescription(option); - - write(`"${option}": `); - if (typeof compilerOptions[option] === "string") { - write(`"${compilerOptions[option]}",`); - writeLine(); - } - else { - if (compilerOptions[option]) { - write("true,"); - } - else { - write("false,"); - } - writeLine(); - } - } - - function writeComplexCompilerOption(option: string) { - writeOptionalOptionDescription(option); - - outer: switch (option) { - case "module": - var moduleValue: string; - switch (compilerOptions.module) { - case ModuleKind.None: - break outer; - case ModuleKind.CommonJS: - moduleValue = "commonjs"; - break; - case ModuleKind.System: - moduleValue = "system"; - break; - case ModuleKind.UMD: - moduleValue = "umd"; - break; - default: - moduleValue = "amd"; - break; - } - write(`"module": "${moduleValue}",`); - writeLine(); - break; - - case "target": - var targetValue: string; - switch (compilerOptions.target) { - case ScriptTarget.ES5: - targetValue = "es5"; - break; - case ScriptTarget.ES6: - targetValue = "es6"; - break; - default: - targetValue = "es3"; - break; - } - write(`"target": "${targetValue}",`); - writeLine(); - break; - - case "newLine": - var newlineValue: string; - switch (compilerOptions.newLine) { - case NewLineKind.CarriageReturnLineFeed: - newlineValue = "CRLF"; - break; - default: - newlineValue = "LF"; - break; - } - write(`"newLine": "${newlineValue}",`); - writeLine(); - break; - } - } - - function writeFileNames() { - write(`"files": [`); - writeLine(); - increaseIndent(); - - for (let fileName of fileNames) { - write(`"${fileName}",`); - writeLine(); - } - - decreaseIndent(); - write("]"); - } - - function writeExcludeOptions() { - write(`"exclude": [`); - writeLine(); - increaseIndent(); - - for (let exclude of excludes) { - write(`"${exclude}",`); - writeLine(); - } - - decreaseIndent(); - write("]"); - } - } - export function isExternalModuleOrDeclarationFile(sourceFile: SourceFile) { return isExternalModule(sourceFile) || isDeclarationFile(sourceFile); } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index ce6dac19f91f9..70b89db4eaf7a 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1,5 +1,6 @@ /// /// +/// namespace ts { /* @internal */ export let programTime = 0; @@ -26,10 +27,219 @@ namespace ts { return undefined; } - export function writeConfigFile(file: string, compilerOptions: CompilerOptions, fileNames: string[]): void { - let writer = createTextWriter("\n"); - buildConfigFile(writer, compilerOptions, fileNames, ["node_modules"]); - sys.writeFile(file, writer.getText()); + export const defaultInitCompilerOptions: CompilerOptions = { + module: ModuleKind.CommonJS, + target: ScriptTarget.ES3, + noImplicitAny: false, + outDir: "built", + rootDir: ".", + sourceMap: false, + } + + export function buildConfigFile(writer: EmitTextWriter, compilerOptions: CompilerOptions, fileNames?: string[], excludes?: string[]) { + compilerOptions = extend(compilerOptions, defaultInitCompilerOptions); + let { write, writeLine, increaseIndent, decreaseIndent } = writer; + let { optionNameMap } = getOptionNameMap(); + writeConfigFile(); + + function writeConfigFile() { + write("{"); + writeLine(); + increaseIndent(); + writeCompilerOptions(); + if (fileNames && fileNames.length > 0) { + write(","); + writeLine(); + writeFileNames(); + } + if (excludes) { + write(","); + writeLine(); + writeExcludeOptions(); + } + writeLine(); + decreaseIndent(); + write("}"); + } + + function writeCompilerOptions() { + write(`"compilerOptions": {`); + writeLine(); + increaseIndent(); + + let length = 0; + for (var option in compilerOptions) { + length++; + } + + let i = 0; + for (var option in compilerOptions) { + switch (option) { + case "init": + case "watch": + case "help": + case "version": + i++; + continue; + + case "module": + case "target": + case "newLine": + writeComplexCompilerOption(option, i < length - 1); + break; + + default: + writeSimpleCompilerOption(option, i < length - 1); + + } + i++; + } + + decreaseIndent(); + write("}"); + } + + function writeOptionalOptionDescription(option: string) { + option = option.toLowerCase(); + if (optionNameMap[option].description && + optionNameMap[option].description.key) { + + write(`// ${optionNameMap[option].description.key}`); + writeLine(); + } + } + + /** + * Write simple compiler option. A simple compiler option is an option + * with boolean or non string set value. + */ + function writeSimpleCompilerOption(option: string, writeComma: boolean) { + writeOptionalOptionDescription(option); + + write(`"${option}": `); + if (typeof compilerOptions[option] === "string") { + write(`"${compilerOptions[option]}"`); + } + else { + if (compilerOptions[option]) { + write("true"); + } + else { + write("false"); + } + } + + if (writeComma) { + write(","); + } + writeLine(); + } + + /** + * Write complex compiler option. A complex compiler option is an option + * which maps to a TypeScript enum type. + */ + function writeComplexCompilerOption(option: string, writeComma: boolean) { + writeOptionalOptionDescription(option); + + outer: switch (option) { + case "module": + var moduleValue: string; + switch (compilerOptions.module) { + case ModuleKind.None: + break outer; + case ModuleKind.CommonJS: + moduleValue = "commonjs"; + break; + case ModuleKind.System: + moduleValue = "system"; + break; + case ModuleKind.UMD: + moduleValue = "umd"; + break; + default: + moduleValue = "amd"; + break; + } + write(`"module": "${moduleValue}"`); + if (writeComma) { + write(","); + } + writeLine(); + break; + + case "target": + var targetValue: string; + switch (compilerOptions.target) { + case ScriptTarget.ES5: + targetValue = "es5"; + break; + case ScriptTarget.ES6: + targetValue = "es6"; + break; + default: + targetValue = "es3"; + break; + } + write(`"target": "${targetValue}"`); + if (writeComma) { + write(","); + } + writeLine(); + break; + + case "newLine": + var newlineValue: string; + switch (compilerOptions.newLine) { + case NewLineKind.CarriageReturnLineFeed: + newlineValue = "CRLF"; + break; + default: + newlineValue = "LF"; + break; + } + write(`"newLine": "${newlineValue}"`); + if (writeComma) { + write(","); + } + writeLine(); + break; + } + } + + function writeFileNames() { + write(`"files": [`); + writeLine(); + increaseIndent(); + + forEach(fileNames, (fileName, index) => { + write(`"${fileName}"`); + if (index < fileNames.length - 1) { + write(","); + } + writeLine(); + }); + + decreaseIndent(); + write("]"); + } + + function writeExcludeOptions() { + write(`"exclude": [`); + writeLine(); + increaseIndent(); + + forEach(excludes, (exclude, index) => { + write(`"${exclude}"`); + if (index < excludes.length - 1) { + write(","); + } + writeLine(); + }); + + decreaseIndent(); + write("]"); + } } export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost { diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 676538a6859b4..37f7c29097d74 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -150,7 +150,9 @@ namespace ts { reportDiagnostic(createCompilerDiagnostic(Diagnostics.You_already_have_a_tsconfig_json_file_defined)); } else { - writeConfigFile(file, commandLine.options, commandLine.fileNames); + let writer = createTextWriter("\n"); + buildConfigFile(writer, compilerOptions, commandLine.fileNames, ["node_modules"]); + sys.writeFile(file, writer.getText()); } return sys.exit(ExitStatus.Success); } diff --git a/tests/cases/unittests/jsonWithCommentsAndTrailingCommas.ts b/tests/cases/unittests/jsonWithComments.ts similarity index 65% rename from tests/cases/unittests/jsonWithCommentsAndTrailingCommas.ts rename to tests/cases/unittests/jsonWithComments.ts index 2a3304e9baba2..cf29e22ffcf69 100644 --- a/tests/cases/unittests/jsonWithCommentsAndTrailingCommas.ts +++ b/tests/cases/unittests/jsonWithComments.ts @@ -32,30 +32,6 @@ module ts { }); }); - it("should parse JSON with trailing commas in an object @jsonWithCommentsAndTrailingCommas", () => { - let json = -`{ - "a": { - "b": true, - } -}`; - expect(parseConfigFileText("file.ts", json).config).to.be.deep.equal({ - a: { b: true } - }); - }); - - it("should parse JSON with trailing commas in an array @jsonWithCommentsAndTrailingCommas", () => { - let json = -`{ - "a": [ - "b", - ] -}`; - expect(parseConfigFileText("file.ts", json).config).to.be.deep.equal({ - a: [ "b" ] - }); - }); - it("should parse JSON with escape characters @jsonWithCommentsAndTrailingCommas", () => { let json = `{ diff --git a/tests/cases/unittests/projectInit.ts b/tests/cases/unittests/projectInit.ts index a0334c7ff1663..ba3c80c03cdb2 100644 --- a/tests/cases/unittests/projectInit.ts +++ b/tests/cases/unittests/projectInit.ts @@ -1,6 +1,5 @@ /// -/// -/// +/// module ts { describe('Project initializer', () => { @@ -38,23 +37,36 @@ module ts { expectedOutput += expectedCompilerOptionOutput[option].toString() + ",\n"; } } + expectedOutput = expectedOutput.slice(0, expectedOutput.lastIndexOf(',')) + "\n"; expectedOutput += " }"; if (expectedFileNames) { expectedOutput += ",\n"; expectedOutput += ` "files": [\n`; - for (let fileName of expectedFileNames) { - expectedOutput += ` "${fileName}",\n`; - } + + forEach(expectedFileNames, (fileName, index) => { + expectedOutput += ` "${fileName}"`; + if (index < expectedFileNames.length - 1) { + expectedOutput += ","; + } + expectedOutput += "\n"; + }); + expectedOutput += " ]"; } if (excludes) { expectedOutput += ",\n"; expectedOutput += ` "exclude": [\n`; - for (let exclude of excludes) { - expectedOutput += ` "${exclude}",\n`; - } + + forEach(excludes, (exclude, index) => { + expectedOutput += ` "${exclude}"`; + if (index < excludes.length - 1) { + expectedOutput += ","; + } + expectedOutput += "\n"; + }); + expectedOutput += " ]"; } expectedOutput += "\n}"; @@ -70,7 +82,7 @@ module ts { { module: "commonjs", target: "es3", - noImplicitAny: true, + noImplicitAny: false, outDir: "built", rootDir: ".", sourceMap: false, @@ -90,7 +102,7 @@ module ts { { module: "amd", // overrides commonjs target: "es5", // overrides es3 - noImplicitAny: true, + noImplicitAny: false, outDir: "built", rootDir: ".", sourceMap: false, @@ -110,7 +122,7 @@ module ts { newLine: "CRLF", module: "commonjs", target: "es3", - noImplicitAny: true, + noImplicitAny: false, outDir: "built", rootDir: ".", sourceMap: false, @@ -128,7 +140,7 @@ module ts { newLine: "LF", module: "commonjs", target: "es3", - noImplicitAny: true, + noImplicitAny: false, outDir: "built", rootDir: ".", sourceMap: false, @@ -145,7 +157,7 @@ module ts { { module: "commonjs", target: "es3", - noImplicitAny: true, + noImplicitAny: false, outDir: "built", rootDir: ".", sourceMap: false @@ -162,7 +174,7 @@ module ts { { module: "commonjs", target: "es3", - noImplicitAny: true, + noImplicitAny: false, outDir: "built", rootDir: ".", sourceMap: false @@ -184,7 +196,7 @@ module ts { { module: "commonjs", target: "es3", - noImplicitAny: true, + noImplicitAny: false, outDir: "built", rootDir: ".", sourceMap: false @@ -206,10 +218,10 @@ module ts { { module: "commonjs", target: "es3", - noImplicitAny: true, + noImplicitAny: false, outDir: "built", rootDir: ".", - sourceMap: false + sourceMap: false, }, null, null); From 07fb139326c2040f72587f736ddcbf14bf024462 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Wed, 29 Jul 2015 10:32:33 +0800 Subject: [PATCH 6/9] Adds success message for tsconfig.json init --- src/compiler/diagnosticInformationMap.generated.ts | 1 + src/compiler/diagnosticMessages.json | 4 ++++ src/compiler/tsc.ts | 1 + 3 files changed, 6 insertions(+) diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index c2fe4c57b2172..49ca79b0f1ec5 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -574,6 +574,7 @@ namespace ts { Option_experimentalAsyncFunctions_cannot_be_specified_when_targeting_ES5_or_lower: { code: 6067, category: DiagnosticCategory.Message, key: "Option 'experimentalAsyncFunctions' cannot be specified when targeting ES5 or lower." }, Enables_experimental_support_for_ES7_async_functions: { code: 6068, category: DiagnosticCategory.Message, key: "Enables experimental support for ES7 async functions." }, Initializes_a_TypeScript_project_and_creates_a_tsconfig_json_file: { code: 6069, category: DiagnosticCategory.Message, key: "Initializes a TypeScript project and creates a tsconfig.json file." }, + Successfully_created_a_tsconfig_json_file: { code: 6070, category: DiagnosticCategory.Message, key: "Successfully created a tsconfig.json file." }, Variable_0_implicitly_has_an_1_type: { code: 7005, category: DiagnosticCategory.Error, key: "Variable '{0}' implicitly has an '{1}' type." }, Parameter_0_implicitly_has_an_1_type: { code: 7006, category: DiagnosticCategory.Error, key: "Parameter '{0}' implicitly has an '{1}' type." }, Member_0_implicitly_has_an_1_type: { code: 7008, category: DiagnosticCategory.Error, key: "Member '{0}' implicitly has an '{1}' type." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index b59fb2313749f..78ffb2da1c8d5 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2286,6 +2286,10 @@ "category": "Message", "code": 6069 }, + "Successfully created a tsconfig.json file.": { + "category": "Message", + "code": 6070 + }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 37f7c29097d74..e026732bc2c05 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -153,6 +153,7 @@ namespace ts { let writer = createTextWriter("\n"); buildConfigFile(writer, compilerOptions, commandLine.fileNames, ["node_modules"]); sys.writeFile(file, writer.getText()); + reportDiagnostic(createCompilerDiagnostic(Diagnostics.Successfully_created_a_tsconfig_json_file)); } return sys.exit(ExitStatus.Success); } From 963ba1918e49e5469a3915832e2de57149bf47c6 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Tue, 25 Aug 2015 15:05:02 +0800 Subject: [PATCH 7/9] Addresses CR feedback --- src/compiler/commandLineParser.ts | 88 --------- src/compiler/core.ts | 10 +- src/compiler/program.ts | 227 +++------------------- src/compiler/tsc.ts | 59 ++++-- tests/cases/unittests/jsonWithComments.ts | 48 ----- 5 files changed, 78 insertions(+), 354 deletions(-) delete mode 100644 tests/cases/unittests/jsonWithComments.ts diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 38faf0a43fbb2..d5ab9022b3e61 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -367,93 +367,6 @@ namespace ts { return parseConfigFileText(fileName, text); } - /** - * Remove whitespace, comments and trailing commas from JSON text. - * @param text JSON text string. - */ - function stripJsonTrivia(text: string): string { - let ch: number; - let pos = 0; - let end = text.length - 1; - let result = ''; - let pendingCommaInsertion = false; - - while (pos <= end) { - ch = text.charCodeAt(pos); - - if(isWhiteSpace(ch) || isLineBreak(ch)) { - pos++; - continue; - } - - switch (ch) { - case CharacterCodes.slash: - if (text.charCodeAt(pos + 1) === CharacterCodes.slash) { - pos += 2; - - while (pos <= end) { - if (isLineBreak(text.charCodeAt(pos))) { - break; - } - pos++; - } - break; - } - else if (text.charCodeAt(pos + 1) === CharacterCodes.asterisk) { - pos += 2; - - while (pos <= end) { - ch = text.charCodeAt(pos); - - if (ch === CharacterCodes.asterisk && - text.charCodeAt(pos + 1) === CharacterCodes.slash) { - - pos += 2; - break; - } - pos++; - } - break; - } - - case CharacterCodes.doubleQuote: - result += text[pos]; - pos++; - - while (pos <= end) { - ch = text.charCodeAt(pos); - if (ch === CharacterCodes.backslash) { - switch (text.charCodeAt(pos + 1)) { - case CharacterCodes.doubleQuote: - result += "\\\""; - pos += 2; - continue; - case CharacterCodes.backslash: - result += "\\\\"; - pos += 2; - continue; - } - pos++; - } - result += text[pos]; - - if (ch === CharacterCodes.doubleQuote) { - break; - } - - pos++; - } - break; - - default: - result += text[pos]; - } - - pos++; - } - return result; - } - /** * Parse the text of the tsconfig.json file * @param fileName The path to the config file @@ -461,7 +374,6 @@ namespace ts { */ export function parseConfigFileText(fileName: string, jsonText: string): { config?: any; error?: Diagnostic } { try { - jsonText = stripJsonTrivia(jsonText); return { config: /\S/.test(jsonText) ? JSON.parse(jsonText) : {} }; } catch (e) { diff --git a/src/compiler/core.ts b/src/compiler/core.ts index ec171d4aee298..61232696697ff 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -275,14 +275,14 @@ namespace ts { return result; } - export function extend(first: Map, second: Map): Map { - let result: Map = {}; + export function extend(first: Map, second: Map): Map { + let result: Map = {}; for (let id in first) { - result[id] = first[id]; + (result as any)[id] = first[id]; } for (let id in second) { if (!hasProperty(result, id)) { - result[id] = second[id]; + (result as any)[id] = second[id]; } } return result; @@ -805,4 +805,4 @@ namespace ts { Debug.assert(false, message); } } -} +} diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 70b89db4eaf7a..a749e0e4ad672 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -36,209 +36,38 @@ namespace ts { sourceMap: false, } - export function buildConfigFile(writer: EmitTextWriter, compilerOptions: CompilerOptions, fileNames?: string[], excludes?: string[]) { - compilerOptions = extend(compilerOptions, defaultInitCompilerOptions); - let { write, writeLine, increaseIndent, decreaseIndent } = writer; - let { optionNameMap } = getOptionNameMap(); - writeConfigFile(); - - function writeConfigFile() { - write("{"); - writeLine(); - increaseIndent(); - writeCompilerOptions(); - if (fileNames && fileNames.length > 0) { - write(","); - writeLine(); - writeFileNames(); - } - if (excludes) { - write(","); - writeLine(); - writeExcludeOptions(); - } - writeLine(); - decreaseIndent(); - write("}"); - } - - function writeCompilerOptions() { - write(`"compilerOptions": {`); - writeLine(); - increaseIndent(); - - let length = 0; - for (var option in compilerOptions) { - length++; - } - - let i = 0; - for (var option in compilerOptions) { - switch (option) { - case "init": - case "watch": - case "help": - case "version": - i++; - continue; - - case "module": - case "target": - case "newLine": - writeComplexCompilerOption(option, i < length - 1); - break; - - default: - writeSimpleCompilerOption(option, i < length - 1); - - } - i++; - } - - decreaseIndent(); - write("}"); - } - - function writeOptionalOptionDescription(option: string) { - option = option.toLowerCase(); - if (optionNameMap[option].description && - optionNameMap[option].description.key) { - - write(`// ${optionNameMap[option].description.key}`); - writeLine(); - } - } - - /** - * Write simple compiler option. A simple compiler option is an option - * with boolean or non string set value. - */ - function writeSimpleCompilerOption(option: string, writeComma: boolean) { - writeOptionalOptionDescription(option); - - write(`"${option}": `); - if (typeof compilerOptions[option] === "string") { - write(`"${compilerOptions[option]}"`); - } - else { - if (compilerOptions[option]) { - write("true"); - } - else { - write("false"); - } - } - - if (writeComma) { - write(","); - } - writeLine(); - } - - /** - * Write complex compiler option. A complex compiler option is an option - * which maps to a TypeScript enum type. - */ - function writeComplexCompilerOption(option: string, writeComma: boolean) { - writeOptionalOptionDescription(option); - - outer: switch (option) { - case "module": - var moduleValue: string; - switch (compilerOptions.module) { - case ModuleKind.None: - break outer; - case ModuleKind.CommonJS: - moduleValue = "commonjs"; - break; - case ModuleKind.System: - moduleValue = "system"; - break; - case ModuleKind.UMD: - moduleValue = "umd"; - break; - default: - moduleValue = "amd"; - break; - } - write(`"module": "${moduleValue}"`); - if (writeComma) { - write(","); - } - writeLine(); - break; - - case "target": - var targetValue: string; - switch (compilerOptions.target) { - case ScriptTarget.ES5: - targetValue = "es5"; - break; - case ScriptTarget.ES6: - targetValue = "es6"; - break; - default: - targetValue = "es3"; - break; - } - write(`"target": "${targetValue}"`); - if (writeComma) { - write(","); - } - writeLine(); - break; - - case "newLine": - var newlineValue: string; - switch (compilerOptions.newLine) { - case NewLineKind.CarriageReturnLineFeed: - newlineValue = "CRLF"; - break; - default: - newlineValue = "LF"; - break; - } - write(`"newLine": "${newlineValue}"`); - if (writeComma) { - write(","); - } - writeLine(); - break; - } + export function scriptTargetToString(target: ScriptTarget): string { + switch (target) { + case ScriptTarget.ES5: + return "es5"; + case ScriptTarget.ES6: + return "es6"; + default: + return "es3"; } + } - function writeFileNames() { - write(`"files": [`); - writeLine(); - increaseIndent(); - - forEach(fileNames, (fileName, index) => { - write(`"${fileName}"`); - if (index < fileNames.length - 1) { - write(","); - } - writeLine(); - }); - - decreaseIndent(); - write("]"); + export function moduleKindToString(kind: ModuleKind): string { + switch (kind) { + case ModuleKind.None: + return undefined; + case ModuleKind.CommonJS: + return "commonjs"; + case ModuleKind.System: + return "system"; + case ModuleKind.UMD: + return "umd"; + default: + return "amd"; } + } - function writeExcludeOptions() { - write(`"exclude": [`); - writeLine(); - increaseIndent(); - - forEach(excludes, (exclude, index) => { - write(`"${exclude}"`); - if (index < excludes.length - 1) { - write(","); - } - writeLine(); - }); - - decreaseIndent(); - write("]"); + export function newLineKindToString(kind: NewLineKind): string { + switch (kind) { + case NewLineKind.CarriageReturnLineFeed: + return "CRLF"; + default: + return "LF"; } } diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index e026732bc2c05..bc7aa67b93961 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -144,20 +144,6 @@ namespace ts { let hostGetSourceFile: typeof compilerHost.getSourceFile; // getSourceFile method from default host let timerHandle: number; // Handle for 0.25s wait timer - if (commandLine.options.init) { - let file = `${sys.getCurrentDirectory()}/tsconfig.json`; - if (sys.fileExists(file)) { - reportDiagnostic(createCompilerDiagnostic(Diagnostics.You_already_have_a_tsconfig_json_file_defined)); - } - else { - let writer = createTextWriter("\n"); - buildConfigFile(writer, compilerOptions, commandLine.fileNames, ["node_modules"]); - sys.writeFile(file, writer.getText()); - reportDiagnostic(createCompilerDiagnostic(Diagnostics.Successfully_created_a_tsconfig_json_file)); - } - return sys.exit(ExitStatus.Success); - } - if (commandLine.options.locale) { if (!isJSONSupported()) { reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--locale")); @@ -173,6 +159,51 @@ namespace ts { return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } + if (commandLine.options.init) { + let file = combinePaths(sys.getCurrentDirectory(), 'tsconfig.json'); + if (sys.fileExists(file)) { + reportDiagnostic(createCompilerDiagnostic(Diagnostics.You_already_have_a_tsconfig_json_file_defined)); + } + else { + let compilerOptions = extend(commandLine.options, defaultInitCompilerOptions); + let configs = { + compilerOptions, + files: commandLine.fileNames, + exclude: ["node_modules"] + }; + sys.writeFile(file, JSON.stringify(configs, (k, v) => { + if (k === "compilerOptions") { + let options: CompilerOptions = v; + for (let o in options) { + switch (o) { + case "target": + options[o] = scriptTargetToString(options[o] as ScriptTarget); + continue; + case "module": + options[o] = moduleKindToString(options[o] as ModuleKind); + continue; + case "newLine": + options[o] = newLineKindToString(options[o] as NewLineKind); + continue; + case "init": + case "watch": + case "version": + case "help": + delete options[o]; + continue; + } + } + + return options; + } + + return v; + }, 4)); + reportDiagnostic(createCompilerDiagnostic(Diagnostics.Successfully_created_a_tsconfig_json_file)); + } + return sys.exit(ExitStatus.Success); + } + if (commandLine.options.version) { reportDiagnostic(createCompilerDiagnostic(Diagnostics.Version_0, ts.version)); return sys.exit(ExitStatus.Success); diff --git a/tests/cases/unittests/jsonWithComments.ts b/tests/cases/unittests/jsonWithComments.ts deleted file mode 100644 index cf29e22ffcf69..0000000000000 --- a/tests/cases/unittests/jsonWithComments.ts +++ /dev/null @@ -1,48 +0,0 @@ -/// -/// - -module ts { - describe("JSON with comments and trailing commas", () => { - it("should parse JSON with single line comments @jsonWithCommentsAndTrailingCommas", () => { - let json = -`{ - "a": { - // comment - "b": true - } -}`; - expect(parseConfigFileText("file.ts", json).config).to.be.deep.equal({ - a: { b: true } - }); - }); - - - it("should parse JSON with multiline line comments @jsonWithCommentsAndTrailingCommas", () => { - let json = -`{ - "a": { - /* - * comment - */ - "b": true - } -}`; - expect(parseConfigFileText("file.ts", json).config).to.be.deep.equal({ - a: { b: true } - }); - }); - - it("should parse JSON with escape characters @jsonWithCommentsAndTrailingCommas", () => { - let json = -`{ - "a": [ - "b\\\"\\\\", - ] -}`; - expect(parseConfigFileText("file.ts", json).config).to.be.deep.equal({ - a: [ "b\"\\" ] - }); - }); - }); -} - From 075cd1249fbe55339e72379e90634782a79b74e0 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Tue, 25 Aug 2015 15:31:14 +0800 Subject: [PATCH 8/9] Removes jsonWithComments --- Jakefile.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Jakefile.js b/Jakefile.js index 4f922dd3ab880..c67277405f86a 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -142,8 +142,7 @@ var harnessSources = harnessCoreSources.concat([ "versionCache.ts", "convertToBase64.ts", "transpile.ts", - "projectInit.ts", - "jsonWithComments.ts" + "projectInit.ts" ].map(function (f) { return path.join(unittestsDirectory, f); })).concat([ From 1670ce9664ed914ba2cd7c172caf8fe905261a81 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Tue, 25 Aug 2015 15:43:10 +0800 Subject: [PATCH 9/9] Removes project init test --- Jakefile.js | 3 +- tests/cases/unittests/projectInit.ts | 230 --------------------------- 2 files changed, 1 insertion(+), 232 deletions(-) delete mode 100644 tests/cases/unittests/projectInit.ts diff --git a/Jakefile.js b/Jakefile.js index c67277405f86a..c4a8121d03703 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -141,8 +141,7 @@ var harnessSources = harnessCoreSources.concat([ "session.ts", "versionCache.ts", "convertToBase64.ts", - "transpile.ts", - "projectInit.ts" + "transpile.ts" ].map(function (f) { return path.join(unittestsDirectory, f); })).concat([ diff --git a/tests/cases/unittests/projectInit.ts b/tests/cases/unittests/projectInit.ts deleted file mode 100644 index ba3c80c03cdb2..0000000000000 --- a/tests/cases/unittests/projectInit.ts +++ /dev/null @@ -1,230 +0,0 @@ -/// -/// - -module ts { - describe('Project initializer', () => { - interface ExpectedCompilerOptionsOutput { - [option: string]: string | boolean; - } - - function assertConfigFile( - compilerOptions: CompilerOptions, - fileNames: string[], - excludes: string[], - expectedCompilerOptionOutput: ExpectedCompilerOptionsOutput, - expectedFileNames: string[], - expectedExcludes: string[]): void { - - let writer = createTextWriter("\n"); - let optionNameMap = getOptionNameMap().optionNameMap; - - buildConfigFile(writer, compilerOptions, fileNames, excludes); - - let expectedOutput = `{\n "compilerOptions": {\n`; - for (let option in expectedCompilerOptionOutput) { - let lowerCaseOption = option.toLowerCase() - if (optionNameMap[lowerCaseOption].description && - optionNameMap[lowerCaseOption].description.key) { - - expectedOutput += ` // ${optionNameMap[lowerCaseOption].description.key}\n`; - } - - expectedOutput += ` "${option}": `; - if (typeof expectedCompilerOptionOutput[option] === "string") { - expectedOutput += `"${expectedCompilerOptionOutput[option]}",\n`; - } - else { - expectedOutput += expectedCompilerOptionOutput[option].toString() + ",\n"; - } - } - expectedOutput = expectedOutput.slice(0, expectedOutput.lastIndexOf(',')) + "\n"; - expectedOutput += " }"; - - if (expectedFileNames) { - expectedOutput += ",\n"; - expectedOutput += ` "files": [\n`; - - forEach(expectedFileNames, (fileName, index) => { - expectedOutput += ` "${fileName}"`; - if (index < expectedFileNames.length - 1) { - expectedOutput += ","; - } - expectedOutput += "\n"; - }); - - expectedOutput += " ]"; - } - - if (excludes) { - expectedOutput += ",\n"; - expectedOutput += ` "exclude": [\n`; - - forEach(excludes, (exclude, index) => { - expectedOutput += ` "${exclude}"`; - if (index < excludes.length - 1) { - expectedOutput += ","; - } - expectedOutput += "\n"; - }); - - expectedOutput += " ]"; - } - expectedOutput += "\n}"; - - expect(writer.getText()).to.equal(expectedOutput); - } - - it("should generate default compiler options @projectInit", () => { - assertConfigFile( - {}, - null, - null, - { - module: "commonjs", - target: "es3", - noImplicitAny: false, - outDir: "built", - rootDir: ".", - sourceMap: false, - }, - null, - null); - }); - - it("should override default compiler options @projectInit", () => { - assertConfigFile( - { - module: ModuleKind.AMD, - target: ScriptTarget.ES5, - }, - null, - null, - { - module: "amd", // overrides commonjs - target: "es5", // overrides es3 - noImplicitAny: false, - outDir: "built", - rootDir: ".", - sourceMap: false, - }, - null, - null); - }); - - it("should be able to generate newline option @projectInit", () => { - assertConfigFile( - { - newLine: NewLineKind.CarriageReturnLineFeed - }, - null, - null, - { - newLine: "CRLF", - module: "commonjs", - target: "es3", - noImplicitAny: false, - outDir: "built", - rootDir: ".", - sourceMap: false, - }, - null, - null); - - assertConfigFile( - { - newLine: NewLineKind.LineFeed - }, - null, - null, - { - newLine: "LF", - module: "commonjs", - target: "es3", - noImplicitAny: false, - outDir: "built", - rootDir: ".", - sourceMap: false, - }, - null, - null); - }); - - it("should generate a `files` property @projectInit", () => { - assertConfigFile( - {}, - ["file1.ts", "file2.ts"], - null, - { - module: "commonjs", - target: "es3", - noImplicitAny: false, - outDir: "built", - rootDir: ".", - sourceMap: false - }, - ["file1.ts", "file2.ts"], - null); - }); - - it("should generate exclude options @projectInit", () => { - assertConfigFile( - {}, - null, - ["node_modules"], - { - module: "commonjs", - target: "es3", - noImplicitAny: false, - outDir: "built", - rootDir: ".", - sourceMap: false - }, - null, - ["node_modules"]); - }); - - it("should not generate compiler options for `version`, `watch`, `init` and `help` @projectInit", () => { - assertConfigFile( - { - version: true, - watch: true, - init: true, - help: true, - }, - null, - null, - { - module: "commonjs", - target: "es3", - noImplicitAny: false, - outDir: "built", - rootDir: ".", - sourceMap: false - }, - null, - null); - }); - - it("should not generate a files property if the files length is zero @projectInit", () => { - assertConfigFile( - { - version: true, - watch: true, - init: true, - help: true, - }, - [], - null, - { - module: "commonjs", - target: "es3", - noImplicitAny: false, - outDir: "built", - rootDir: ".", - sourceMap: false, - }, - null, - null); - }); - }); -} \ No newline at end of file