Skip to main content

atomcode_core/graph/
resolve.rs

1use std::path::Path;
2
3use super::{CodeGraph, SymbolId};
4
5/// Resolve a callee name to the best-matching SymbolId.
6/// Priority:
7/// 1. Same file (private helper in same file) — score 4
8/// 2. Imported name (appears in caller's import list) — score 3
9/// 3. Same directory — score 2
10/// 4. Same top-level crate/package — score 1
11/// 5. Any match — score 0
12pub fn resolve_callee(
13    graph: &CodeGraph,
14    callee_name: &str,
15    caller_file: &Path,
16    imported_names: &[String],
17) -> Option<SymbolId> {
18    let candidates = graph.find_by_name(callee_name);
19    if candidates.is_empty() {
20        return None;
21    }
22
23    let caller_dir = caller_file.parent();
24    let caller_root = top_component(caller_file);
25
26    let mut best_id: Option<SymbolId> = None;
27    let mut best_score: i32 = -1;
28
29    for node in &candidates {
30        let score = if node.file == caller_file {
31            4
32        } else if imported_names.contains(&node.name) {
33            3
34        } else if caller_dir.is_some() && node.file.parent() == caller_dir {
35            2
36        } else if caller_root.is_some() && top_component(&node.file) == caller_root {
37            1
38        } else {
39            0
40        };
41
42        if score > best_score {
43            best_score = score;
44            best_id = Some(node.id);
45        }
46    }
47
48    best_id
49}
50
51fn top_component(path: &Path) -> Option<String> {
52    path.components()
53        .next()
54        .map(|c| c.as_os_str().to_string_lossy().to_string())
55}