///|
pub struct SarifStats {
runs : Int
rules : Int
results : Int
artifacts : Int
invocations : Int
errors : Int
warnings : Int
notes : Int
none : Int
baselined : Int
} derive(Eq, Debug, ToJson)
///|
pub fn SarifStats::empty() -> SarifStats {
{
runs: 0,
rules: 0,
results: 0,
artifacts: 0,
invocations: 0,
errors: 0,
warnings: 0,
notes: 0,
none: 0,
baselined: 0,
}
}
///|
pub fn SarifStats::total_findings(self : SarifStats) -> Int {
self.errors + self.warnings + self.notes + self.none
}
///|
pub fn SarifStats::has_blocking_findings(self : SarifStats) -> Bool {
self.errors > 0
}
///|
fn add_level(stats : SarifStats, level : StringView) -> SarifStats {
match normalize_level(level) {
"error" => { ..stats, errors: stats.errors + 1 }
"warning" => { ..stats, warnings: stats.warnings + 1 }
"note" => { ..stats, notes: stats.notes + 1 }
_ => { ..stats, none: stats.none + 1 }
}
}
///|
pub fn SarifRun::stats(self : SarifRun) -> SarifStats {
let mut stats = SarifStats::empty()
stats = {
..stats,
runs: 1,
rules: self.tool.rules.length(),
artifacts: self.artifacts.length(),
invocations: self.invocations.length(),
}
for result in self.results {
stats = add_level(stats, result.level)
if result.baseline_state is Some(_) {
stats = { ..stats, baselined: stats.baselined + 1 }
}
}
{ ..stats, results: self.results.length() }
}
///|
pub fn SarifLog::stats(self : SarifLog) -> SarifStats {
let mut out = SarifStats::empty()
for run in self.runs {
let stats = run.stats()
out = {
runs: out.runs + stats.runs,
rules: out.rules + stats.rules,
results: out.results + stats.results,
artifacts: out.artifacts + stats.artifacts,
invocations: out.invocations + stats.invocations,
errors: out.errors + stats.errors,
warnings: out.warnings + stats.warnings,
notes: out.notes + stats.notes,
none: out.none + stats.none,
baselined: out.baselined + stats.baselined,
}
}
out
}
///|
pub struct RuleSummary {
rule_id : String
count : Int
errors : Int
warnings : Int
notes : Int
} derive(Eq, Debug, ToJson)
///|
fn find_rule_summary(
items : ArrayView[RuleSummary],
rule_id : StringView,
) -> Int? {
let needle = rule_id.to_owned()
for i, item in items {
if item.rule_id == needle {
return Some(i)
}
}
None
}
///|
pub fn SarifRun::rule_summaries(self : SarifRun) -> Array[RuleSummary] {
let out : Array[RuleSummary] = []
for result in self.results {
match find_rule_summary(out, result.rule_id) {
Some(index) => {
let current = out[index]
let next = match normalize_level(result.level) {
"error" =>
{ ..current, count: current.count + 1, errors: current.errors + 1 }
"warning" =>
{
..current,
count: current.count + 1,
warnings: current.warnings + 1,
}
"note" =>
{ ..current, count: current.count + 1, notes: current.notes + 1 }
_ => { ..current, count: current.count + 1 }
}
out[index] = next
}
None => {
let base = {
rule_id: result.rule_id,
count: 1,
errors: 0,
warnings: 0,
notes: 0,
}
let next = match normalize_level(result.level) {
"error" => { ..base, errors: 1 }
"warning" => { ..base, warnings: 1 }
"note" => { ..base, notes: 1 }
_ => base
}
out.push(next)
}
}
}
out
}
///|
pub fn SarifLog::rule_summaries(self : SarifLog) -> Array[RuleSummary] {
let out : Array[RuleSummary] = []
for run in self.runs {
for summary in run.rule_summaries() {
match find_rule_summary(out, summary.rule_id) {
Some(index) => {
let current = out[index]
out[index] = {
rule_id: current.rule_id,
count: current.count + summary.count,
errors: current.errors + summary.errors,
warnings: current.warnings + summary.warnings,
notes: current.notes + summary.notes,
}
}
None => out.push(summary)
}
}
}
out
}
///|
pub fn SarifStats::summary(self : SarifStats) -> String {
"runs=\{self.runs} rules=\{self.rules} results=\{self.results} errors=\{self.errors} warnings=\{self.warnings} notes=\{self.notes} artifacts=\{self.artifacts}"
}
///|
pub fn SarifLog::summary(self : SarifLog) -> String {
self.stats().summary()
}