///|
pub fn Diagnostic::with_rule(self : Diagnostic, rule : String) -> Diagnostic {
{ ..self, rule, }
}
///|
pub fn Diagnostic::with_notes(
self : Diagnostic,
notes : Array[String],
) -> Diagnostic {
{ ..self, notes, }
}
///|
pub fn Diagnostic::location_key(self : Diagnostic) -> String {
self.file + ":" + self.span.start.to_string() + ":" + self.code
}
///|
pub fn Diagnostic::is_at_least(self : Diagnostic, minimum : Severity) -> Bool {
match (minimum, self.severity) {
(Error, Error) => true
(Warning, Error | Warning) => true
(Info, Error | Warning | Info) => true
_ => false
}
}
///|
pub fn stable_diagnostic_order(
diagnostics : Array[Diagnostic],
) -> Array[Diagnostic] {
let result : Array[Diagnostic] = []
for diagnostic in diagnostics {
let mut inserted = false
let key = diagnostic.location_key()
for index, existing in result {
if !inserted && key < existing.location_key() {
result.insert(index, diagnostic)
inserted = true
}
}
if !inserted {
result.push(diagnostic)
}
}
result
}
///|
pub fn group_diagnostics_by_code(
diagnostics : Array[Diagnostic],
) -> Array[(String, Int)] {
let result : Array[(String, Int)] = []
for diagnostic in diagnostics {
let mut found = false
for index, entry in result {
let (code, count) = entry
if code == diagnostic.code {
result[index] = (code, count + 1)
found = true
}
}
if !found {
result.push((diagnostic.code, 1))
}
}
result
}
///|
pub fn diagnostics_for_file(
diagnostics : Array[Diagnostic],
file : String,
) -> Array[Diagnostic] {
diagnostics.filter(fn(item) { item.file == file })
}
///|
pub fn diagnostics_have_code(
diagnostics : Array[Diagnostic],
code : String,
) -> Bool {
diagnostics.any(fn(item) { item.code == code })
}
///|
pub fn diagnostic_summary(diagnostics : Array[Diagnostic]) -> String {
let (errors, warnings, infos) = severity_counts(diagnostics)
"errors=" +
errors.to_string() +
", warnings=" +
warnings.to_string() +
", infos=" +
infos.to_string() +
", total=" +
diagnostics.length().to_string()
}
///|
pub fn render_diagnostic_table(diagnostics : Array[Diagnostic]) -> String {
let builder = StringBuilder()
builder.write_string("CODE\tSEVERITY\tFILE\tSTART\tMESSAGE\n")
for diagnostic in stable_diagnostic_order(diagnostics) {
builder.write_string(diagnostic.code)
builder.write_char('\t')
builder.write_string(diagnostic.severity.label())
builder.write_char('\t')
builder.write_string(diagnostic.file)
builder.write_char('\t')
builder.write_object(diagnostic.span.start)
builder.write_char('\t')
builder.write_string(diagnostic.message)
builder.write_char('\n')
}
builder.to_string()
}