Skip to main content

specfold_core/audit/
plugins.rs

1//! Audit items contributed by plugins that provide `audits`.
2
3use super::types::{Item, Kind};
4use crate::corpus::Corpus;
5use crate::graph::Graph;
6use crate::plugins::{self, payload, process};
7use serde::Deserialize;
8use serde_json::json;
9
10#[derive(Deserialize)]
11struct PluginItem {
12    subject: String,
13    #[serde(default)]
14    path: String,
15    #[serde(default)]
16    line: usize,
17    detail: String,
18    next: Option<String>,
19}
20
21#[derive(Deserialize)]
22struct Response {
23    #[serde(default)]
24    items: Vec<PluginItem>,
25}
26
27pub fn run(c: &Corpus, g: &Graph, out: &mut Vec<Item>) {
28    for p in plugins::load(&c.cfg) {
29        let Ok(d) = &p.description else { continue };
30        if d.provides.audits.is_empty() {
31            continue;
32        }
33        let params =
34            json!({"audits": d.provides.audits, "docs": payload::docs(c, None), "edges": payload::edges(c, g)});
35        match process::call::<Response>(&c.cfg, &p.def, "audit.run", params) {
36            Ok(r) => out.extend(r.items.into_iter().map(|x| Item {
37                kind: Kind::Plugin,
38                subject: x.subject,
39                path: x.path,
40                line: x.line,
41                detail: format!("[{}] {}", p.def.name, x.detail),
42                next: x.next,
43            })),
44            Err(e) => out.push(Item {
45                kind: Kind::Plugin,
46                subject: p.def.name.clone(),
47                path: "spec.toml".into(),
48                line: 0,
49                detail: e.to_string(),
50                next: None,
51            }),
52        }
53    }
54}