mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Addresses CR feedback
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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\"\\" ]
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user