///|
/// Mutable builder for constructing a single-run SARIF log.
pub struct SarifBuilder {
tool_name : String
mut tool_version : String?
mut information_uri : String?
rules : Array[SarifRule]
results : Array[SarifResult]
artifacts : Array[Artifact]
invocations : Array[SarifInvocation]
mut automation_id : String?
} derive(Debug)
///|
pub fn SarifBuilder::SarifBuilder(
tool_name : StringView,
tool_version? : String,
information_uri? : String,
) -> SarifBuilder {
{
tool_name: tool_name.to_owned(),
tool_version,
information_uri,
rules: [],
results: [],
artifacts: [],
invocations: [],
automation_id: None,
}
}
///|
pub fn SarifBuilder::set_tool_version(
self : SarifBuilder,
version : StringView,
) -> Unit {
self.tool_version = Some(version.to_owned())
}
///|
pub fn SarifBuilder::set_information_uri(
self : SarifBuilder,
uri : StringView,
) -> Unit {
self.information_uri = Some(uri.to_owned())
}
///|
pub fn SarifBuilder::set_automation_id(
self : SarifBuilder,
id : StringView,
) -> Unit {
self.automation_id = Some(id.to_owned())
}
///|
pub fn SarifBuilder::rule_count(self : SarifBuilder) -> Int {
self.rules.length()
}
///|
pub fn SarifBuilder::result_count(self : SarifBuilder) -> Int {
self.results.length()
}
///|
pub fn SarifBuilder::artifact_count(self : SarifBuilder) -> Int {
self.artifacts.length()
}
///|
fn find_rule_index(rules : ArrayView[SarifRule], id : StringView) -> Int? {
let needle = id.to_owned()
for i, rule in rules {
if rule.id == needle {
return Some(i)
}
}
None
}
///|
fn find_artifact_index(
artifacts : ArrayView[Artifact],
uri : StringView,
) -> Int? {
let needle = uri.to_owned()
for i, artifact in artifacts {
if artifact.location.uri == needle {
return Some(i)
}
}
None
}
///|
pub fn SarifBuilder::add_rule(
self : SarifBuilder,
id : StringView,
name? : String,
short_description? : String,
default_level? : String = "warning",
tags? : ArrayView[String] = [],
) -> Int {
match find_rule_index(self.rules, id) {
Some(index) => index
None => {
let index = self.rules.length()
self.rules.push({
id: id.to_owned(),
name,
short_description: short_description.map(text => {
SarifMessage::SarifMessage(text)
}),
full_description: None,
default_level: normalize_level(default_level),
help_uri: None,
tags: tags.to_owned(),
})
index
}
}
}
///|
pub fn SarifBuilder::add_rule_object(
self : SarifBuilder,
rule : SarifRule,
) -> Int {
match find_rule_index(self.rules, rule.id) {
Some(index) => index
None => {
let index = self.rules.length()
self.rules.push(rule)
index
}
}
}
///|
pub fn SarifBuilder::add_artifact(
self : SarifBuilder,
uri : StringView,
length? : Int,
mime_type? : String,
roles? : ArrayView[String] = [],
) -> Int {
match find_artifact_index(self.artifacts, uri) {
Some(index) => index
None => {
let index = self.artifacts.length()
let artifact = {
location: ArtifactLocation::ArtifactLocation(uri),
length,
mime_type,
roles: roles.to_owned(),
}
self.artifacts.push(artifact)
index
}
}
}
///|
pub fn SarifBuilder::add_invocation(
self : SarifBuilder,
command_line? : String,
working_directory? : String,
execution_successful? : Bool = true,
) -> Unit {
self.invocations.push({
command_line,
working_directory,
execution_successful,
})
}
///|
pub fn SarifBuilder::add_result(
self : SarifBuilder,
rule_id : StringView,
message : StringView,
level? : String = "warning",
uri? : String,
line? : Int,
column? : Int = 1,
) -> Int {
self.add_rule(rule_id, default_level=level) |> ignore
let locations : Array[SarifLocation] = []
if uri is Some(path) {
self.add_artifact(path) |> ignore
let row = match line {
Some(value) => value
None => 1
}
locations.push(SarifLocation::from_path(path, row, column~))
}
let result = SarifResult::SarifResult(
rule_id,
message,
level=normalize_level(level),
locations~,
)
let index = self.results.length()
self.results.push(result)
index
}
///|
pub fn SarifBuilder::add_result_object(
self : SarifBuilder,
result : SarifResult,
) -> Int {
self.add_rule(result.rule_id, default_level=result.level) |> ignore
if result.primary_uri() is Some(uri) {
self.add_artifact(uri) |> ignore
}
let index = self.results.length()
self.results.push(result)
index
}
///|
pub fn SarifBuilder::add_fingerprinted_result(
self : SarifBuilder,
rule_id : StringView,
message : StringView,
uri : StringView,
line : Int,
column? : Int = 1,
level? : String = "warning",
) -> Int {
let location = SarifLocation::from_path(uri, line, column~)
let key = stable_result_key(rule_id, message, uri, line, column)
let result = SarifResult::SarifResult(
rule_id,
message,
level=normalize_level(level),
locations=[location],
fingerprints=[Fingerprint::Fingerprint("stableKey", key)],
)
self.add_result_object(result)
}
///|
pub fn SarifBuilder::run(self : SarifBuilder) -> SarifRun {
let driver = {
name: self.tool_name,
version: self.tool_version,
information_uri: self.information_uri,
rules: self.rules.copy(),
}
{
tool: driver,
results: self.results.copy(),
artifacts: self.artifacts.copy(),
invocations: self.invocations.copy(),
automation_id: self.automation_id,
}
}
///|
pub fn SarifBuilder::log(self : SarifBuilder) -> SarifLog {
SarifLog::SarifLog([self.run()])
}
///|
pub fn quick_log(
tool_name : StringView,
rule_id : StringView,
message : StringView,
uri : StringView,
line : Int,
column? : Int = 1,
level? : String = "warning",
) -> SarifLog {
let builder = SarifBuilder::SarifBuilder(tool_name)
builder.add_fingerprinted_result(rule_id, message, uri, line, column~, level~)
|> ignore
builder.log()
}