From 963ba1918e49e5469a3915832e2de57149bf47c6 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Tue, 25 Aug 2015 15:05:02 +0800 Subject: [PATCH] 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 38faf0a43fb..d5ab9022b3e 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 ec171d4aee2..61232696697 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 70b89db4eaf..a749e0e4ad6 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("}"); + export function scriptTargetToString(target: ScriptTarget): string { + switch (target) { + case ScriptTarget.ES5: + return "es5"; + case ScriptTarget.ES6: + return "es6"; + default: + return "es3"; } + } - 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("}"); + 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 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 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 e026732bc2c..bc7aa67b939 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 cf29e22ffcf..00000000000 --- 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\"\\" ] - }); - }); - }); -} -