src/knowledge/scip.rs
//! RESOLVED knowledge map — the SCIP ROW MODEL and its id helpers.
//!
//! The `rust-analyzer scip` subprocess ingest that used to live here (spawn,
//! `index.scip` protobuf decode, retry/deadline/stderr digest) was removed with
//! Mímir v2 (PLAN-MIMIR-V2 §7.3a); the rustc-driver dump replaces it (lane 3).
//! What stays is the id scheme: the [`ScipRow`] / [`ScipScan`] PODs (lifted into
//! the edda `nornir-warehouse-trait` leaf and re-exported here) and the pure
//! def-site-key classifier.
// The RESOLVED-knowledge PODs live in the edda `nornir-warehouse-trait` leaf so
// the `Warehouse::load_latest_scip` trait surface can name them without pulling
// nornir. Re-exported so every `crate::knowledge::scip::{ScipScan, ScipRow}` call
// site is untouched.
pub use nornir_warehouse_trait::{ScipRow, ScipScan};
/// Is `symbol` a DEF-SITE KEY (`<workspace-relative file>#Lline:Ccol`, the id the
/// removed in-process rust-analyzer road synthesized) rather than a real,
/// globally-unique SCIP moniker?
///
/// PURE + unit-tested, because the two vocabularies are easy to confuse by eye
/// and a def-site key must never be joined across scans. A SCIP moniker is
/// either `local N` or `<scheme> <manager> <package> <version> <descriptors>`;
/// a def-site key is `file#Lline:Ccol` from a def's navigation range. The distinguishing
/// mark is the exact `#L<digits>:C<digits>` SUFFIX — a real moniker never ends in
/// one, and neither near-miss (`#L7`, `#Lx:C4`, `#L7:C`) is claimed.
///
/// The `file` half is workspace-RELATIVE, which is precisely why the key cannot
/// cross a scan boundary: every repo in the workspace has a `src/lib.rs`.
pub fn is_def_site_key(symbol: &str) -> bool {
let Some((head, tail)) = symbol.rsplit_once("#L") else {
return false;
};
if head.is_empty() {
return false;
}
let Some((line, col)) = tail.split_once(":C") else {
return false;
};
!line.is_empty()
&& !col.is_empty()
&& line.bytes().all(|b| b.is_ascii_digit())
&& col.bytes().all(|b| b.is_ascii_digit())
}
/// Is this scan keyed by def-site keys rather than real SCIP monikers?
///
/// Read off the DEFINITION rows, which is where the identity scheme is decided;
/// an empty scan is not def-site-keyed (there is nothing to refuse). Cheap enough
/// to call per scan — it stops at the first definition.
pub fn scan_is_def_site_keyed(scan: &ScipScan) -> bool {
scan.rows
.iter()
.find(|r| r.is_definition)
.is_some_and(|r| is_def_site_key(&r.symbol))
}
#[cfg(test)]
mod tests {
use super::*;
use chrono::Utc;
use uuid::Uuid;
/// A def-site-keyed row (not a SCIP moniker).
fn def_site_row(
symbol: &str,
kind: &str,
display_name: &str,
file: &str,
line: u32,
enc: (u32, u32),
is_definition: bool,
) -> ScipRow {
ScipRow {
symbol: symbol.to_string(),
role: if is_definition { "definition" } else { "reference" }.to_string(),
is_definition,
display_name: display_name.to_string(),
kind: kind.to_string(),
file: file.to_string(),
start_line: line,
start_col: 4,
enc_start_line: enc.0,
enc_end_line: enc.1,
}
}
/// Member `alpha`, def-site keyed. `run()` is callable and spans 10..20;
/// `count` is a FIELD at `src/lib.rs#L7:C4`; line 14 inside `run()` reads it.
fn alpha_in_process_scan() -> ScipScan {
ScipScan {
snapshot_id: Uuid::nil(),
ts: Utc::now(),
repo: "alpha".into(),
git_sha: "alphasha".into(),
rows: vec![
def_site_row("src/lib.rs#L10:C4", "Function", "run", "src/lib.rs", 10, (10, 20), true),
def_site_row("src/lib.rs#L7:C4", "Field", "count", "src/lib.rs", 7, (0, 0), true),
// The read of `self.count` at line 14 — `refs_in_file` gives it the
// FIELD's def-site key, an empty display_name and an empty kind.
def_site_row("src/lib.rs#L7:C4", "", "", "src/lib.rs", 14, (0, 0), false),
],
}
}
/// The classifier the refusal rests on, asserted on both vocabularies.
#[test]
fn def_site_key_classifier_separates_the_two_vocabularies() {
// ra_ingest def-site keys.
assert!(is_def_site_key("src/lib.rs#L7:C4"));
assert!(is_def_site_key("crates/a/src/mod.rs#L1:C1"));
assert!(is_def_site_key("a#L10:C20"));
// Real SCIP monikers (and locals) are never mistaken for one.
assert!(!is_def_site_key("rust-analyzer cargo demo_lib 0.1.0 helper()."));
assert!(!is_def_site_key("local 3"));
assert!(!is_def_site_key(""));
// Near-misses stay OUT of the def-site bucket (they are not our key shape).
assert!(!is_def_site_key("src/lib.rs#L7"));
assert!(!is_def_site_key("src/lib.rs#Lx:C4"));
assert!(!is_def_site_key("src/lib.rs#L7:C"));
}
/// A scan is classified by what its DEFINITIONS are keyed by.
#[test]
fn scan_provenance_is_read_off_the_definition_keys() {
assert!(scan_is_def_site_keyed(&alpha_in_process_scan()));
let mut lib = ScipScan::default();
lib.rows.push(ScipRow {
symbol: "rust-analyzer cargo demo_lib 0.1.0 helper().".into(),
role: "definition".into(),
is_definition: true,
display_name: "helper".into(),
kind: "Function".into(),
file: "src/lib.rs".into(),
start_line: 6,
start_col: 7,
enc_start_line: 6,
enc_end_line: 10,
});
assert!(!scan_is_def_site_keyed(&lib));
assert!(!scan_is_def_site_keyed(&ScipScan::default()));
}
}