gobby-code 1.3.3

Fast Rust CLI for Gobby's code index — AST-aware search, symbol navigation, and dependency graph
Documentation
use std::collections::HashMap;

use crate::graph::typed_query;

const CODE_EDGE_REL_TYPES: &str = "['DEFINES', 'IMPORTS', 'CALLS']";

pub(super) fn report_node_type_case(alias: &str) -> String {
    format!(
        "CASE \
          WHEN {alias}:CodeFile THEN 'file' \
          WHEN {alias}:CodeModule THEN 'module' \
          WHEN {alias}:CodeSymbol THEN coalesce({alias}.kind, 'symbol') \
          WHEN {alias}:UnresolvedCallee THEN 'unresolved' \
          WHEN {alias}:ExternalSymbol THEN 'external' \
          ELSE 'node' \
        END"
    )
}

fn report_node_id_expr(alias: &str) -> String {
    format!("coalesce({alias}.id, {alias}.path, {alias}.name)")
}

fn report_node_name_expr(alias: &str) -> String {
    format!("coalesce({alias}.name, {alias}.path, {alias}.id)")
}

pub(super) fn report_node_counts_query(project_id: &str) -> (String, HashMap<String, String>) {
    (
        format!(
            "MATCH (n {{project: $project}}) \
             WHERE n:CodeFile OR n:CodeSymbol OR n:CodeModule OR n:UnresolvedCallee OR n:ExternalSymbol \
             RETURN {} AS name, count(n) AS count",
            report_node_type_case("n")
        ),
        typed_query::string_params(&[("project", project_id)]),
    )
}

pub(super) fn report_code_edge_counts_query(project_id: &str) -> (String, HashMap<String, String>) {
    (
        format!(
            "MATCH (source {{project: $project}})-[r]->(target {{project: $project}}) \
             WHERE type(r) IN {CODE_EDGE_REL_TYPES} \
             RETURN type(r) AS name, count(r) AS count"
        ),
        typed_query::string_params(&[("project", project_id)]),
    )
}

pub(super) fn report_hotspots_query(
    project_id: &str,
    node_class: &str,
    top_n: usize,
) -> (String, HashMap<String, String>) {
    let predicate = match node_class {
        "file" => "n:CodeFile",
        "module" => "n:CodeModule",
        _ => "n:CodeSymbol",
    };
    let limit = top_n.max(1);
    (
        format!(
            "MATCH (n {{project: $project}}) \
             WHERE {predicate} \
             OPTIONAL MATCH (n)-[out]->(out_target {{project: $project}}) \
             WHERE type(out) IN {CODE_EDGE_REL_TYPES} \
               AND (out_target:CodeFile OR out_target:CodeSymbol OR out_target:CodeModule OR out_target:UnresolvedCallee OR out_target:ExternalSymbol) \
             WITH n, count(out) AS outgoing \
             OPTIONAL MATCH (in_source {{project: $project}})-[inc]->(n) \
             WHERE type(inc) IN {CODE_EDGE_REL_TYPES} \
               AND (in_source:CodeFile OR in_source:CodeSymbol OR in_source:CodeModule OR in_source:UnresolvedCallee OR in_source:ExternalSymbol) \
             WITH n, outgoing, count(inc) AS incoming \
             WITH n, outgoing, incoming, outgoing + incoming AS degree \
             WHERE degree > 0 \
             RETURN {} AS id, {} AS name, {} AS node_type, degree, incoming, outgoing, coalesce(n.file_path, n.path) AS file_path \
             ORDER BY degree DESC, name ASC, id ASC \
             LIMIT {limit}",
            report_node_id_expr("n"),
            report_node_name_expr("n"),
            report_node_type_case("n")
        ),
        typed_query::string_params(&[("project", project_id)]),
    )
}

pub(super) fn report_incoming_call_hotspots_query(
    project_id: &str,
    top_n: usize,
) -> (String, HashMap<String, String>) {
    let limit = top_n.max(1);
    (
        format!(
            "MATCH (:CodeSymbol {{project: $project}})-[r:CALLS]->(n:CodeSymbol {{project: $project}}) \
             WITH n, count(r) AS incoming \
             WHERE incoming > 0 \
             RETURN n.id AS id, coalesce(n.name, n.id) AS name, {} AS node_type, incoming AS degree, incoming, 0 AS outgoing, n.file_path AS file_path \
             ORDER BY degree DESC, name ASC, id ASC \
             LIMIT {limit}",
            report_node_type_case("n")
        ),
        typed_query::string_params(&[("project", project_id)]),
    )
}

pub(super) fn report_target_frequencies_query(
    project_id: &str,
    target_type: &str,
    top_n: usize,
) -> (String, HashMap<String, String>) {
    let target_label = if target_type == "external" {
        "ExternalSymbol"
    } else {
        "UnresolvedCallee"
    };
    let limit = top_n.max(1);
    (
        format!(
            "MATCH (:CodeSymbol {{project: $project}})-[r:CALLS]->(target:{target_label} {{project: $project}}) \
             RETURN target.id AS id, coalesce(target.name, target.id) AS name, count(r) AS count \
             ORDER BY count DESC, name ASC, id ASC \
             LIMIT {limit}"
        ),
        typed_query::string_params(&[("project", project_id)]),
    )
}

pub(super) fn report_bridge_edges_query(project_id: &str) -> (String, HashMap<String, String>) {
    (
        "MATCH (source)-[r:RELATES_TO_CODE]->(target:CodeSymbol {project: $project}) \
         RETURN coalesce(source.id, source.uuid, source.name) AS source_id, \
                target.id AS target_symbol_id, \
                'RELATES_TO_CODE' AS relation, \
                r.provenance AS provenance, \
                r.confidence AS confidence, \
                coalesce(r.source_system, 'gobby-memory') AS source_system, \
                r.source_file_path AS source_file_path, \
                r.source_line AS source_line, \
                r.source_symbol_id AS source_symbol_id, \
                r.matching_method AS matching_method"
            .to_string(),
        typed_query::string_params(&[("project", project_id)]),
    )
}