From ba7fadeb1228f9c8f0217b18e5090688613f1b9e Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 30 Jun 2015 20:40:06 -0400 Subject: [PATCH 01/20] Add support to tell whether output directs to a terminal emulator. --- src/compiler/sys.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index a47d6959ba81a..f3244af0df7e8 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -6,6 +6,7 @@ namespace ts { newLine: string; useCaseSensitiveFileNames: boolean; write(s: string): void; + writesToTty?(): boolean; readFile(path: string, encoding?: string): string; writeFile(path: string, data: string, writeByteOrderMark?: boolean): void; watchFile?(path: string, callback: (path: string) => void): FileWatcher; @@ -187,7 +188,8 @@ namespace ts { function getNodeSystem(): System { var _fs = require("fs"); var _path = require("path"); - var _os = require('os'); + var _os = require("os"); + var _tty = require("tty"); var platform: string = _os.platform(); // win32\win64 are case insensitive platforms, MacOS (darwin) by default is also case insensitive @@ -271,6 +273,7 @@ namespace ts { // 1 is a standard descriptor for stdout _fs.writeSync(1, s); }, + writesToTty: () => _tty.isatty(1), readFile, writeFile, watchFile: (fileName, callback) => { From f660bd3652fd567c4c13fd5afafd35a070e2aed0 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 30 Jun 2015 22:35:17 -0400 Subject: [PATCH 02/20] Got "prettier" error printing working. --- src/compiler/tsc.ts | 84 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 78 insertions(+), 6 deletions(-) diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 2a01774fbcaaf..5f474b861fe0a 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -80,24 +80,96 @@ namespace ts { return diagnostic.messageText; } - function reportDiagnostic(diagnostic: Diagnostic) { - var output = ""; + function reportDiagnostic(diagnostic: Diagnostic): void { + let output = ""; if (diagnostic.file) { - var loc = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start); + let { line, character } = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start); - output += `${ diagnostic.file.fileName }(${ loc.line + 1 },${ loc.character + 1 }): `; + output += `${ diagnostic.file.fileName }(${ line + 1 },${ character + 1 }): `; } - var category = DiagnosticCategory[diagnostic.category].toLowerCase(); + let category = DiagnosticCategory[diagnostic.category].toLowerCase(); output += `${ category } TS${ diagnostic.code }: ${ flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine) }${ sys.newLine }`; sys.write(output); } + const redColorControlChar = "\u001b[31m"; + const resetColorControlChar = "\u001b[0m"; + + function reportDiagnosticAllPrettyLike(diagnostic: Diagnostic): void { + let output = ""; + + if (diagnostic.file) { + let { start, length, file } = diagnostic; + let { line: firstLine, character: firstLineChar } = getLineAndCharacterOfPosition(file, start); + let { line: lastLine, character: lastLineChar } = getLineAndCharacterOfPosition(file, start + length); + + output += sys.newLine; + for (let i = 0, indexOfLastLine = lastLine - firstLine; i <= indexOfLastLine; i++) { + let lineStart = getPositionOfLineAndCharacter(file, firstLine + i, 0); + let lineEnd = getPositionOfLineAndCharacter(file, firstLine + i + 1, 0); + let lineContent = file.text.slice(lineStart, lineEnd); + lineContent = lineContent.replace(/\s+$/g, ""); // trim from end + lineContent = lineContent.replace("\t", " "); // normalize tabs to 4 spaces + + output += lineContent + sys.newLine; + + if (i === 0) { + let lastCharForLine = i === indexOfLastLine ? lastLineChar : undefined; + + output += lineContent.slice(0, firstLineChar).replace(/\S/g, " "); + output += redColorControlChar; + output += lineContent.slice(firstLineChar, lastCharForLine).replace(/./g, "~"); + output += resetColorControlChar; + } + else if (i === indexOfLastLine) { + output += redColorControlChar; + output += lineContent.slice(0, lastLineChar).replace(/./g, "~"); + output += resetColorControlChar; + // Don't bother "filling" at the end. + } + else { + output += lineContent.replace(/^(\s*)(.*)$/, replaceLineWithRedSquiggles); + } + + output += sys.newLine; + } + + output += `${ file.fileName }(${ firstLine + 1 },${ firstLineChar + 1 }): `; + } + + let category = DiagnosticCategory[diagnostic.category].toLowerCase(); + output += `${ category } TS${ diagnostic.code }: ${ flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine) }`; + output += sys.newLine + sys.newLine; + + sys.write(output); + } + + function replaceLineWithRedSquiggles(orig: string, leadingWhitespace: string, content: string): string { + return leadingWhitespace + redColorControlChar + content.replace(/./g, "~") + resetColorControlChar; + } + + /** Splits the given string on \r\n, or on only \n if that fails, or on only \r if *that* fails. */ + function splitContentByNewlines(content: string) { + // Split up the input file by line + // Note: IE JS engine incorrectly handles consecutive delimiters here when using RegExp split, so + // we have to use string-based splitting instead and try to figure out the delimiting chars + var lines = content.split('\r\n'); + if (lines.length === 1) { + lines = content.split('\n'); + + if (lines.length === 1) { + lines = content.split("\r"); + } + } + return lines; + } + function reportDiagnostics(diagnostics: Diagnostic[]) { for (var i = 0; i < diagnostics.length; i++) { - reportDiagnostic(diagnostics[i]); + reportDiagnosticAllPrettyLike(diagnostics[i]); } } From 17f443ac3be562a93cb45b34dd7e9ad4d3ea1366 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 1 Jul 2015 03:49:58 -0400 Subject: [PATCH 03/20] Just squiggle the entire line for middle lines (sans trailing space). --- src/compiler/tsc.ts | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 5f474b861fe0a..b920949c00450 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -116,23 +116,21 @@ namespace ts { output += lineContent + sys.newLine; + output += redColorControlChar; if (i === 0) { let lastCharForLine = i === indexOfLastLine ? lastLineChar : undefined; output += lineContent.slice(0, firstLineChar).replace(/\S/g, " "); - output += redColorControlChar; output += lineContent.slice(firstLineChar, lastCharForLine).replace(/./g, "~"); - output += resetColorControlChar; } else if (i === indexOfLastLine) { - output += redColorControlChar; output += lineContent.slice(0, lastLineChar).replace(/./g, "~"); - output += resetColorControlChar; // Don't bother "filling" at the end. } else { - output += lineContent.replace(/^(\s*)(.*)$/, replaceLineWithRedSquiggles); + output += lineContent.replace(/./g, "~"); } + output += resetColorControlChar; output += sys.newLine; } @@ -147,10 +145,6 @@ namespace ts { sys.write(output); } - function replaceLineWithRedSquiggles(orig: string, leadingWhitespace: string, content: string): string { - return leadingWhitespace + redColorControlChar + content.replace(/./g, "~") + resetColorControlChar; - } - /** Splits the given string on \r\n, or on only \n if that fails, or on only \r if *that* fails. */ function splitContentByNewlines(content: string) { // Split up the input file by line From fdbea8b6828d8dd5822b21634fd6c3057ff7a81d Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 1 Jul 2015 12:23:10 -0400 Subject: [PATCH 04/20] Give the new reporter a more reasonable name. --- src/compiler/tsc.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index b920949c00450..d724a54742f09 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -98,7 +98,7 @@ namespace ts { const redColorControlChar = "\u001b[31m"; const resetColorControlChar = "\u001b[0m"; - function reportDiagnosticAllPrettyLike(diagnostic: Diagnostic): void { + function reportDiagnosticWithColorAndContext(diagnostic: Diagnostic): void { let output = ""; if (diagnostic.file) { @@ -163,7 +163,7 @@ namespace ts { function reportDiagnostics(diagnostics: Diagnostic[]) { for (var i = 0; i < diagnostics.length; i++) { - reportDiagnosticAllPrettyLike(diagnostics[i]); + reportDiagnosticWithColorAndContext(diagnostics[i]); } } From d8e462d6e767893ae6ac2bff997f509e3d605ba8 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 1 Jul 2015 12:40:01 -0400 Subject: [PATCH 05/20] Make output reliant on whether stdout redirects to a terminal; use forEach. --- src/compiler/tsc.ts | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index d724a54742f09..2e577b8b0f933 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -145,6 +145,10 @@ namespace ts { sys.write(output); } + const diagnosticReporter = sys.writesToTty && sys.writesToTty() ? + reportDiagnosticWithColorAndContext : + reportDiagnostic; + /** Splits the given string on \r\n, or on only \n if that fails, or on only \r if *that* fails. */ function splitContentByNewlines(content: string) { // Split up the input file by line @@ -161,12 +165,6 @@ namespace ts { return lines; } - function reportDiagnostics(diagnostics: Diagnostic[]) { - for (var i = 0; i < diagnostics.length; i++) { - reportDiagnosticWithColorAndContext(diagnostics[i]); - } - } - function padLeft(s: string, length: number) { while (s.length < length) { s = " " + s; @@ -220,7 +218,7 @@ namespace ts { // If there are any errors due to command line parsing and/or // setting up localization, report them and quit. if (commandLine.errors.length > 0) { - reportDiagnostics(commandLine.errors); + forEach(commandLine.errors, diagnosticReporter); return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } @@ -285,7 +283,7 @@ namespace ts { let configObject = result.config; let configParseResult = parseConfigFile(configObject, sys, getDirectoryPath(configFileName)); if (configParseResult.errors.length > 0) { - reportDiagnostics(configParseResult.errors); + forEach(configParseResult.errors, diagnosticReporter); return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } rootFileNames = configParseResult.fileNames; @@ -422,17 +420,17 @@ namespace ts { function compileProgram(): ExitStatus { // First get any syntactic errors. var diagnostics = program.getSyntacticDiagnostics(); - reportDiagnostics(diagnostics); + forEach(diagnostics, diagnosticReporter); // If we didn't have any syntactic errors, then also try getting the global and // semantic errors. if (diagnostics.length === 0) { var diagnostics = program.getGlobalDiagnostics(); - reportDiagnostics(diagnostics); + forEach(diagnostics, diagnosticReporter); if (diagnostics.length === 0) { var diagnostics = program.getSemanticDiagnostics(); - reportDiagnostics(diagnostics); + forEach(diagnostics, diagnosticReporter); } } @@ -445,7 +443,7 @@ namespace ts { // Otherwise, emit and report any errors we ran into. var emitOutput = program.emit(); - reportDiagnostics(emitOutput.diagnostics); + forEach(emitOutput.diagnostics, diagnosticReporter); // If the emitter didn't emit anything, then pass that value along. if (emitOutput.emitSkipped) { From cc6b04c7a62cf42d6e4423fd702d4989a509c3d0 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 1 Jul 2015 12:49:46 -0400 Subject: [PATCH 06/20] Bring back 'reportDiagnostics'. --- src/compiler/tsc.ts | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 2e577b8b0f933..c3b80b800c84d 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -6,6 +6,16 @@ namespace ts { fileWatcher: FileWatcher; } + const reportDiagnostic = sys.writesToTty && sys.writesToTty() ? + reportDiagnosticWithColorAndContext : + reportDiagnosticSimply; + + function reportDiagnostics(diagnostics: Diagnostic[]): void { + for (let diagnostic of diagnostics) { + reportDiagnostic(diagnostic); + } + } + /** * Checks to see if the locale is in the appropriate format, * and if it is, attempts to set the appropriate language. @@ -80,7 +90,7 @@ namespace ts { return diagnostic.messageText; } - function reportDiagnostic(diagnostic: Diagnostic): void { + function reportDiagnosticSimply(diagnostic: Diagnostic): void { let output = ""; if (diagnostic.file) { @@ -145,10 +155,6 @@ namespace ts { sys.write(output); } - const diagnosticReporter = sys.writesToTty && sys.writesToTty() ? - reportDiagnosticWithColorAndContext : - reportDiagnostic; - /** Splits the given string on \r\n, or on only \n if that fails, or on only \r if *that* fails. */ function splitContentByNewlines(content: string) { // Split up the input file by line @@ -209,7 +215,7 @@ namespace ts { if (commandLine.options.locale) { if (!isJSONSupported()) { - reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--locale")); + reportDiagnosticSimply(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--locale")); return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } validateLocaleAndSetLanguage(commandLine.options.locale, commandLine.errors); @@ -218,12 +224,12 @@ namespace ts { // If there are any errors due to command line parsing and/or // setting up localization, report them and quit. if (commandLine.errors.length > 0) { - forEach(commandLine.errors, diagnosticReporter); + reportDiagnostics(commandLine.errors); return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } if (commandLine.options.version) { - reportDiagnostic(createCompilerDiagnostic(Diagnostics.Version_0, ts.version)); + reportDiagnosticSimply(createCompilerDiagnostic(Diagnostics.Version_0, ts.version)); return sys.exit(ExitStatus.Success); } @@ -235,12 +241,12 @@ namespace ts { if (commandLine.options.project) { if (!isJSONSupported()) { - reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--project")); + reportDiagnosticSimply(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--project")); return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } configFileName = normalizePath(combinePaths(commandLine.options.project, "tsconfig.json")); if (commandLine.fileNames.length !== 0) { - reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line)); + reportDiagnosticSimply(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line)); return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } } @@ -258,7 +264,7 @@ namespace ts { // Firefox has Object.prototype.watch if (commandLine.options.watch && commandLine.options.hasOwnProperty("watch")) { if (!sys.watchFile) { - reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch")); + reportDiagnosticSimply(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch")); return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } if (configFileName) { @@ -276,14 +282,14 @@ namespace ts { let result = readConfigFile(configFileName); if (result.error) { - reportDiagnostic(result.error); + reportDiagnosticSimply(result.error); return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } let configObject = result.config; let configParseResult = parseConfigFile(configObject, sys, getDirectoryPath(configFileName)); if (configParseResult.errors.length > 0) { - forEach(configParseResult.errors, diagnosticReporter); + reportDiagnostics(configParseResult.errors); return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } rootFileNames = configParseResult.fileNames; @@ -305,7 +311,7 @@ namespace ts { } setCachedProgram(compileResult.program); - reportDiagnostic(createCompilerDiagnostic(Diagnostics.Compilation_complete_Watching_for_file_changes)); + reportDiagnosticSimply(createCompilerDiagnostic(Diagnostics.Compilation_complete_Watching_for_file_changes)); } function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError ?: (message: string) => void) { @@ -367,7 +373,7 @@ namespace ts { function recompile() { timerHandle = undefined; - reportDiagnostic(createCompilerDiagnostic(Diagnostics.File_change_detected_Starting_incremental_compilation)); + reportDiagnosticSimply(createCompilerDiagnostic(Diagnostics.File_change_detected_Starting_incremental_compilation)); performCompilation(); } } @@ -420,17 +426,17 @@ namespace ts { function compileProgram(): ExitStatus { // First get any syntactic errors. var diagnostics = program.getSyntacticDiagnostics(); - forEach(diagnostics, diagnosticReporter); + reportDiagnostics(diagnostics); // If we didn't have any syntactic errors, then also try getting the global and // semantic errors. if (diagnostics.length === 0) { var diagnostics = program.getGlobalDiagnostics(); - forEach(diagnostics, diagnosticReporter); + reportDiagnostics(diagnostics); if (diagnostics.length === 0) { var diagnostics = program.getSemanticDiagnostics(); - forEach(diagnostics, diagnosticReporter); + reportDiagnostics(diagnostics); } } @@ -443,7 +449,7 @@ namespace ts { // Otherwise, emit and report any errors we ran into. var emitOutput = program.emit(); - forEach(emitOutput.diagnostics, diagnosticReporter); + reportDiagnostics(emitOutput.diagnostics); // If the emitter didn't emit anything, then pass that value along. if (emitOutput.emitSkipped) { From 99f6985115cfe26ed6f850d0d6943af3d80492f6 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 16 Jul 2015 19:41:23 -0700 Subject: [PATCH 07/20] Don't expand tabs; just use a space. --- src/compiler/tsc.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index c3b80b800c84d..dbd70e7557c7e 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -122,7 +122,7 @@ namespace ts { let lineEnd = getPositionOfLineAndCharacter(file, firstLine + i + 1, 0); let lineContent = file.text.slice(lineStart, lineEnd); lineContent = lineContent.replace(/\s+$/g, ""); // trim from end - lineContent = lineContent.replace("\t", " "); // normalize tabs to 4 spaces + lineContent = lineContent.replace("\t", " "); // convert tabs to single spaces output += lineContent + sys.newLine; From 85b54e8946f9c19f3237d017cff181fd199618fc Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 16 Jul 2015 22:45:31 -0700 Subject: [PATCH 08/20] Fixed out of bounds error; made index start directly at the line number. --- src/compiler/tsc.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index dbd70e7557c7e..5105d2d37194f 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -117,9 +117,9 @@ namespace ts { let { line: lastLine, character: lastLineChar } = getLineAndCharacterOfPosition(file, start + length); output += sys.newLine; - for (let i = 0, indexOfLastLine = lastLine - firstLine; i <= indexOfLastLine; i++) { - let lineStart = getPositionOfLineAndCharacter(file, firstLine + i, 0); - let lineEnd = getPositionOfLineAndCharacter(file, firstLine + i + 1, 0); + for (let i = firstLine; i <= lastLine; i++) { + let lineStart = getPositionOfLineAndCharacter(file, i, 0); + let lineEnd = i < lastLine ? getPositionOfLineAndCharacter(file, i + 1, 0) : file.text.length; let lineContent = file.text.slice(lineStart, lineEnd); lineContent = lineContent.replace(/\s+$/g, ""); // trim from end lineContent = lineContent.replace("\t", " "); // convert tabs to single spaces @@ -127,13 +127,13 @@ namespace ts { output += lineContent + sys.newLine; output += redColorControlChar; - if (i === 0) { - let lastCharForLine = i === indexOfLastLine ? lastLineChar : undefined; + if (i === firstLine) { + let lastCharForLine = i === lastLine ? lastLineChar : undefined; output += lineContent.slice(0, firstLineChar).replace(/\S/g, " "); output += lineContent.slice(firstLineChar, lastCharForLine).replace(/./g, "~"); } - else if (i === indexOfLastLine) { + else if (i === lastLine) { output += lineContent.slice(0, lastLineChar).replace(/./g, "~"); // Don't bother "filling" at the end. } From dda058b85e73da1166f80364d26aaa5e62df57fb Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 24 Jul 2015 12:18:18 -0700 Subject: [PATCH 09/20] Use 'process.stdout.write' to ensure colors get displayed correctly on Windows. --- src/compiler/sys.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index f3244af0df7e8..8564eafa47262 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -271,7 +271,7 @@ namespace ts { useCaseSensitiveFileNames: useCaseSensitiveFileNames, write(s: string): void { // 1 is a standard descriptor for stdout - _fs.writeSync(1, s); + process.stdout.write(s); }, writesToTty: () => _tty.isatty(1), readFile, From 3c04dff0593acc423c9167c96f80bd6a38feee60 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 18 Aug 2015 00:47:09 -0700 Subject: [PATCH 10/20] Limit errors to 5 lines, fixed some other issues. --- src/compiler/tsc.ts | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 5105d2d37194f..069f87dae1f11 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -105,7 +105,7 @@ namespace ts { sys.write(output); } - const redColorControlChar = "\u001b[31m"; + const redColorControlChar = "\u001b[91m"; const resetColorControlChar = "\u001b[0m"; function reportDiagnosticWithColorAndContext(diagnostic: Diagnostic): void { @@ -115,19 +115,38 @@ namespace ts { let { start, length, file } = diagnostic; let { line: firstLine, character: firstLineChar } = getLineAndCharacterOfPosition(file, start); let { line: lastLine, character: lastLineChar } = getLineAndCharacterOfPosition(file, start + length); - + const lastLineInFile = getLineAndCharacterOfPosition(file, file.text.length).line; + + let hasMoreThanFiveLines = (lastLine - firstLine) >= 4; + let gutterWidth = (lastLine + 1 + "").length; + if (hasMoreThanFiveLines) { + gutterWidth = Math.max("...".length, gutterWidth); + } + output += sys.newLine; for (let i = firstLine; i <= lastLine; i++) { + // If the error spans over 5 lines, we'll only show the first 2 and last 2 lines, + // so we'll skip ahead to the second-to-last line. + if (hasMoreThanFiveLines && firstLine + 1 < i && i < lastLine - 1) { + output += padLeft("...", gutterWidth) + " ||" + sys.newLine; + i = lastLine - 1; + } + let lineStart = getPositionOfLineAndCharacter(file, i, 0); - let lineEnd = i < lastLine ? getPositionOfLineAndCharacter(file, i + 1, 0) : file.text.length; + let lineEnd = i < lastLineInFile ? getPositionOfLineAndCharacter(file, i + 1, 0) : file.text.length; let lineContent = file.text.slice(lineStart, lineEnd); lineContent = lineContent.replace(/\s+$/g, ""); // trim from end lineContent = lineContent.replace("\t", " "); // convert tabs to single spaces - output += lineContent + sys.newLine; + // Output the actual contents of the line. + output += padLeft(i + 1 + "", gutterWidth) + " ||" + lineContent + sys.newLine; + // Output the error span for the line using tildes. + output += padLeft("", gutterWidth) + " ||"; output += redColorControlChar; if (i === firstLine) { + // If we're on the last line, then limit it to the last character of the last line. + // Otherwise, we'll just squiggle the rest of the line, giving 'slice' no end position. let lastCharForLine = i === lastLine ? lastLineChar : undefined; output += lineContent.slice(0, firstLineChar).replace(/\S/g, " "); @@ -135,9 +154,9 @@ namespace ts { } else if (i === lastLine) { output += lineContent.slice(0, lastLineChar).replace(/./g, "~"); - // Don't bother "filling" at the end. } else { + // Squiggle the entire line. output += lineContent.replace(/./g, "~"); } output += resetColorControlChar; @@ -145,6 +164,7 @@ namespace ts { output += sys.newLine; } + output += sys.newLine; output += `${ file.fileName }(${ firstLine + 1 },${ firstLineChar + 1 }): `; } From 44f3c0ca8a4198ec17952888c038657f8e50dd61 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 19 Aug 2015 12:30:50 -0700 Subject: [PATCH 11/20] Stylize gutter. --- src/compiler/tsc.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 0d8e33413128c..10eddc41b7eee 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -106,8 +106,9 @@ namespace ts { sys.write(output); } - const redColorControlChar = "\u001b[91m"; - const resetColorControlChar = "\u001b[0m"; + const redForegroundEscapeSequence = "\u001b[91m"; + const gutterStyleSequence = "\u001b[100;30m"; + const resetEscapeSequence = "\u001b[0m"; function reportDiagnosticWithColorAndContext(diagnostic: Diagnostic): void { let output = ""; @@ -129,7 +130,7 @@ namespace ts { // If the error spans over 5 lines, we'll only show the first 2 and last 2 lines, // so we'll skip ahead to the second-to-last line. if (hasMoreThanFiveLines && firstLine + 1 < i && i < lastLine - 1) { - output += padLeft("...", gutterWidth) + " ||" + sys.newLine; + output += gutterStyleSequence + padLeft("...", gutterWidth) + resetEscapeSequence + " " + sys.newLine; i = lastLine - 1; } @@ -140,11 +141,11 @@ namespace ts { lineContent = lineContent.replace("\t", " "); // convert tabs to single spaces // Output the actual contents of the line. - output += padLeft(i + 1 + "", gutterWidth) + " ||" + lineContent + sys.newLine; + output += gutterStyleSequence + padLeft(i + 1 + "", gutterWidth) + resetEscapeSequence + " " + lineContent + sys.newLine; // Output the error span for the line using tildes. - output += padLeft("", gutterWidth) + " ||"; - output += redColorControlChar; + output += gutterStyleSequence + padLeft("", gutterWidth) + resetEscapeSequence + " "; + output += redForegroundEscapeSequence; if (i === firstLine) { // If we're on the last line, then limit it to the last character of the last line. // Otherwise, we'll just squiggle the rest of the line, giving 'slice' no end position. @@ -160,7 +161,7 @@ namespace ts { // Squiggle the entire line. output += lineContent.replace(/./g, "~"); } - output += resetColorControlChar; + output += resetEscapeSequence; output += sys.newLine; } From ac5bed86b236da6d2746944819043cce54c9d9cc Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 18 Sep 2015 19:12:08 -0700 Subject: [PATCH 12/20] Added '--diagnosticStyle' compiler argument with options 'simple' and 'pretty'. --- src/compiler/commandLineParser.ts | 11 ++++++++ .../diagnosticInformationMap.generated.ts | 2 ++ src/compiler/diagnosticMessages.json | 9 ++++++ src/compiler/tsc.ts | 28 +++++++++++-------- src/compiler/types.ts | 6 ++++ 5 files changed, 45 insertions(+), 11 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 9a984b9a2f12a..5d7c1bc169070 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -20,6 +20,17 @@ namespace ts { name: "diagnostics", type: "boolean", }, + { + name: "diagnosticStyle", + paramType: Diagnostics.KIND, + description: Diagnostics.Specify_diagnostic_printing_style_Colon_simple_default_or_pretty, + type: { + "simple": DiagnosticStyle.Simple, + "pretty": DiagnosticStyle.Pretty, + }, + error: Diagnostics.Argument_for_diagnosticStyle_must_be_simple_or_pretty, + experimental: true, + }, { name: "emitBOM", type: "boolean" diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 5ccc0a0db9b40..4fdb2221762aa 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -567,6 +567,8 @@ namespace ts { Specifies_the_end_of_line_sequence_to_be_used_when_emitting_files_Colon_CRLF_dos_or_LF_unix: { code: 6060, category: DiagnosticCategory.Message, key: "Specifies the end of line sequence to be used when emitting files: 'CRLF' (dos) or 'LF' (unix)." }, NEWLINE: { code: 6061, category: DiagnosticCategory.Message, key: "NEWLINE" }, Argument_for_newLine_option_must_be_CRLF_or_LF: { code: 6062, category: DiagnosticCategory.Error, key: "Argument for '--newLine' option must be 'CRLF' or 'LF'." }, + Specify_diagnostic_printing_style_Colon_simple_default_or_pretty: { code: 6063, category: DiagnosticCategory.Message, key: "Specify diagnostic printing style: 'simple' (default) or 'pretty'." }, + Argument_for_diagnosticStyle_must_be_simple_or_pretty: { code: 6064, category: DiagnosticCategory.Error, key: "Argument for '--diagnosticStyle' must be 'simple' or 'pretty'." }, Specify_JSX_code_generation_Colon_preserve_or_react: { code: 6080, category: DiagnosticCategory.Message, key: "Specify JSX code generation: 'preserve' or 'react'" }, Argument_for_jsx_must_be_preserve_or_react: { code: 6081, category: DiagnosticCategory.Message, key: "Argument for '--jsx' must be 'preserve' or 'react'." }, Option_experimentalDecorators_must_also_be_specified_when_option_emitDecoratorMetadata_is_specified: { code: 6064, category: DiagnosticCategory.Error, key: "Option 'experimentalDecorators' must also be specified when option 'emitDecoratorMetadata' is specified." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index e138e2ddac489..4a7280f5fda18 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2258,6 +2258,15 @@ "category": "Error", "code": 6062 }, + "Specify diagnostic printing style: 'simple' (default) or 'pretty'.": { + "category": "Message", + "code": 6063 + }, + "Argument for '--diagnosticStyle' must be 'simple' or 'pretty'.": { + "category": "Error", + "code": 6064 + }, + "Specify JSX code generation: 'preserve' or 'react'": { "category": "Message", "code": 6080 diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 10eddc41b7eee..ae1a7cda22036 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -6,9 +6,11 @@ namespace ts { fileWatcher?: FileWatcher; } - const reportDiagnostic = sys.writesToTty && sys.writesToTty() ? - reportDiagnosticWithColorAndContext : - reportDiagnosticSimply; + export interface CompilerOptions { + diagnosticStyle?: DiagnosticStyle; + } + + let reportDiagnostic = reportDiagnosticSimply; function reportDiagnostics(diagnostics: Diagnostic[]): void { for (let diagnostic of diagnostics) { @@ -221,7 +223,7 @@ namespace ts { if (commandLine.options.locale) { if (!isJSONSupported()) { - reportDiagnosticSimply(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--locale")); + reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--locale")); return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } validateLocaleAndSetLanguage(commandLine.options.locale, commandLine.errors); @@ -235,7 +237,7 @@ namespace ts { } if (commandLine.options.version) { - reportDiagnosticSimply(createCompilerDiagnostic(Diagnostics.Version_0, ts.version)); + reportDiagnostic(createCompilerDiagnostic(Diagnostics.Version_0, ts.version)); return sys.exit(ExitStatus.Success); } @@ -247,12 +249,12 @@ namespace ts { if (commandLine.options.project) { if (!isJSONSupported()) { - reportDiagnosticSimply(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--project")); + reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--project")); return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } configFileName = normalizePath(combinePaths(commandLine.options.project, "tsconfig.json")); if (commandLine.fileNames.length !== 0) { - reportDiagnosticSimply(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line)); + reportDiagnostic(createCompilerDiagnostic(Diagnostics.Option_project_cannot_be_mixed_with_source_files_on_a_command_line)); return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } } @@ -270,7 +272,7 @@ namespace ts { // Firefox has Object.prototype.watch if (commandLine.options.watch && commandLine.options.hasOwnProperty("watch")) { if (!sys.watchFile) { - reportDiagnosticSimply(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch")); + reportDiagnostic(createCompilerDiagnostic(Diagnostics.The_current_host_does_not_support_the_0_option, "--watch")); return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } if (configFileName) { @@ -288,7 +290,7 @@ namespace ts { let result = readConfigFile(configFileName); if (result.error) { - reportDiagnosticSimply(result.error); + reportDiagnostic(result.error); return sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); } @@ -310,6 +312,10 @@ namespace ts { compilerHost.getSourceFile = getSourceFile; } + if (compilerOptions.diagnosticStyle === DiagnosticStyle.Pretty) { + reportDiagnostic = reportDiagnosticWithColorAndContext; + } + let compileResult = compile(rootFileNames, compilerOptions, compilerHost); if (!compilerOptions.watch) { @@ -317,7 +323,7 @@ namespace ts { } setCachedProgram(compileResult.program); - reportDiagnosticSimply(createCompilerDiagnostic(Diagnostics.Compilation_complete_Watching_for_file_changes)); + reportDiagnostic(createCompilerDiagnostic(Diagnostics.Compilation_complete_Watching_for_file_changes)); } function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void) { @@ -379,7 +385,7 @@ namespace ts { function recompile() { timerHandle = undefined; - reportDiagnosticSimply(createCompilerDiagnostic(Diagnostics.File_change_detected_Starting_incremental_compilation)); + reportDiagnostic(createCompilerDiagnostic(Diagnostics.File_change_detected_Starting_incremental_compilation)); performCompilation(); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 1338d19e1a747..01a791237ad93 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2094,6 +2094,12 @@ namespace ts { JSX } + /* @internal */ + export const enum DiagnosticStyle { + Simple, + Pretty, + } + export interface ParsedCommandLine { options: CompilerOptions; fileNames: string[]; From 2b4febee1c9eddaa8497a8dcfce0aedc49469db5 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 5 Oct 2015 23:10:04 -0700 Subject: [PATCH 13/20] Moved JSX diagnostics to a more sensical spot. --- src/compiler/diagnosticMessages.json | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 03d890bffa1db..8880544798582 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2258,14 +2258,6 @@ "code": 6063 }, - "Specify JSX code generation: 'preserve' or 'react'": { - "category": "Message", - "code": 6080 - }, - "Argument for '--jsx' must be 'preserve' or 'react'.": { - "category": "Message", - "code": 6081 - }, "Enables experimental support for ES7 decorators.": { "category": "Message", "code": 6065 @@ -2307,6 +2299,15 @@ "code": 6074 }, + "Specify JSX code generation: 'preserve' or 'react'": { + "category": "Message", + "code": 6080 + }, + "Argument for '--jsx' must be 'preserve' or 'react'.": { + "category": "Message", + "code": 6081 + }, + "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", "code": 7005 From c3e00a24f3fccd5dfd126703fa3dbeb95e3261c9 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 5 Oct 2015 23:37:50 -0700 Subject: [PATCH 14/20] Only use colors if we are certain we are using a pseudoterminal. --- src/compiler/sys.ts | 2 +- src/compiler/tsc.ts | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index c50291e60b8c0..fdf6d075cbfd7 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -272,7 +272,7 @@ namespace ts { args: process.argv.slice(2), newLine: _os.EOL, useCaseSensitiveFileNames: useCaseSensitiveFileNames, - write(s: string): void { + write(s: string): void { process.stdout.write(s); }, writesToTty: () => _tty.isatty(1), diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 5222ca2fccf13..d849425a885b6 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -108,9 +108,11 @@ namespace ts { sys.write(output); } - const redForegroundEscapeSequence = "\u001b[91m"; - const gutterStyleSequence = "\u001b[100;30m"; - const resetEscapeSequence = "\u001b[0m"; + const shouldUseColors = sys.writesToTty && sys.writesToTty(); + const redForegroundEscapeSequence = shouldUseColors ? "\u001b[91m" : ""; + const gutterStyleSequence = shouldUseColors ? "\u001b[100;30m" : ""; + const gutterSeparator = shouldUseColors ? " " : " | " + const resetEscapeSequence = shouldUseColors ? "\u001b[0m" : ""; function reportDiagnosticWithColorAndContext(diagnostic: Diagnostic): void { let output = ""; @@ -132,7 +134,7 @@ namespace ts { // If the error spans over 5 lines, we'll only show the first 2 and last 2 lines, // so we'll skip ahead to the second-to-last line. if (hasMoreThanFiveLines && firstLine + 1 < i && i < lastLine - 1) { - output += gutterStyleSequence + padLeft("...", gutterWidth) + resetEscapeSequence + " " + sys.newLine; + output += gutterStyleSequence + padLeft("...", gutterWidth) + resetEscapeSequence + gutterSeparator + sys.newLine; i = lastLine - 1; } @@ -142,11 +144,12 @@ namespace ts { lineContent = lineContent.replace(/\s+$/g, ""); // trim from end lineContent = lineContent.replace("\t", " "); // convert tabs to single spaces - // Output the actual contents of the line. - output += gutterStyleSequence + padLeft(i + 1 + "", gutterWidth) + resetEscapeSequence + " " + lineContent + sys.newLine; + // Output the gutter and the actual contents of the line. + output += gutterStyleSequence + padLeft(i + 1 + "", gutterWidth) + resetEscapeSequence + gutterSeparator; + output += lineContent + sys.newLine; - // Output the error span for the line using tildes. - output += gutterStyleSequence + padLeft("", gutterWidth) + resetEscapeSequence + " "; + // Output the gutter and the error span for the line using tildes. + output += gutterStyleSequence + padLeft("", gutterWidth) + resetEscapeSequence + gutterSeparator; output += redForegroundEscapeSequence; if (i === firstLine) { // If we're on the last line, then limit it to the last character of the last line. From 5c5fca64f03eff1eb9d1519d2181b5ddda429057 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 5 Oct 2015 23:41:44 -0700 Subject: [PATCH 15/20] Just make the compiler option internal. --- src/compiler/tsc.ts | 10 +++------- src/compiler/types.ts | 1 + 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index d849425a885b6..b58f59e8a43ed 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -6,10 +6,6 @@ namespace ts { fileWatcher?: FileWatcher; } - export interface CompilerOptions { - diagnosticStyle?: DiagnosticStyle; - } - let reportDiagnostic = reportDiagnosticSimply; function reportDiagnostics(diagnostics: Diagnostic[]): void { @@ -95,7 +91,7 @@ namespace ts { function reportDiagnosticSimply(diagnostic: Diagnostic): void { let output = ""; - + if (diagnostic.file) { let { line, character } = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start); @@ -111,7 +107,7 @@ namespace ts { const shouldUseColors = sys.writesToTty && sys.writesToTty(); const redForegroundEscapeSequence = shouldUseColors ? "\u001b[91m" : ""; const gutterStyleSequence = shouldUseColors ? "\u001b[100;30m" : ""; - const gutterSeparator = shouldUseColors ? " " : " | " + const gutterSeparator = shouldUseColors ? " " : " | "; const resetEscapeSequence = shouldUseColors ? "\u001b[0m" : ""; function reportDiagnosticWithColorAndContext(diagnostic: Diagnostic): void { @@ -147,7 +143,7 @@ namespace ts { // Output the gutter and the actual contents of the line. output += gutterStyleSequence + padLeft(i + 1 + "", gutterWidth) + resetEscapeSequence + gutterSeparator; output += lineContent + sys.newLine; - + // Output the gutter and the error span for the line using tildes. output += gutterStyleSequence + padLeft("", gutterWidth) + resetEscapeSequence + gutterSeparator; output += redForegroundEscapeSequence; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 48a31c417b7d2..d271f0d47aba3 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2043,6 +2043,7 @@ namespace ts { charset?: string; declaration?: boolean; diagnostics?: boolean; + /* @internal */diagnosticStyle?: DiagnosticStyle; emitBOM?: boolean; help?: boolean; init?: boolean; From 48c2bb1c5005c100e599612fb756b025d70d8fb5 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 30 Oct 2015 18:10:31 -0700 Subject: [PATCH 16/20] Fixed 'tsconfig.json' ordering. --- src/compiler/tsconfig.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/tsconfig.json b/src/compiler/tsconfig.json index fd541a8ca80c1..ca297c087cf0c 100644 --- a/src/compiler/tsconfig.json +++ b/src/compiler/tsconfig.json @@ -11,6 +11,7 @@ "core.ts", "sys.ts", "types.ts", + "diagnosticInformationMap.generated.ts", "scanner.ts", "parser.ts", "utilities.ts", @@ -19,7 +20,6 @@ "emitter.ts", "program.ts", "commandLineParser.ts", - "tsc.ts", - "diagnosticInformationMap.generated.ts" + "tsc.ts" ] } From 4219c5ffecbefea92b507cf57652a0f1ec40c306 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 2 Nov 2015 13:12:19 -0800 Subject: [PATCH 17/20] Added colors to diagnostic types, addressed some CR feedback. --- src/compiler/tsc.ts | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index ab2a83c90d49c..cedfacba9e305 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -104,11 +104,23 @@ namespace ts { sys.write(output); } - const shouldUseColors = sys.writesToTty && sys.writesToTty(); + const shouldUseColors = !!sys.writesToTty && sys.writesToTty(); const redForegroundEscapeSequence = shouldUseColors ? "\u001b[91m" : ""; + const yellowForegroundEscapeSequence = shouldUseColors ? "\u001b[93m" : ""; + const blueForegroundEscapeSequence = shouldUseColors ? "\u001b[93m" : ""; const gutterStyleSequence = shouldUseColors ? "\u001b[100;30m" : ""; const gutterSeparator = shouldUseColors ? " " : " | "; const resetEscapeSequence = shouldUseColors ? "\u001b[0m" : ""; + const elipsis = "..."; + const categoryFormatMap: Map = { + [DiagnosticCategory.Warning]: yellowForegroundEscapeSequence, + [DiagnosticCategory.Error]: redForegroundEscapeSequence, + [DiagnosticCategory.Message]: blueForegroundEscapeSequence, + } + + function formatAndReset(text: string, formatStyle: string) { + return formatStyle + text + resetEscapeSequence; + } function reportDiagnosticWithColorAndContext(diagnostic: Diagnostic): void { let output = ""; @@ -122,7 +134,7 @@ namespace ts { let hasMoreThanFiveLines = (lastLine - firstLine) >= 4; let gutterWidth = (lastLine + 1 + "").length; if (hasMoreThanFiveLines) { - gutterWidth = Math.max("...".length, gutterWidth); + gutterWidth = Math.max(elipsis.length, gutterWidth); } output += sys.newLine; @@ -130,7 +142,7 @@ namespace ts { // If the error spans over 5 lines, we'll only show the first 2 and last 2 lines, // so we'll skip ahead to the second-to-last line. if (hasMoreThanFiveLines && firstLine + 1 < i && i < lastLine - 1) { - output += gutterStyleSequence + padLeft("...", gutterWidth) + resetEscapeSequence + gutterSeparator + sys.newLine; + output += formatAndReset(padLeft(elipsis, gutterWidth), gutterStyleSequence) + gutterSeparator + sys.newLine; i = lastLine - 1; } @@ -141,16 +153,16 @@ namespace ts { lineContent = lineContent.replace("\t", " "); // convert tabs to single spaces // Output the gutter and the actual contents of the line. - output += gutterStyleSequence + padLeft(i + 1 + "", gutterWidth) + resetEscapeSequence + gutterSeparator; + output += formatAndReset(padLeft(i + 1 + "", gutterWidth), gutterStyleSequence) + gutterSeparator; output += lineContent + sys.newLine; // Output the gutter and the error span for the line using tildes. - output += gutterStyleSequence + padLeft("", gutterWidth) + resetEscapeSequence + gutterSeparator; + output += formatAndReset(padLeft("", gutterWidth), gutterStyleSequence) + gutterSeparator; output += redForegroundEscapeSequence; if (i === firstLine) { // If we're on the last line, then limit it to the last character of the last line. // Otherwise, we'll just squiggle the rest of the line, giving 'slice' no end position. - let lastCharForLine = i === lastLine ? lastLineChar : undefined; + const lastCharForLine = i === lastLine ? lastLineChar : undefined; output += lineContent.slice(0, firstLineChar).replace(/\S/g, " "); output += lineContent.slice(firstLineChar, lastCharForLine).replace(/./g, "~"); @@ -171,8 +183,9 @@ namespace ts { output += `${ file.fileName }(${ firstLine + 1 },${ firstLineChar + 1 }): `; } - let category = DiagnosticCategory[diagnostic.category].toLowerCase(); - output += `${ category } TS${ diagnostic.code }: ${ flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine) }`; + const categoryColor = categoryFormatMap[diagnostic.category]; + const category = DiagnosticCategory[diagnostic.category].toLowerCase(); + output += `${ formatAndReset(category, categoryColor) } TS${ diagnostic.code }: ${ flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine) }`; output += sys.newLine + sys.newLine; sys.write(output); From 654cbd977940b367962500f3d89dd28b21383704 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 2 Nov 2015 13:20:48 -0800 Subject: [PATCH 18/20] Just name the option 'pretty' for now. --- src/compiler/commandLineParser.ts | 17 ++++++----------- src/compiler/diagnosticMessages.json | 6 +----- src/compiler/tsc.ts | 2 +- src/compiler/types.ts | 2 +- 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index ee1a36ec45e02..141ab85929e62 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -21,17 +21,6 @@ namespace ts { name: "diagnostics", type: "boolean", }, - { - name: "diagnosticStyle", - paramType: Diagnostics.KIND, - description: Diagnostics.Specify_diagnostic_printing_style_Colon_simple_default_or_pretty, - type: { - "simple": DiagnosticStyle.Simple, - "pretty": DiagnosticStyle.Pretty, - }, - error: Diagnostics.Argument_for_diagnosticStyle_must_be_simple_or_pretty, - experimental: true, - }, { name: "emitBOM", type: "boolean" @@ -162,6 +151,12 @@ namespace ts { type: "boolean", description: Diagnostics.Do_not_erase_const_enum_declarations_in_generated_code }, + { + name: "pretty", + paramType: Diagnostics.KIND, + description: Diagnostics.Stylize_errors_and_messages_using_colors_if_available_experimental, + type: "boolean" + }, { name: "project", shortName: "p", diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 0abe92299bf39..ed17c2a77b015 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2286,14 +2286,10 @@ "category": "Message", "code": 6072 }, - "Specify diagnostic printing style: 'simple' (default) or 'pretty'.": { + "Stylize errors and messages using colors if available. (experimental)": { "category": "Message", "code": 6073 }, - "Argument for '--diagnosticStyle' must be 'simple' or 'pretty'.": { - "category": "Error", - "code": 6074 - }, "Specify JSX code generation: 'preserve' or 'react'": { "category": "Message", diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index cedfacba9e305..66a6cbb65bd1a 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -374,7 +374,7 @@ namespace ts { compilerHost.fileExists = cachedFileExists; } - if (compilerOptions.diagnosticStyle === DiagnosticStyle.Pretty) { + if (compilerOptions.pretty) { reportDiagnostic = reportDiagnosticWithColorAndContext; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ca8a001492451..363c3a4a29f05 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2053,7 +2053,6 @@ namespace ts { charset?: string; declaration?: boolean; diagnostics?: boolean; - /* @internal */diagnosticStyle?: DiagnosticStyle; emitBOM?: boolean; help?: boolean; init?: boolean; @@ -2076,6 +2075,7 @@ namespace ts { outFile?: string; outDir?: string; preserveConstEnums?: boolean; + /* @internal */ pretty?: DiagnosticStyle; project?: string; removeComments?: boolean; rootDir?: string; From 40f10abe01b3765193c62f7eacb7e17e2f911cd7 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 2 Nov 2015 14:48:28 -0800 Subject: [PATCH 19/20] Forget about tty detection. It won't work in build tools. --- src/compiler/sys.ts | 2 -- src/compiler/tsc.ts | 13 ++++++------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index ee9d1a9653c72..6263f7237f609 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -6,7 +6,6 @@ namespace ts { newLine: string; useCaseSensitiveFileNames: boolean; write(s: string): void; - writesToTty?(): boolean; readFile(path: string, encoding?: string): string; writeFile(path: string, data: string, writeByteOrderMark?: boolean): void; watchFile?(path: string, callback: (path: string, removed?: boolean) => void): FileWatcher; @@ -379,7 +378,6 @@ namespace ts { write(s: string): void { process.stdout.write(s); }, - writesToTty: () => _tty.isatty(1), readFile, writeFile, watchFile: (fileName, callback) => { diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 66a6cbb65bd1a..f996797db6ec0 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -104,13 +104,12 @@ namespace ts { sys.write(output); } - const shouldUseColors = !!sys.writesToTty && sys.writesToTty(); - const redForegroundEscapeSequence = shouldUseColors ? "\u001b[91m" : ""; - const yellowForegroundEscapeSequence = shouldUseColors ? "\u001b[93m" : ""; - const blueForegroundEscapeSequence = shouldUseColors ? "\u001b[93m" : ""; - const gutterStyleSequence = shouldUseColors ? "\u001b[100;30m" : ""; - const gutterSeparator = shouldUseColors ? " " : " | "; - const resetEscapeSequence = shouldUseColors ? "\u001b[0m" : ""; + const redForegroundEscapeSequence = "\u001b[91m"; + const yellowForegroundEscapeSequence = "\u001b[93m"; + const blueForegroundEscapeSequence = "\u001b[93m"; + const gutterStyleSequence = "\u001b[100;30m"; + const gutterSeparator = " "; + const resetEscapeSequence = "\u001b[0m"; const elipsis = "..."; const categoryFormatMap: Map = { [DiagnosticCategory.Warning]: yellowForegroundEscapeSequence, From ce24bcb2eecec7c0d5cdc5d760a28b2428d79345 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 2 Nov 2015 15:45:57 -0800 Subject: [PATCH 20/20] ; --- src/compiler/tsc.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index de43ce103328d..083df70be0f76 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -119,7 +119,7 @@ namespace ts { [DiagnosticCategory.Warning]: yellowForegroundEscapeSequence, [DiagnosticCategory.Error]: redForegroundEscapeSequence, [DiagnosticCategory.Message]: blueForegroundEscapeSequence, - } + }; function formatAndReset(text: string, formatStyle: string) { return formatStyle + text + resetEscapeSequence;