///|
fn json_string(value : String) -> String {
let output = StringBuilder()
output.write_char('"')
for char in value {
match char {
'"' => output.write_string("\\\"")
'\\' => output.write_string("\\\\")
'\n' => output.write_string("\\n")
'\r' => output.write_string("\\r")
'\t' => output.write_string("\\t")
other =>
if other.to_int() < 32 {
let hex = other.to_int().to_string(radix=16)
let padded = if hex.length() == 1 { "0" + hex } else { hex }
output.write_string("\\u00" + padded)
} else {
output.write_char(other)
}
}
}
output.write_char('"')
output.to_string()
}
///|
fn json_strings(values : Array[String]) -> String {
let output = StringBuilder()
output.write_char('[')
for index, value in values {
if index > 0 {
output.write_char(',')
}
output.write_string(json_string(value))
}
output.write_char(']')
output.to_string()
}
///|
fn json_optional_string(value : String?) -> String {
match value {
Some(actual) => json_string(actual)
None => "null"
}
}
///|
fn json_optional_int(value : Int?) -> String {
match value {
Some(actual) => actual.to_string()
None => "null"
}
}
///|
fn json_bool(value : Bool) -> String {
if value {
"true"
} else {
"false"
}
}
///|
fn json_kinds(values : Array[ChangeKind]) -> String {
json_strings(values.map(fn(kind) { kind.to_text() }))
}
///|
pub fn Finding::to_json(self : Finding) -> String {
"{" +
"\"level\":" +
json_string(self.level.to_text()) +
",\"code\":" +
json_string(self.code) +
",\"path\":" +
json_string(self.path) +
",\"message\":" +
json_string(self.message) +
"}"
}
///|
pub fn PathDecision::to_json(self : PathDecision) -> String {
"{" +
"\"path\":" +
json_string(self.path) +
",\"owners\":" +
json_strings(self.owners) +
",\"owner_pattern\":" +
json_optional_string(self.owner_pattern) +
",\"matched_rules\":" +
json_strings(self.matched_rules) +
",\"approvals\":" +
self.approvals.to_string() +
",\"checks\":" +
json_strings(self.checks) +
",\"labels\":" +
json_strings(self.labels) +
",\"forbidden\":" +
json_kinds(self.forbidden) +
",\"max_lines\":" +
json_optional_int(self.max_lines) +
",\"release_note\":" +
json_bool(self.release_note) +
",\"allow_binary\":" +
json_bool(self.allow_binary) +
"}"
}
///|
pub fn PathDecision::to_explain_json(self : PathDecision) -> String {
"{\"schema\":\"moonchange.explain.v1\",\"decision\":" + self.to_json() + "}"
}
///|
pub fn ReviewPlan::to_json(self : ReviewPlan) -> String {
"{" +
"\"required_owners\":" +
json_strings(self.required_owners) +
",\"approved_owners\":" +
json_strings(self.approved_owners) +
",\"unapproved_owners\":" +
json_strings(self.unapproved_owners) +
",\"required_checks\":" +
json_strings(self.required_checks) +
",\"passed_checks\":" +
json_strings(self.passed_checks) +
",\"unresolved_checks\":" +
json_strings(self.unresolved_checks) +
",\"required_labels\":" +
json_strings(self.required_labels) +
",\"present_labels\":" +
json_strings(self.present_labels) +
",\"missing_labels\":" +
json_strings(self.missing_labels) +
",\"touched_rules\":" +
json_strings(self.touched_rules) +
",\"maximum_path_approvals\":" +
self.maximum_path_approvals.to_string() +
",\"release_note_required\":" +
json_bool(self.release_note_required) +
",\"release_note_present\":" +
json_bool(self.release_note_present) +
"}"
}
///|
pub fn AuditReport::to_json(self : AuditReport) -> String {
let output = StringBuilder()
output.write_string(
"{\"schema\":\"moonchange.audit.v1\",\"change_id\":" +
json_string(self.change_id) +
",\"status\":" +
json_string(self.status.to_text()) +
",\"total_lines\":" +
self.total_lines.to_string() +
",\"decisions\":[",
)
for index, decision in self.decisions {
if index > 0 {
output.write_char(',')
}
output.write_string(decision.to_json())
}
output.write_string("],\"findings\":[")
for index, finding in self.findings {
if index > 0 {
output.write_char(',')
}
output.write_string(finding.to_json())
}
output.write_string("],\"plan\":" + self.plan.to_json() + "}")
output.to_string()
}
///|
pub fn LintIssue::to_json(self : LintIssue) -> String {
"{" +
"\"level\":" +
json_string(self.level.to_text()) +
",\"code\":" +
json_string(self.code) +
",\"subject\":" +
json_string(self.subject) +
",\"message\":" +
json_string(self.message) +
"}"
}
///|
pub fn LintReport::to_json(self : LintReport) -> String {
let output = StringBuilder()
output.write_string(
"{\"schema\":\"moonchange.lint.v1\",\"clean\":" +
json_bool(self.issues.is_empty()) +
",\"has_errors\":" +
json_bool(self.has_errors()) +
",\"issues\":[",
)
for index, issue in self.issues {
if index > 0 {
output.write_char(',')
}
output.write_string(issue.to_json())
}
output.write_string("]}")
output.to_string()
}
///|
pub fn StringDelta::to_json(self : StringDelta) -> String {
"{\"added\":" +
json_strings(self.added) +
",\"removed\":" +
json_strings(self.removed) +
"}"
}
///|
pub fn PathPolicyDelta::to_json(self : PathPolicyDelta) -> String {
"{" +
"\"path\":" +
json_string(self.path) +
",\"changed\":" +
json_bool(self.changed()) +
",\"before\":" +
self.before.to_json() +
",\"after\":" +
self.after.to_json() +
",\"owners\":" +
self.owners.to_json() +
",\"rules\":" +
self.rules.to_json() +
",\"checks\":" +
self.checks.to_json() +
",\"labels\":" +
self.labels.to_json() +
",\"forbidden\":" +
self.forbidden.to_json() +
"}"
}
///|
pub fn PolicyComparison::to_json(self : PolicyComparison) -> String {
let output = StringBuilder()
output.write_string(
"{\"schema\":\"moonchange.compare.v1\",\"path_count\":" +
self.paths.length().to_string() +
",\"changed_count\":" +
self.changed_count().to_string() +
",\"paths\":[",
)
for index, path in self.paths {
if index > 0 {
output.write_char(',')
}
output.write_string(path.to_json())
}
output.write_string("]}")
output.to_string()
}