Skip to main content

corpora_rules/
positional.rs

1//! Flags brittle positional `§` references in normative records. The corpus favours stable
2//! ids over section numbers, which drift whenever a document is reorganised.
3
4use corpora_core::{Authority, Diagnostic, Graph};
5
6use crate::Rule;
7
8pub struct PositionalRef;
9
10impl Rule for PositionalRef {
11    fn code(&self) -> &'static str {
12        "POSITIONAL"
13    }
14
15    fn check(&self, g: &Graph, out: &mut Vec<Diagnostic>) {
16        for r in g.records().filter(|r| r.authority == Authority::Normative) {
17            for s in &r.body.section_refs {
18                out.push(Diagnostic::warn(
19                    "POSITIONAL",
20                    &r.path,
21                    format!("positional reference §{s} is brittle; prefer a stable id"),
22                ));
23            }
24        }
25    }
26}
27
28#[cfg(test)]
29mod tests {
30    use super::*;
31    use corpora_core::*;
32    use std::sync::Arc;
33
34    #[test]
35    fn warns_on_section_ref_in_normative_record() {
36        let mut r = Record::minimal(
37            Some(Id("A1".into())),
38            DocPath("a.md".into()),
39            Kind::Architecture,
40            Lifecycle::Current,
41            Authority::Normative,
42            Facet::Canon { implementation: None, code_revision: None },
43        );
44        r.body.section_refs = vec!["9.6".into()];
45        let g = Graph::build(vec![Arc::new(r)]).0;
46        let mut out = Vec::new();
47        PositionalRef.check(&g, &mut out);
48        assert_eq!(out.len(), 1);
49        assert_eq!(out[0].code, "POSITIONAL");
50    }
51}