use crate::graph::schema::SymbolNode;
use anyhow::Result;
use rusqlite::params;
use sqlitegraph::{EdgeSpec, GraphBackend};
use super::CodeGraph;
use crate::graph::query;
fn find_or_create_display_name(conn: &rusqlite::Connection, display_fqn: &str) -> Result<i64> {
let mut stmt = conn.prepare_cached(
"SELECT id FROM graph_entities
WHERE kind = 'DisplayName' AND name = ?1",
)?;
match stmt.query_row(params![display_fqn], |row| row.get(0)) {
Ok(id) => Ok(id),
Err(rusqlite::Error::QueryReturnedNoRows) => {
let data_json = serde_json::json!({});
let data_str = serde_json::to_string(&data_json)?;
conn.execute(
"INSERT INTO graph_entities (kind, name, data) VALUES (?1, ?2, ?3)",
params!["DisplayName", display_fqn, data_str],
)?;
Ok(conn.last_insert_rowid())
}
Err(e) => Err(anyhow::anyhow!("Failed to query DisplayName: {}", e)),
}
}
pub trait AmbiguityOps {
fn create_ambiguous_group(&mut self, display_fqn: &str, symbol_ids: &[i64]) -> Result<()>;
fn resolve_by_symbol_id(
&mut self,
display_fqn: &str,
preferred_symbol_id: &str,
) -> Result<Option<SymbolNode>>;
fn get_candidates(&mut self, display_fqn: &str) -> Result<Vec<(i64, SymbolNode)>>;
}
impl AmbiguityOps for CodeGraph {
fn create_ambiguous_group(&mut self, display_fqn: &str, symbol_ids: &[i64]) -> Result<()> {
let conn = self.chunks.connect()?;
let display_name_id = find_or_create_display_name(&conn, display_fqn)?;
for symbol_id in symbol_ids {
let edge_spec = EdgeSpec {
from: display_name_id,
to: *symbol_id,
edge_type: "alias_of".to_string(),
data: serde_json::json!({}),
};
self.symbols.backend.insert_edge(edge_spec)?;
}
Ok(())
}
fn resolve_by_symbol_id(
&mut self,
display_fqn: &str,
preferred_symbol_id: &str,
) -> Result<Option<SymbolNode>> {
let symbol = query::find_by_symbol_id(self, preferred_symbol_id)?;
if let Some(ref s) = symbol {
if s.display_fqn.as_deref() == Some(display_fqn) {
return Ok(symbol);
}
}
Ok(None)
}
fn get_candidates(&mut self, display_fqn: &str) -> Result<Vec<(i64, SymbolNode)>> {
query::get_ambiguous_candidates(self, display_fqn)
}
}