-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stylize tsc's error messages with color and context #5140
Merged
Merged
Changes from 18 commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
ba7fade
Add support to tell whether output directs to a terminal emulator.
DanielRosenwasser f660bd3
Got "prettier" error printing working.
DanielRosenwasser 17f443a
Just squiggle the entire line for middle lines (sans trailing space).
DanielRosenwasser fdbea8b
Give the new reporter a more reasonable name.
DanielRosenwasser d8e462d
Make output reliant on whether stdout redirects to a terminal; use fo…
DanielRosenwasser cc6b04c
Bring back 'reportDiagnostics'.
DanielRosenwasser 99f6985
Don't expand tabs; just use a space.
DanielRosenwasser 85b54e8
Fixed out of bounds error; made index start directly at the line number.
DanielRosenwasser dda058b
Use 'process.stdout.write' to ensure colors get displayed correctly o…
DanielRosenwasser 3c04dff
Limit errors to 5 lines, fixed some other issues.
DanielRosenwasser ea1882d
Merge branch 'master' into iFeelPrettyErr
DanielRosenwasser 44f3c0c
Stylize gutter.
DanielRosenwasser ac5bed8
Added '--diagnosticStyle' compiler argument with options 'simple' and…
DanielRosenwasser 7c73a66
Merge branch 'master' into iFeelPrettyErr
DanielRosenwasser 2b4febe
Moved JSX diagnostics to a more sensical spot.
DanielRosenwasser c3e00a2
Only use colors if we are certain we are using a pseudoterminal.
DanielRosenwasser 5c5fca6
Just make the compiler option internal.
DanielRosenwasser 87554cb
Merge branch 'master' into iFeelPrettyErr
DanielRosenwasser fa2e614
Merge branch 'master' into iFeelPrettyErr
DanielRosenwasser 48c2bb1
Fixed 'tsconfig.json' ordering.
DanielRosenwasser 4219c5f
Added colors to diagnostic types, addressed some CR feedback.
DanielRosenwasser 654cbd9
Just name the option 'pretty' for now.
DanielRosenwasser 40f10ab
Forget about tty detection. It won't work in build tools.
DanielRosenwasser e5f1053
Merge branch 'master' into iFeelPrettyErr
DanielRosenwasser 32b259e
Merge branch 'master' into iFeelPrettyErr
DanielRosenwasser ce24bcb
;
DanielRosenwasser File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,6 +6,14 @@ namespace ts { | |
fileWatcher?: FileWatcher; | ||
} | ||
|
||
let reportDiagnostic = 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. | ||
|
@@ -81,12 +89,13 @@ namespace ts { | |
return <string>diagnostic.messageText; | ||
} | ||
|
||
function reportDiagnostic(diagnostic: Diagnostic) { | ||
function reportDiagnosticSimply(diagnostic: Diagnostic): void { | ||
let output = ""; | ||
|
||
if (diagnostic.file) { | ||
let loc = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start); | ||
output += `${ diagnostic.file.fileName }(${ loc.line + 1 },${ loc.character + 1 }): `; | ||
let { line, character } = getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start); | ||
|
||
output += `${ diagnostic.file.fileName }(${ line + 1 },${ character + 1 }): `; | ||
} | ||
|
||
let category = DiagnosticCategory[diagnostic.category].toLowerCase(); | ||
|
@@ -95,10 +104,78 @@ namespace ts { | |
sys.write(output); | ||
} | ||
|
||
function reportDiagnostics(diagnostics: Diagnostic[]) { | ||
for (let i = 0; i < diagnostics.length; i++) { | ||
reportDiagnostic(diagnostics[i]); | ||
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 = ""; | ||
|
||
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); | ||
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 += gutterStyleSequence + padLeft("...", gutterWidth) + resetEscapeSequence + gutterSeparator + sys.newLine; | ||
i = lastLine - 1; | ||
} | ||
|
||
let lineStart = getPositionOfLineAndCharacter(file, i, 0); | ||
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 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; | ||
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, " "); | ||
output += lineContent.slice(firstLineChar, lastCharForLine).replace(/./g, "~"); | ||
} | ||
else if (i === lastLine) { | ||
output += lineContent.slice(0, lastLineChar).replace(/./g, "~"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sound like a long way to say |
||
} | ||
else { | ||
// Squiggle the entire line. | ||
output += lineContent.replace(/./g, "~"); | ||
} | ||
output += resetEscapeSequence; | ||
|
||
output += sys.newLine; | ||
} | ||
|
||
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 reportWatchDiagnostic(diagnostic: Diagnostic) { | ||
|
@@ -252,6 +329,10 @@ namespace ts { | |
compilerHost.getSourceFile = getSourceFile; | ||
} | ||
|
||
if (compilerOptions.diagnosticStyle === DiagnosticStyle.Pretty) { | ||
reportDiagnostic = reportDiagnosticWithColorAndContext; | ||
} | ||
|
||
let compileResult = compile(rootFileNames, compilerOptions, compilerHost); | ||
|
||
if (!compilerOptions.watch) { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
capture the ellipses in a const, and so is its length.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also applies to the squiggle down below.