Skip to main content

bynk_project/
diagnostics.rs

1use std::path::PathBuf;
2
3use bynk_syntax::error::CompileError;
4
5/// v0.24 (ADR 0052): a compile error attributed — where possible — to the
6/// project-relative source file it belongs to, tagged at the collection
7/// point (the phase that produced it knows which file it was processing).
8/// `None` is the project-level bucket: validations spanning files
9/// (group/cycle/directory consistency) with no single owning file.
10///
11/// P4.0 (#1113): moved here from `bynk-emit`'s `project::diagnostics` — the
12/// one item of that module with no `Mode`/`ErrorSink`-shaped driving logic
13/// behind it, just a plain attributed-diagnostic value type. `Mode`,
14/// `ErrorSink`, `ProjectAnalysis`, `ProjectFailure`, `ContextSequenceInfo`,
15/// and `ContextBoundaryInfo` all stay in `bynk-emit` (each is a fact about
16/// how the pipeline is driven or consumed, not about the project model).
17pub struct AttributedError {
18    pub source_path: Option<PathBuf>,
19    pub error: CompileError,
20    /// The file each of `error.labels` points into, index for index. A
21    /// secondary label may lie in a sibling file — a duplicate's "previously
22    /// declared here" in another file of the same multi-file unit — and its
23    /// span is an offset into *that* file's text, not `source_path`'s. Filled
24    /// in when the sink is drained, from the `FileId` each label's span
25    /// carries. Shorter than `error.labels` (empty, for an error built outside
26    /// the sink) means [`LabelFile::Primary`] for the rest; read it through
27    /// [`Self::label_file`].
28    pub label_files: Vec<LabelFile>,
29}
30
31/// Which file an [`AttributedError`]'s secondary label lies in.
32#[derive(Debug, Clone, PartialEq, Eq)]
33pub enum LabelFile {
34    /// The same file as the error itself — `source_path`'s text. Also what a
35    /// label whose span carries no file identity (`FileId::UNKNOWN`) means.
36    Primary,
37    /// Another project file, by identity path — `snapshots`' key for its text.
38    Other(PathBuf),
39    /// A toolchain-injected first-party unit (#1956): its synthetic identity
40    /// path (`bynk.bynk`) and its source text, which is not a project file and
41    /// so is never in `snapshots`. A renderer that can show it draws the label
42    /// against `source`; one that can't (the LSP, with no document to point
43    /// at) makes it a note. Never drawn against the primary file's text.
44    FirstParty {
45        identity_path: &'static str,
46        source: &'static str,
47    },
48    /// A file with no text to show it against. Rendered as a note, never
49    /// against the primary file's text.
50    Unavailable,
51}
52
53impl AttributedError {
54    /// `error`, attributed to `source_path`, every label in that same file.
55    pub fn new(source_path: Option<PathBuf>, error: CompileError) -> Self {
56        Self {
57            source_path,
58            error,
59            label_files: Vec::new(),
60        }
61    }
62
63    /// The file `error.labels[index]` lies in.
64    pub fn label_file(&self, index: usize) -> &LabelFile {
65        self.label_files.get(index).unwrap_or(&LabelFile::Primary)
66    }
67}