varar_core/diagnostics.rs
1//! Diagnostics produced by the planner — port of the subset of `diagnostics.ts`
2//! that `Plan` needs / `Diagnostics.java`.
3
4use crate::span::Span;
5
6/// Diagnostic severity. Only `Error` is constructed today.
7#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8pub enum Severity {
9 Error,
10 Warning,
11 Info,
12}
13
14/// The closed set of diagnostic codes the planner produces. `Ord` follows the
15/// Java enum's declaration order (ordinal), matching its sort semantics.
16#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
17pub enum DiagnosticCode {
18 AmbiguousMatch,
19 ErrorFenceWithoutStep,
20 Drift,
21 /// Reference blocks (ADR 0016): a link that resolves to no oath, to a
22 /// section with no steps, to a chain that reaches itself, or to an anchor
23 /// that names more than one heading.
24 ReferenceNotFound,
25 ReferenceEmpty,
26 ReferenceCycle,
27 AmbiguousAnchor,
28}
29
30/// One diagnostic: its code, severity, and the source span it points at.
31#[derive(Clone, Copy, Debug, PartialEq, Eq)]
32pub struct Diagnostic {
33 pub code: DiagnosticCode,
34 pub severity: Severity,
35 pub span: Span,
36}
37
38/// Builds an `ambiguous-match` diagnostic pointing at `span`.
39pub fn ambiguous_match(span: Span) -> Diagnostic {
40 Diagnostic {
41 code: DiagnosticCode::AmbiguousMatch,
42 severity: Severity::Error,
43 span,
44 }
45}
46
47/// Builds an `error-fence-without-step` diagnostic pointing at `span`.
48pub fn error_fence_without_step(span: Span) -> Diagnostic {
49 Diagnostic {
50 code: DiagnosticCode::ErrorFenceWithoutStep,
51 severity: Severity::Error,
52 span,
53 }
54}
55
56/// A reference block (ADR 0016) points at an oath the workspace does not hold.
57/// Never prose: a link-only block that resolves to nothing has no other
58/// reading, so it fails the run rather than degrading silently.
59pub fn reference_not_found(span: Span) -> Diagnostic {
60 Diagnostic {
61 code: DiagnosticCode::ReferenceNotFound,
62 severity: Severity::Error,
63 span,
64 }
65}
66
67/// The referenced document exists but the section contributes no steps — a
68/// mistyped anchor, or a section that is pure prose.
69pub fn reference_empty(span: Span) -> Diagnostic {
70 Diagnostic {
71 code: DiagnosticCode::ReferenceEmpty,
72 severity: Severity::Error,
73 span,
74 }
75}
76
77/// References nest to any depth, so a chain that reaches a section already on
78/// it is reported rather than recursed into.
79pub fn reference_cycle(span: Span) -> Diagnostic {
80 Diagnostic {
81 code: DiagnosticCode::ReferenceCycle,
82 severity: Severity::Error,
83 span,
84 }
85}
86
87/// The anchor names more than one heading in the target document (two headings
88/// slugify identically), so the reference could mean either section. Reported
89/// rather than guessed: rename the headings so each has an anchor of its own.
90pub fn ambiguous_anchor(span: Span) -> Diagnostic {
91 Diagnostic {
92 code: DiagnosticCode::AmbiguousAnchor,
93 severity: Severity::Error,
94 span,
95 }
96}