Addresses CR feedback

This commit is contained in:
Tingan Ho
2015-08-25 15:05:02 +08:00
parent 07fb139326
commit 963ba1918e
5 changed files with 78 additions and 354 deletions
-88
View File
@@ -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) {
+5 -5
View File
@@ -275,14 +275,14 @@ namespace ts {
return <T>result;
}
export function extend<T>(first: Map<T>, second: Map<T>): Map<T> {
let result: Map<T> = {};
export function extend<T1, T2>(first: Map<T1>, second: Map<T2>): Map<T1 & T2> {
let result: Map<T1 & T2> = {};
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);
}
}
}
}
+28 -199
View File
@@ -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";
}
}
+45 -14
View File
@@ -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);
-48
View File
@@ -1,48 +0,0 @@
/// <reference path="..\..\..\src\harness\harness.ts" />
/// <reference path="..\..\..\src\compiler\commandLineParser.ts" />
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\"\\" ]
});
});
});
}