///|
/// Counts diagnostics by severity without exposing mutable internal state.
pub struct Summary {
advice : Int
warnings : Int
errors : Int
} derive(Eq, Debug)
///|
pub fn Summary::advice(self : Summary) -> Int {
self.advice
}
///|
pub fn Summary::warnings(self : Summary) -> Int {
self.warnings
}
///|
pub fn Summary::errors(self : Summary) -> Int {
self.errors
}
///|
pub fn Summary::total(self : Summary) -> Int {
self.advice + self.warnings + self.errors
}
///|
pub fn Summary::has_errors(self : Summary) -> Bool {
self.errors > 0
}
///|
/// An insertion-ordered batch of diagnostics.
pub struct DiagnosticBag {
items : Array[Diagnostic]
}
///|
pub fn DiagnosticBag::new() -> DiagnosticBag {
{ items: [] }
}
///|
pub fn DiagnosticBag::from_array(items : Array[Diagnostic]) -> DiagnosticBag {
{ items: items.copy() }
}
///|
pub fn DiagnosticBag::add(
self : DiagnosticBag,
diagnostic : Diagnostic,
) -> Unit {
self.items.push(diagnostic)
}
///|
pub fn DiagnosticBag::length(self : DiagnosticBag) -> Int {
self.items.length()
}
///|
pub fn DiagnosticBag::is_empty(self : DiagnosticBag) -> Bool {
self.items.is_empty()
}
///|
pub fn DiagnosticBag::to_array(self : DiagnosticBag) -> Array[Diagnostic] {
self.items.copy()
}
///|
pub fn DiagnosticBag::summary(self : DiagnosticBag) -> Summary {
let mut advice = 0
let mut warnings = 0
let mut errors = 0
for diagnostic in self.items {
match diagnostic.severity() {
Advice => advice += 1
Warning => warnings += 1
Error => errors += 1
}
}
{ advice, warnings, errors }
}
///|
/// Returns diagnostics at or above the requested severity.
pub fn DiagnosticBag::at_least(
self : DiagnosticBag,
minimum : Severity,
) -> Array[Diagnostic] {
self.items.filter(fn(item) { item.severity().rank() >= minimum.rank() })
}
///|
/// Conventional process exit code: one when a diagnostic reaches the failure
/// threshold, otherwise zero.
pub fn DiagnosticBag::exit_code(
self : DiagnosticBag,
fail_on? : Severity = Error,
) -> Int {
if self.items.any(fn(item) { item.severity().rank() >= fail_on.rank() }) {
1
} else {
0
}
}
///|
/// Renders a diagnostic batch, separated by one blank line.
pub fn DiagnosticBag::render(
self : DiagnosticBag,
sources : SourceMap,
config? : RenderConfig = RenderConfig::default(),
) -> String {
let output = StringBuilder::new()
for index, diagnostic in self.items {
if index > 0 {
output.write_string("\n\n")
}
output.write_string(render(sources, diagnostic, config~))
}
output.to_string()
}
///|
/// Serializes a batch as newline-delimited JSON.
pub fn DiagnosticBag::render_json_lines(
self : DiagnosticBag,
sources : SourceMap,
) -> String {
render_json_lines(sources, self.items)
}