refactor: consolidate nvim crates, extract server library, and update workspace dependencies

This commit is contained in:
Riz Ashraf committed 2026-10-04 01:42:59 +01:00
1 parent a083719cf1
commit 533adfd41b
53 files changed
+5967 -1230

No files matched your search

+148
View File
@@ -247,6 +247,154 @@ impl McpTool for ReplaceAstNodeHandler {
}
}
pub struct FindSymbolReferencesHandler;
#[async_trait]
impl McpTool for FindSymbolReferencesHandler {
fn name(&self) -> &'static str {
"find_symbol_references"
}
fn schema(&self) -> Value {
crate::mcp::tool_def::<crate::tools::FindSymbolReferencesTool>(
"find_symbol_references",
"Find all source locations and AST chunks where a specific symbol is referenced or called.",
)
}
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
let req: crate::tools::FindSymbolReferencesTool =
serde_json::from_value(args).map_err(|e| e.to_string())?;
let limit = req.limit.unwrap_or(10);
let target_sym = req.symbol;
let matches = state.code.snippets.read_with(|snippets| {
let mut refs = Vec::new();
for snippet in snippets {
if snippet.code.contains(&target_sym) || snippet.name.contains(&target_sym) {
refs.push(snippet.clone());
if refs.len() >= limit {
break;
}
}
}
Ok::<String, crate::error::AppError>(serde_json::to_string(&refs)?)
})?;
Ok(matches)
}
}
pub struct GetCallersHandler;
#[async_trait]
impl McpTool for GetCallersHandler {
fn name(&self) -> &'static str {
"get_callers"
}
fn schema(&self) -> Value {
crate::mcp::tool_def::<crate::tools::GetCallersTool>(
"get_callers",
"Find all caller functions or methods that invoke a specified target function name.",
)
}
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
let req: crate::tools::GetCallersTool =
serde_json::from_value(args).map_err(|e| e.to_string())?;
let limit = req.limit.unwrap_or(10);
let target_fn = req.function_name;
let callers = state.code.snippets.read_with(|snippets| {
let mut matching = Vec::new();
for snippet in snippets {
if snippet.code.contains(&format!("{}(", target_fn))
|| snippet.code.contains(&format!("{}.await", target_fn))
{
matching.push(snippet.clone());
if matching.len() >= limit {
break;
}
}
}
Ok::<String, crate::error::AppError>(serde_json::to_string(&matching)?)
})?;
Ok(callers)
}
}
pub struct AnalyzeImpactHandler;
#[async_trait]
impl McpTool for AnalyzeImpactHandler {
fn name(&self) -> &'static str {
"analyze_impact"
}
fn schema(&self) -> Value {
crate::mcp::tool_def::<crate::tools::AnalyzeImpactTool>(
"analyze_impact",
"Analyze the potential downstream breaking impact of modifying a function, struct, or file.",
)
}
async fn execute(&self, args: Value, state: Arc<MemoryState>) -> crate::error::Result<String> {
let req: crate::tools::AnalyzeImpactTool =
serde_json::from_value(args).map_err(|e| e.to_string())?;
let sym = req.target_symbol.clone();
let mut callers = Vec::new();
state.code.snippets.read_with(|snippets| {
for snippet in snippets {
if snippet.code.contains(&sym) {
callers.push(snippet.name.clone());
}
}
});
let mut kg_connected = Vec::new();
state.read_graph(|g| {
for rel in &g.relations {
if rel.from == sym {
kg_connected.push(format!("Outgoing: {} -> {}", rel.relation_type, rel.to));
} else if rel.to == sym {
kg_connected.push(format!("Incoming: {} <- {}", rel.relation_type, rel.from));
}
}
});
let caller_count = callers.len();
let graph_count = kg_connected.len();
let risk_level = if caller_count > 10 || graph_count > 5 {
"CRITICAL"
} else if caller_count > 3 || graph_count > 2 {
"HIGH"
} else if caller_count > 0 || graph_count > 0 {
"MEDIUM"
} else {
"LOW"
};
let result = serde_json::json!({
"target_symbol": sym,
"risk_level": risk_level,
"ast_callers_count": caller_count,
"ast_callers_sample": callers.into_iter().take(5).collect::<Vec<_>>(),
"graph_relations_count": graph_count,
"graph_relations": kg_connected,
"recommendation": match risk_level {
"CRITICAL" | "HIGH" => "Requires comprehensive unit test verification and backwards compatibility checks before modifying.",
"MEDIUM" => "Verify direct call sites and run affected module tests.",
_ => "Safe to modify with standard unit test verification.",
}
});
Ok(serde_json::to_string_pretty(&result)?)
}
}
#[cfg(test)]
mod tests {
use super::*;