Skip to content

Diagnostics and Sources

darkstar edited this page Oct 3, 2026 · 2 revisions

Diagnostics & Sources

Source capture is its own pipeline:

SourceCache → SourceSnapshot → SourceRevision → CapturedDiagnostic

💾 Virtual and in-memory sources

Source text doesn't need to exist on disk:

let reporter = Reporter::builder()
    .application("editor")
    .source("memory://editor/main.rs", "let answer = old_value();\n")
    .build()?;

SourceCache stores virtual or generated text. Names match exactly, cached source beats filesystem fallback, and cloned handles share state:

use diagprint::SourceCache;

let cache = SourceCache::new();
cache.insert("memory://generated.rs", "fn generated() {}\n");

📸 Immutable snapshots

SourceSnapshot freezes the view at a point in time (text stays shared via Arc); later edits to the live cache don't change it:

let snapshot = reporter.source_cache().snapshot();

🔢 Source revisions

Every cached source tracks a SourceRevision. Every insertion advances it, even identical text, and history survives removal so an old revision can never be silently reused:

let revision = cache.insert_revisioned("memory://editor/main.rs", "let answer = old_value();\n");
println!("revision: {revision}");

🔗 Revision-bound diagnostics

Bind a diagnostic's locations to the revisions it was created from:

let snapshot = reporter.source_snapshot();
let diagnostic = reporter
    .error("Invalid editor value")
    .label("memory://editor/main.rs", 1, Some(14), Some(9), Some("old value"))
    .bind_source_revisions(&snapshot);

If the live source changes, revision-aware rendering fails closed instead of underlining unrelated new text:

! stale source: r1 != r2

📦 Captured diagnostics

CapturedDiagnostic pairs a diagnostic with the snapshot it belongs to:

let captured = reporter.capture(
    reporter.error("editor diagnostic")
        .label("memory://editor/main.rs", 1, Some(14), Some(9), Some("source at diagnostic time")),
);

reporter.register_source("memory://editor/main.rs", "let answer = new_value();\n");
assert!(captured.is_stale(&reporter.source_cache()));

reporter.emit_captured(&captured)?;   // still renders against the original source

Source text stays outside Diagnostic serialization.

🔌 Source providers

Integrations that own in-memory text expose it via SourceProvider:

reporter.register_sources(&provider);
// or
let reporter = Reporter::builder().sources_from(&provider).build()?;

The Ariadne and annotate-snippets bridges implement this handoff.

← 🚀 Quick Start  ·  🖨️ Rendering & Output →

🩺 diagprint

⚡ Start

🧱 Build

📤 Ship

🔧 Fix

🔬 Investigate

🛠️ Project


🌐 Site · 📖 docs.rs · 📦 crates.io

Clone this wiki locally