brokk-bifrost-python 0.9.5

Python language knowledge for brokk-bifrost: module identity, declarations, imports, and usage-graph resolution
Documentation
use crate::graph::extractor::ScanCtx;
use brokk_bifrost_core::analyzer::Range;
use brokk_bifrost_core::analyzer::usages::common::{
    SNIPPET_CONTEXT_LINES, reclassify_self_receiver_hit_at, usage_hit,
};
use brokk_bifrost_core::text_utils::{find_line_index_for_offset, trimmed_snippet_around_line};
use tree_sitter::Node;

pub fn record_hit(node: Node<'_>, ctx: &mut ScanCtx<'_>) {
    if let Some(hit) = build_hit(node, ctx) {
        ctx.hits.insert(hit);
    }
}

pub fn record_unproven_hit(node: Node<'_>, ctx: &mut ScanCtx<'_>) {
    if let Some(hit) = build_hit(node, ctx) {
        ctx.unproven_hits.insert(hit.into_unproven());
    }
}

/// Record `node` as a same-owner self/cls receiver hit (#1014 facet B): a
/// `self.member` / `cls.member` access whose receiver is the current instance /
/// own class. Excluded from the external usage surface, counted as a same-owner
/// site. Records the ordinary hit, then reclassifies it — the shared scan
/// consumer, so the record ceremony lives in exactly one place.
pub fn record_self_receiver_hit(node: Node<'_>, ctx: &mut ScanCtx<'_>) {
    record_hit(node, ctx);
    reclassify_self_receiver_hit_at(ctx.hits, ctx.file, node.start_byte(), node.end_byte());
}

/// Record `node` as an `Import`-binding hit (the token that brings the symbol
/// into this file), which the IDE find-references surface includes but the
/// call-graph surfaces ignore.
pub fn record_import_hit(node: Node<'_>, ctx: &mut ScanCtx<'_>) {
    if let Some(hit) = build_hit(node, ctx) {
        ctx.hits.insert(hit.into_import());
    }
}

fn build_hit(
    node: Node<'_>,
    ctx: &mut ScanCtx<'_>,
) -> Option<brokk_bifrost_core::analyzer::usages::model::UsageHit> {
    let start_byte = node.start_byte();
    let end_byte = node.end_byte();
    if start_byte >= end_byte {
        return None;
    }

    let line_idx = find_line_index_for_offset(ctx.line_starts, start_byte);
    let snippet =
        trimmed_snippet_around_line(ctx.source, ctx.line_starts, line_idx, SNIPPET_CONTEXT_LINES);
    let range = Range {
        start_byte,
        end_byte,
        start_line: line_idx,
        end_line: line_idx,
    };

    let enclosing = ctx.graph.index.enclosing_code_unit(ctx.file, &range)?;

    Some(usage_hit(
        ctx.file, line_idx, start_byte, end_byte, enclosing, snippet,
    ))
}