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}