use serde_json::Value;
use crate::analysis::findings::{Finding, Severity};
use crate::languages::runner::ToolOutputError;
use crate::languages::spec::ToolSpec;
use super::{expect_array, json_payload, path_or_root};
pub(super) fn parse_sqlfluff(
spec: &ToolSpec,
output: &str,
root_name: &str,
) -> Result<Vec<Finding>, ToolOutputError> {
let Some(payload) = json_payload(spec, output)? else {
return Ok(Vec::new());
};
let entries = expect_array(spec, &payload)?;
let mut findings = Vec::new();
for entry in entries {
let file_path = path_or_root(entry.get("filepath"), root_name);
for violation in entry
.get("violations")
.and_then(Value::as_array)
.into_iter()
.flatten()
{
findings.push(Finding::deterministic(
violation
.get("code")
.and_then(Value::as_str)
.map(str::to_owned)
.unwrap_or_else(|| spec.name.to_owned()),
sqlfluff_severity(violation.get("warning")),
file_path.clone(),
violation
.get("start_line_no")
.and_then(Value::as_u64)
.map(|n| n as u32)
.unwrap_or(1),
violation
.get("start_line_pos")
.and_then(Value::as_u64)
.map(|n| n as u32),
violation
.get("description")
.and_then(Value::as_str)
.unwrap_or("")
.to_owned(),
None,
));
}
}
Ok(findings)
}
fn sqlfluff_severity(warning: Option<&Value>) -> Severity {
match warning {
Some(Value::Bool(true)) => Severity::Warning,
_ => Severity::Error,
}
}