///|
pub(all) enum DiagnosticKind {
Parse
Validation
Graph
Execution
} derive(Debug, Eq)
///|
pub impl Show for DiagnosticKind with fn output(
self : DiagnosticKind,
logger : &Logger,
) -> Unit {
match self {
Parse => logger.write_string("Parse")
Validation => logger.write_string("Validation")
Graph => logger.write_string("Graph")
Execution => logger.write_string("Execution")
}
}
///|
pub(all) struct Diagnostic {
kind : DiagnosticKind
code : String
message : String
subject : String
hint : String
} derive(Debug, Eq)
///|
pub fn Diagnostic::to_text(self : Diagnostic) -> String {
let kind = match self.kind {
Parse => "parse"
Validation => "validation"
Graph => "graph"
Execution => "execution"
}
kind +
"[" +
self.code +
"] " +
self.message +
" (" +
self.subject +
") hint: " +
self.hint
}
///|
fn diagnostic(
kind : DiagnosticKind,
code : String,
message : String,
subject : String,
hint : String,
) -> Diagnostic {
{ kind, code, message, subject, hint }
}
///|
pub fn Manifest::diagnostics_for_manifest(self : Manifest) -> Array[Diagnostic] {
let result : Array[Diagnostic] = []
for issue in self.validation_issues() {
let hint = match issue.code {
"unknown-rule" => "declare the rule before using it"
"empty-outputs" => "add at least one output to the build edge"
"duplicate-output" => "make one edge the unique producer"
"empty-manifest" => "add a rule and a build edge"
"empty-rules" => "declare at least one rule"
_ => "review the supported manifest subset"
}
result.push(
diagnostic(Validation, issue.code, issue.message, issue.subject, hint),
)
}
result
}
///|
pub fn diagnostics_for_parse(error : ParseError) -> Diagnostic {
match error {
ParseError::SyntaxError(message, line~, col~) =>
diagnostic(
Parse,
"syntax-error",
message,
line.to_string() + ":" + col.to_string(),
"check the rule, command, colon, and build input syntax",
)
ParseError::UnexpectedToken(token, expected~) =>
diagnostic(
Parse,
"unexpected-token",
"unexpected " + token.to_string(),
expected,
"use a supported rule or build declaration",
)
}
}
///|
pub fn diagnostics_for_graph(error : String) -> Diagnostic {
diagnostic(
Graph,
if error.contains("SCC") {
"cycle"
} else {
"graph-error"
},
error,
"dependency graph",
"inspect the target's producer and input edges",
)
}
///|
pub fn diagnostics_text(diagnostics : Array[Diagnostic]) -> String {
let lines : Array[String] = []
for item in diagnostics {
lines.push(item.to_text())
}
join_strings(lines, "\n")
}