UNPKG

typescript

Version:

TypeScript is a language for application scale JavaScript development

169 lines • 7 kB
import { convertToRelativePath } from "./path.js"; const foregroundColorEscapeGrey = "\x1b[90m"; const foregroundColorEscapeRed = "\x1b[91m"; const foregroundColorEscapeYellow = "\x1b[93m"; const foregroundColorEscapeBlue = "\x1b[94m"; const foregroundColorEscapeCyan = "\x1b[96m"; const gutterStyleSequence = "\x1b[7m"; const gutterSeparator = " "; const resetEscapeSequence = "\x1b[0m"; const ellipsis = "..."; const halfIndent = " "; const indent = " "; const fileAppearsToBeBinaryCode = 1490; function diagnosticCategoryName(category) { switch (category) { case 0: return "warning"; case 1: return "error"; case 2: return "suggestion"; case 3: return "message"; default: throw new Error(`Unknown diagnostic category: ${category}`); } } function getCategoryFormat(category) { switch (category) { case 0: return foregroundColorEscapeYellow; case 1: return foregroundColorEscapeRed; case 2: return foregroundColorEscapeGrey; case 3: return foregroundColorEscapeBlue; default: throw new Error(`Unknown diagnostic category: ${category}`); } } function formatColorAndReset(text, formatStyle) { return formatStyle + text + resetEscapeSequence; } function diagnosticPrefix(diagnostic) { return diagnostic.source || "TS"; } function flattenDiagnosticMessage(diagnostic, newLine, indentLevel = 0) { let result = ""; if (indentLevel) { result += newLine + " ".repeat(indentLevel); } result += diagnostic.text; for (const child of diagnostic.messageChain ?? []) { result += flattenDiagnosticMessage(child, newLine, indentLevel + 1); } return result; } function relativeFileName(fileName, host) { return convertToRelativePath(fileName, host.getCurrentDirectory(), name => host.getCanonicalFileName(name)); } function formatLocation(diagnostic, host) { if (!diagnostic.fileName || !diagnostic.startPosition) return ""; const fileName = relativeFileName(diagnostic.fileName, host); const { line, character } = diagnostic.startPosition; return formatColorAndReset(fileName, foregroundColorEscapeCyan) + ":" + formatColorAndReset(`${line + 1}`, foregroundColorEscapeYellow) + ":" + formatColorAndReset(`${character + 1}`, foregroundColorEscapeYellow); } function formatCodeSpan(diagnostic, lineIndent, squiggleColor, host) { const { startPosition, endPosition, sourceLines } = diagnostic; if (!startPosition || !endPosition || !sourceLines?.length) return ""; const endCharacter = startPosition.line === endPosition.line && startPosition.character === endPosition.character ? endPosition.character + 1 : endPosition.character; const hasMoreThanFiveLines = endPosition.line - startPosition.line >= 4; const gutterWidth = hasMoreThanFiveLines ? Math.max(ellipsis.length, `${endPosition.line + 1}`.length) : `${endPosition.line + 1}`.length; let context = ""; let previousLine; for (const sourceLine of sourceLines) { if (previousLine !== undefined && sourceLine.line > previousLine + 1) { context += host.getNewLine(); context += lineIndent + formatColorAndReset(ellipsis.padStart(gutterWidth), gutterStyleSequence) + gutterSeparator; } const lineContent = sourceLine.text.trimEnd().replace(/\t/g, " "); context += host.getNewLine(); context += lineIndent + formatColorAndReset(`${sourceLine.line + 1}`.padStart(gutterWidth), gutterStyleSequence) + gutterSeparator + lineContent + host.getNewLine(); context += lineIndent + formatColorAndReset("".padStart(gutterWidth), gutterStyleSequence) + gutterSeparator + squiggleColor; if (sourceLine.line === startPosition.line) { const lastCharacter = sourceLine.line === endPosition.line ? endCharacter : lineContent.length; context += " ".repeat(startPosition.character); context += "~".repeat(Math.max(0, lastCharacter - startPosition.character)); } else if (sourceLine.line === endPosition.line) { context += "~".repeat(endCharacter); } else { context += "~".repeat(lineContent.length); } context += resetEscapeSequence; previousLine = sourceLine.line; } return context; } export function formatDiagnostics(diagnostics, host) { let output = ""; for (const diagnostic of diagnostics) { const errorMessage = `${diagnosticCategoryName(diagnostic.category)} ${diagnosticPrefix(diagnostic)}${diagnostic.code}: ${flattenDiagnosticMessage(diagnostic, host.getNewLine())}${host.getNewLine()}`; if (diagnostic.fileName && diagnostic.startPosition) { const { line, character } = diagnostic.startPosition; output += `${relativeFileName(diagnostic.fileName, host)}(${line + 1},${character + 1}): ${errorMessage}`; } else { output += errorMessage; } } return output; } export function formatDiagnosticsWithColorAndContext(diagnostics, host) { let output = ""; for (let i = 0; i < diagnostics.length; i++) { if (i > 0) { output += host.getNewLine(); } const diagnostic = diagnostics[i]; if (diagnostic.fileName && diagnostic.startPosition) { output += formatLocation(diagnostic, host) + " - "; } output += formatColorAndReset(diagnosticCategoryName(diagnostic.category), getCategoryFormat(diagnostic.category)); output += formatColorAndReset(` ${diagnosticPrefix(diagnostic)}${diagnostic.code}: `, foregroundColorEscapeGrey); output += flattenDiagnosticMessage(diagnostic, host.getNewLine()); if (diagnostic.fileName && diagnostic.code !== fileAppearsToBeBinaryCode) { output += host.getNewLine(); output += formatCodeSpan(diagnostic, "", getCategoryFormat(diagnostic.category), host); output += host.getNewLine(); } if (diagnostic.relatedInformation?.length) { for (const related of diagnostic.relatedInformation) { if (related.fileName && related.startPosition) { output += host.getNewLine(); output += halfIndent + formatLocation(related, host); output += " - " + flattenDiagnosticMessage(related, host.getNewLine()); output += formatCodeSpan(related, indent, foregroundColorEscapeCyan, host); } output += host.getNewLine(); } } } return output; } //# sourceMappingURL=diagnosticFormatter.js.map