brokk-bifrost-ruby 0.9.5

Ruby language knowledge for brokk-bifrost: declarations, require/autoload and Zeitwerk visibility, mixin and dispatch-mode facts, and usage-graph resolution
Documentation
use crate::syntax::ruby_semantic_identifier_range;
use brokk_bifrost_core::analyzer::model::Range;
use brokk_bifrost_core::analyzer::usages::common::{
    SNIPPET_CONTEXT_LINES, reclassify_self_receiver_hit_at, usage_hit,
};
use brokk_bifrost_core::analyzer::usages::model::UsageHit;
use brokk_bifrost_core::analyzer::{CodeUnit, CodeUnitIndex, ProjectFile};
use brokk_bifrost_core::text_utils::{find_line_index_for_offset, trimmed_snippet_around_line};
use std::collections::BTreeSet;
use tree_sitter::Node;

pub fn record_usage_hit(
    index: &dyn CodeUnitIndex,
    file: &ProjectFile,
    source: &str,
    line_starts: &[usize],
    hits: &mut BTreeSet<UsageHit>,
    node: Node<'_>,
) {
    let range = ruby_semantic_identifier_range(node, source);
    let start_byte = range.start_byte;
    let end_byte = range.end_byte;
    if start_byte >= end_byte {
        return;
    }
    let line_idx = find_line_index_for_offset(line_starts, start_byte);
    let snippet = trimmed_snippet_around_line(source, line_starts, line_idx, SNIPPET_CONTEXT_LINES);
    let enclosing_range = Range {
        start_byte,
        end_byte,
        start_line: line_idx,
        end_line: line_idx,
    };
    let enclosing = index
        .enclosing_code_unit(file, &enclosing_range)
        .unwrap_or_else(|| CodeUnit::file_scope(file.clone()));
    hits.insert(usage_hit(
        file, line_idx, start_byte, end_byte, enclosing, snippet,
    ));
}

/// Record `node` as a same-owner self receiver hit (#1014 facet B): a `self.`
/// or implicit-self method reference on 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 (semantic range, enclosing, self-definition guard) lives
/// in exactly one place.
pub fn record_self_receiver_usage_hit(
    index: &dyn CodeUnitIndex,
    file: &ProjectFile,
    source: &str,
    line_starts: &[usize],
    hits: &mut BTreeSet<UsageHit>,
    node: Node<'_>,
) {
    record_usage_hit(index, file, source, line_starts, hits, node);
    let range = ruby_semantic_identifier_range(node, source);
    reclassify_self_receiver_hit_at(hits, file, range.start_byte, range.end_byte);
}

pub fn record_unproven_usage_hit(
    index: &dyn CodeUnitIndex,
    file: &ProjectFile,
    source: &str,
    line_starts: &[usize],
    hits: &mut BTreeSet<UsageHit>,
    node: Node<'_>,
) {
    let range = ruby_semantic_identifier_range(node, source);
    let start_byte = range.start_byte;
    let end_byte = range.end_byte;
    if start_byte >= end_byte {
        return;
    }
    let line_idx = find_line_index_for_offset(line_starts, start_byte);
    let snippet = trimmed_snippet_around_line(source, line_starts, line_idx, SNIPPET_CONTEXT_LINES);
    let enclosing_range = Range {
        start_byte,
        end_byte,
        start_line: line_idx,
        end_line: line_idx,
    };
    let enclosing = index
        .enclosing_code_unit(file, &enclosing_range)
        .unwrap_or_else(|| CodeUnit::file_scope(file.clone()));
    hits.insert(
        usage_hit(file, line_idx, start_byte, end_byte, enclosing, snippet).into_unproven(),
    );
}