diff --git a/sarif-fmt/src/bin.rs b/sarif-fmt/src/bin.rs index b5aee684..88073c24 100644 --- a/sarif-fmt/src/bin.rs +++ b/sarif-fmt/src/bin.rs @@ -133,6 +133,7 @@ use codespan_reporting::term::termcolor::ColorSpec; use codespan_reporting::term::termcolor::StandardStream; use codespan_reporting::term::termcolor::WriteColor; use serde_sarif::sarif; +use serde_sarif::sarif::ResultKind; use serde_sarif::sarif::ResultLevel; use std::fs::File; use std::io::Write; @@ -324,94 +325,93 @@ fn resolve_level( run: &sarif::Run, result: &sarif::Result, ) -> sarif::ResultLevel { - result + let kind = result .kind .as_ref() // 3.27.9 kind property // If kind is absent, it SHALL default to "fail". - .map_or(Some("fail"), |k| k.as_str()) - .and_then(|kind| match kind { - // If kind has the value "fail" and level is absent, then level SHALL be determined by the following procedure: - "fail" => match result.level.as_ref() { - Some(level) => level.as_str().and_then(|level| { - sarif::ResultLevel::from_str(level).map_or(None, Option::from) - }), - None => result.rule.as_ref().and_then(|rule| { - // IF rule (§3.27.7) is present THEN - rule.index.and_then(|rule_index| { - rules - .get(rule_index as usize) - // LET theDescriptor be the reportingDescriptor object (§3.49) that it specifies. - // # Is there a configuration override for the level property? - .and_then(|the_descriptor| { - // IF result.provenance.invocationIndex (§3.27.29, §3.48.6) is >= 0 THEN - result - .provenance - .as_ref() - .and_then(|provenance| { - provenance.invocation_index.and_then(|invocation_index| { - run - .invocations - .iter() - .flatten() - .collect::>() - .get(invocation_index as usize) - // LET theInvocation be the invocation object (§3.20) that it specifies. - // IF theInvocation.ruleConfigurationOverrides (§3.20.5) is present - // AND it contains a configurationOverride object (§3.51) whose - // descriptor property (§3.51.2) specifies theDescriptor THEN - .and_then(|the_invocation| { - the_invocation - .rule_configuration_overrides - .as_ref() - .and_then(|rule_configuration_overrides| { - rule_configuration_overrides - .iter() - .find(|v| { - v.descriptor.id.as_ref() - == Some(&the_descriptor.id) - }) - .and_then(|the_override| { - the_override - .configuration - .level - .as_ref() - .and_then(|value| { - value.as_str().and_then(|level| { - sarif::ResultLevel::from_str(level) - .map_or(None, Option::from) - }) + .unwrap_or(&ResultKind::Fail); + + match kind { + // If kind has the value "fail" and level is absent, then level SHALL be determined by the following procedure: + ResultKind::Fail => match result.level.as_ref() { + Some(level) => Some(level.clone()), + None => result.rule.as_ref().and_then(|rule| { + // IF rule (§3.27.7) is present THEN + rule.index.and_then(|rule_index| { + rules + .get(rule_index as usize) + // LET theDescriptor be the reportingDescriptor object (§3.49) that it specifies. + // # Is there a configuration override for the level property? + .and_then(|the_descriptor| { + // IF result.provenance.invocationIndex (§3.27.29, §3.48.6) is >= 0 THEN + result + .provenance + .as_ref() + .and_then(|provenance| { + provenance.invocation_index.and_then(|invocation_index| { + run + .invocations + .iter() + .flatten() + .collect::>() + .get(invocation_index as usize) + // LET theInvocation be the invocation object (§3.20) that it specifies. + // IF theInvocation.ruleConfigurationOverrides (§3.20.5) is present + // AND it contains a configurationOverride object (§3.51) whose + // descriptor property (§3.51.2) specifies theDescriptor THEN + .and_then(|the_invocation| { + the_invocation + .rule_configuration_overrides + .as_ref() + .and_then(|rule_configuration_overrides| { + rule_configuration_overrides + .iter() + .find(|v| { + v.descriptor.id.as_ref() + == Some(&the_descriptor.id) + }) + .and_then(|the_override| { + the_override + .configuration + .level + .as_ref() + .and_then(|value| { + value.as_str().and_then(|level| { + sarif::ResultLevel::from_str(level) + .map_or(None, Option::from) }) - }) - }) - }) - }) - }) - .or_else(|| { - // # There is no configuration override for level. Is there a default configuration for it? - // IF theDescriptor.defaultConfiguration.level (§3.49.14, §, §3.50.3) is present THEN - // SET level to theDescriptor.defaultConfiguration.level. - the_descriptor.default_configuration.as_ref().and_then( - |default_configuration| { - default_configuration.level.as_ref().and_then(|value| { - value.as_str().and_then(|level| { - sarif::ResultLevel::from_str(level) - .map_or(None, Option::from) + }) + }) }) - }) - }, - ) + }) }) - }) - }) - }), - }, - // If kind (§3.27.9) has any value other than "fail", then if level is absent, it SHALL default to "none", and if it is present, it SHALL have the value "none". - _ => Some(sarif::ResultLevel::None), - }) - // IF level has not yet been set THEN - // SET level to "warning". - .unwrap_or(sarif::ResultLevel::Warning) + }) + .or_else(|| { + // # There is no configuration override for level. Is there a default configuration for it? + // IF theDescriptor.defaultConfiguration.level (§3.49.14, §, §3.50.3) is present THEN + // SET level to theDescriptor.defaultConfiguration.level. + the_descriptor.default_configuration.as_ref().and_then( + |default_configuration| { + default_configuration.level.as_ref().and_then(|value| { + value.as_str().and_then(|level| { + sarif::ResultLevel::from_str(level) + .map_or(None, Option::from) + }) + }) + }, + ) + }) + }) + }) + }), + }, + // If kind (§3.27.9) has any value other than "fail", then if level is absent, it SHALL default to "none", and if it is present, it SHALL have the value "none". + _ => Some(sarif::ResultLevel::None), + } + // IF level has not yet been set THEN + // SET level to "warning". + .unwrap_or(sarif::ResultLevel::Warning) } // IF theMessage.text is present and the desired language is theRun.language THEN diff --git a/serde-sarif/src/converters/clang_tidy.rs b/serde-sarif/src/converters/clang_tidy.rs index b23bc3a5..d3a6276c 100644 --- a/serde-sarif/src/converters/clang_tidy.rs +++ b/serde-sarif/src/converters/clang_tidy.rs @@ -5,6 +5,7 @@ use serde::{Deserialize, Serialize}; use std::convert::TryFrom; use std::convert::TryInto; use std::io::{BufRead, Write}; +use std::str::FromStr; use typed_builder::TypedBuilder; #[derive(Clone, PartialEq, Debug, Deserialize, Serialize, TypedBuilder)] @@ -139,7 +140,7 @@ fn process(reader: R) -> Result { let builder = sarif::Result::builder() .message(&message) .locations(vec![location]) - .level(result.level); + .level(sarif::ResultLevel::from_str(&result.level)?); let result = if !related_locations.is_empty() { builder.related_locations(related_locations).build() } else { diff --git a/serde-sarif/src/converters/clippy.rs b/serde-sarif/src/converters/clippy.rs index 1d4bb4a8..1246ac78 100644 --- a/serde-sarif/src/converters/clippy.rs +++ b/serde-sarif/src/converters/clippy.rs @@ -148,7 +148,7 @@ fn process(reader: R) -> Result { .rule_index(*value) .message(&diagnostic) .locations(vec![span.into()]) - .level(level.to_string()) + .level(level) .related_locations(get_related_locations(&diagnostic)?) .build(), ); diff --git a/serde-sarif/src/converters/hadolint.rs b/serde-sarif/src/converters/hadolint.rs index 3bbb2197..ea9a661c 100644 --- a/serde-sarif/src/converters/hadolint.rs +++ b/serde-sarif/src/converters/hadolint.rs @@ -112,7 +112,7 @@ fn process(mut reader: R) -> Result { .rule_index(*value) .message(&result.message) .locations(vec![result.into()]) - .level(level.to_string()) + .level(level) .build(), ); } diff --git a/serde-sarif/src/converters/shellcheck.rs b/serde-sarif/src/converters/shellcheck.rs index 9a1727d4..0089ac5b 100644 --- a/serde-sarif/src/converters/shellcheck.rs +++ b/serde-sarif/src/converters/shellcheck.rs @@ -205,7 +205,7 @@ fn process(mut reader: R, format: String) -> Result { .locations(vec![result.into()]) .related_locations(related_locations) .fixes(fixes) - .level(level.to_string()) + .level(level) .build(), ); }