corpora_rules/
positional.rs1use 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}