Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions javascript/packages/highlighter/src/diagnostic-renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export interface DiagnosticRenderOptions {
maxWidth?: number
truncateLines?: boolean
codeUrl?: string
suffix?: string
}

export class DiagnosticRenderer {
Expand Down Expand Up @@ -145,9 +146,9 @@ export class DiagnosticRenderer {

const { codeUrl } = options

const text = diagnostic.severity
const color = severityColor(diagnostic.severity)
const diagnosticIdText = colorize(diagnostic.code || "-", "gray")
const text = colorize(colorize(diagnostic.severity, color), "bold")
const diagnosticIdText = diagnostic.code || "-"
const diagnosticId = codeUrl ? hyperlink(diagnosticIdText, codeUrl) : diagnosticIdText

const originalLines = content.split("\n")
Expand Down Expand Up @@ -249,8 +250,10 @@ export class DiagnosticRenderer {
}

const highlightedMessage = this.highlightBackticks(diagnostic.message)
const { suffix } = options
const suffixText = suffix ? ` ${suffix}` : ""

return `[${text}] ${highlightedMessage} (${diagnosticId})
return `[${text}] ${highlightedMessage} (${diagnosticId})${suffixText}

${fileHeader}

Expand Down
5 changes: 5 additions & 0 deletions javascript/packages/highlighter/src/highlighter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export interface HighlightOptions {
maxWidth?: number
truncateLines?: boolean
codeUrlBuilder?: (code: string) => string
suffixBuilder?: (diagnostic: Diagnostic) => string | undefined
}

export interface HighlightDiagnosticOptions {
Expand All @@ -31,6 +32,7 @@ export interface HighlightDiagnosticOptions {
maxWidth?: number
truncateLines?: boolean
codeUrl?: string
suffix?: string
}

export class Highlighter {
Expand Down Expand Up @@ -100,6 +102,7 @@ export class Highlighter {
maxWidth = LineWrapper.getTerminalWidth(),
truncateLines = false,
codeUrlBuilder,
suffixBuilder,
} = options

// Case 1: Split diagnostics - render each diagnostic individually
Expand All @@ -108,13 +111,15 @@ export class Highlighter {
for (let i = 0; i < diagnostics.length; i++) {
const diagnostic = diagnostics[i]
const codeUrl = codeUrlBuilder && diagnostic.code ? codeUrlBuilder(diagnostic.code) : undefined
const suffix = suffixBuilder ? suffixBuilder(diagnostic) : undefined
const result = this.highlightDiagnostic(path, diagnostic, content, {
contextLines,
showLineNumbers,
wrapLines,
maxWidth,
truncateLines,
codeUrl,
suffix,
})

results.push(result)
Expand Down
1 change: 1 addition & 0 deletions javascript/packages/highlighter/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export * from "./file-renderer.js"
export * from "./highlighter.js"
export * from "./line-wrapper.js"
export * from "./syntax-renderer.js"
export * from "./text-formatter.js"
export * from "./themes.js"
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export class InlineDiagnosticRenderer {
}

private getSeverityText(severity: DiagnosticSeverity): string {
return colorize(severity, severityColor(severity))
return colorize(colorize(severity, severityColor(severity)), "bold")
}

private getHighestSeverity(diagnostics: Diagnostic[]): DiagnosticSeverity {
Expand Down Expand Up @@ -167,7 +167,7 @@ export class InlineDiagnosticRenderer {
output += `${pointerPrefix}${pointerSpacing}${pointer}\n`

const severityText = this.getSeverityText(diagnostic.severity)
const diagnosticIdText = colorize(diagnostic.code || "-", "gray")
const diagnosticIdText = diagnostic.code || "-"
const diagnosticId = codeUrlBuilder && diagnostic.code ? hyperlink(diagnosticIdText, codeUrlBuilder(diagnostic.code)) : diagnosticIdText
const highlightedMessage = TextFormatter.highlightBackticks(diagnostic.message)
const diagnosticText = `[${severityText}] ${highlightedMessage} (${diagnosticId})`
Expand All @@ -185,7 +185,7 @@ export class InlineDiagnosticRenderer {
output += `${pointerSpacing}${pointer}\n`

const severityText = this.getSeverityText(diagnostic.severity)
const diagnosticIdText = colorize(diagnostic.code || "-", "gray")
const diagnosticIdText = diagnostic.code || "-"
const diagnosticId = codeUrlBuilder && diagnostic.code ? hyperlink(diagnosticIdText, codeUrlBuilder(diagnostic.code)) : diagnosticIdText
const highlightedMessage = TextFormatter.highlightBackticks(diagnostic.message)
const diagnosticText = `[${severityText}] ${highlightedMessage} (${diagnosticId})`
Expand Down
31 changes: 11 additions & 20 deletions javascript/packages/linter/src/cli/formatters/detailed-formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,14 @@ export class DetailedFormatter extends BaseFormatter {
await this.highlighter.initialize()
}

const correctableTag = colorize(colorize("[Correctable]", "green"), "bold")
const autocorrectableSet = new Set(
allOffenses.filter(item => item.autocorrectable).map(item => item.offense)
)

if (isSingleFile) {
const { filename, content } = allOffenses[0]
const diagnostics = allOffenses.map(item => {
if (item.autocorrectable && item.offense.code) {
return {
...item.offense,
message: `${item.offense.message} ${colorize(colorize("[Correctable]", "green"), "bold")}`
}
}
return item.offense
})
const diagnostics = allOffenses.map(item => item.offense)

const highlighted = this.highlighter.highlight(filename, content, {
diagnostics: diagnostics,
Expand All @@ -47,6 +44,7 @@ export class DetailedFormatter extends BaseFormatter {
wrapLines: this.wrapLines,
truncateLines: this.truncateLines,
codeUrlBuilder: ruleDocumentationUrl,
suffixBuilder: (diagnostic) => autocorrectableSet.has(diagnostic) ? correctableTag : undefined,
})

console.log(`\n${highlighted}`)
Expand All @@ -56,21 +54,14 @@ export class DetailedFormatter extends BaseFormatter {
for (let i = 0; i < allOffenses.length; i++) {
const { filename, offense, content, autocorrectable } = allOffenses[i]

let modifiedOffense = offense

if (autocorrectable && offense.code) {
modifiedOffense = {
...offense,
message: `${offense.message} ${colorize(colorize("[Correctable]", "green"), "bold")}`
}
}

const codeUrl = modifiedOffense.code ? ruleDocumentationUrl(modifiedOffense.code) : undefined
const formatted = this.highlighter.highlightDiagnostic(filename, modifiedOffense, content, {
const codeUrl = offense.code ? ruleDocumentationUrl(offense.code) : undefined
const suffix = autocorrectable ? correctableTag : undefined
const formatted = this.highlighter.highlightDiagnostic(filename, offense, content, {
contextLines: 2,
wrapLines: this.wrapLines,
truncateLines: this.truncateLines,
codeUrl,
suffix,
})
console.log(`\n${formatted}`)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { colorize, hyperlink } from "@herb-tools/highlighter"
import { colorize, hyperlink, TextFormatter } from "@herb-tools/highlighter"

import { BaseFormatter } from "./base-formatter.js"
import { ruleDocumentationUrl } from "../../urls.js"
Expand Down Expand Up @@ -30,14 +30,14 @@ export class SimpleFormatter extends BaseFormatter {
for (const offense of offenses) {
const isError = offense.severity === "error"
const severity = isError ? colorize("✗", "brightRed") : colorize("⚠", "brightYellow")
const ruleText = colorize(`(${offense.code})`, "blue")
const ruleText = `(${offense.code})`
const rule = offense.code ? hyperlink(ruleText, ruleDocumentationUrl(offense.code)) : ruleText
const locationString = `${offense.location.start.line}:${offense.location.start.column}`
const paddedLocation = locationString.padEnd(4)

console.log(` ${colorize(paddedLocation, "gray")} ${severity} ${offense.message} ${rule}`)
const message = TextFormatter.highlightBackticks(offense.message)
console.log(` ${colorize(paddedLocation, "gray")} ${severity} ${message} ${rule}`)
}
console.log("")
}

formatFileProcessed(filename: string, processedFiles: ProcessedFile[]): void {
Expand All @@ -46,14 +46,14 @@ export class SimpleFormatter extends BaseFormatter {
for (const { offense, autocorrectable } of processedFiles) {
const isError = offense.severity === "error"
const severity = isError ? colorize("✗", "brightRed") : colorize("⚠", "brightYellow")
const ruleText = colorize(`(${offense.code})`, "blue")
const ruleText = `(${offense.code})`
const rule = offense.code ? hyperlink(ruleText, ruleDocumentationUrl(offense.code)) : ruleText
const locationString = `${offense.location.start.line}:${offense.location.start.column}`
const paddedLocation = locationString.padEnd(4)
const correctable = autocorrectable ? colorize(colorize(" [Correctable]", "green"), "bold") : ""

console.log(` ${colorize(paddedLocation, "gray")} ${severity} ${offense.message} ${rule}${correctable}`)
const message = TextFormatter.highlightBackticks(offense.message)
console.log(` ${colorize(paddedLocation, "gray")} ${severity} ${message} ${rule}${correctable}`)
}
console.log("")
}
}
23 changes: 9 additions & 14 deletions javascript/packages/linter/src/cli/summary-reporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,20 +41,14 @@ export class SummaryReporter {
const filesClean = filesChecked - filesWithOffenses

let filesSummary = ""
let shouldDim = false

if (filesWithOffenses > 0) {
filesSummary = `${colorize(colorize(`${filesWithOffenses} with offenses`, "brightRed"), "bold")} | ${colorize(colorize(`${filesClean} clean`, "green"), "bold")} ${colorize(colorize(`(${filesChecked} total)`, "gray"), "dim")}`
filesSummary = `${colorize(colorize(`${filesWithOffenses} with offenses`, "brightRed"), "bold")} | ${colorize(colorize(`${filesClean} clean`, "green"), "bold")} ${colorize(`(${filesChecked} total)`, "gray")}`
} else {
filesSummary = `${colorize(colorize(`${filesChecked} clean`, "green"), "bold")} ${colorize(colorize(`(${filesChecked} total)`, "gray"), "dim")}`
shouldDim = true
filesSummary = `${colorize(colorize(`${filesChecked} clean`, "green"), "bold")} ${colorize(`(${filesChecked} total)`, "gray")}`
}

if (shouldDim) {
console.log(colorize(` ${colorize(pad("Files"), "gray")} ${filesSummary}`, "dim"))
} else {
console.log(` ${colorize(pad("Files"), "gray")} ${filesSummary}`)
}
console.log(` ${colorize(pad("Files"), "gray")} ${filesSummary}`)
}

let offensesSummary = ""
Expand Down Expand Up @@ -96,7 +90,7 @@ export class SummaryReporter {
}

if (detailText) {
offensesSummary += ` ${colorize(colorize(`(${detailText})`, "gray"), "dim")}`
offensesSummary += ` ${colorize(`(${detailText})`, "gray")}`
}
}

Expand Down Expand Up @@ -124,7 +118,7 @@ export class SummaryReporter {
const timeString = startDate.toTimeString().split(' ')[0]

console.log(` ${colorize(pad("Start at"), "gray")} ${colorize(timeString, "cyan")}`)
console.log(` ${colorize(pad("Duration"), "gray")} ${colorize(`${duration}ms`, "cyan")} ${colorize(colorize(`(${ruleCount} ${this.pluralize(ruleCount, "rule")})`, "gray"), "dim")}`)
console.log(` ${colorize(pad("Duration"), "gray")} ${colorize(`${duration}ms`, "cyan")} ${colorize(`(${ruleCount} ${this.pluralize(ruleCount, "rule")})`, "gray")}`)
}

if (filesWithOffenses === 0 && files.length > 1) {
Expand All @@ -141,20 +135,21 @@ export class SummaryReporter {
const remainingRules = allRules.slice(limit)

const title = ruleOffenses.size <= limit ? "Rule offenses:" : "Most frequent rule offenses:"
console.log("\n")
console.log(` ${colorize(title, "bold")}`)

for (const [rule, data] of displayedRules) {
const fileCount = data.files.size
const countText = `(${data.count} ${this.pluralize(data.count, "offense")} in ${fileCount} ${this.pluralize(fileCount, "file")})`
const ruleText = colorize(rule, "gray")
const ruleText = colorize(rule, "white")
const ruleLink = hyperlink(ruleText, ruleDocumentationUrl(rule))
console.log(` ${ruleLink} ${colorize(colorize(countText, "gray"), "dim")}`)
console.log(` ${ruleLink} ${colorize(countText, "gray")}`)
}

if (remainingRules.length > 0) {
const remainingOffenseCount = remainingRules.reduce((sum, [_, data]) => sum + data.count, 0)
const remainingRuleCount = remainingRules.length
console.log(colorize(colorize(`\n ...and ${remainingRuleCount} more ${this.pluralize(remainingRuleCount, "rule")} with ${remainingOffenseCount} ${this.pluralize(remainingOffenseCount, "offense")}`, "gray"), "dim"))
console.log(colorize(`\n ...and ${remainingRuleCount} more ${this.pluralize(remainingRuleCount, "rule")} with ${remainingOffenseCount} ${this.pluralize(remainingOffenseCount, "offense")}`, "gray"))
}
}
}
Loading
Loading