import and call nodes fix

This commit is contained in:
2025-11-14 17:26:06 +00:00
parent c66118a457
commit 4b7aff9062
+52 -37
View File
@@ -1628,11 +1628,15 @@ def parse_rust_file_cached(filepath_str: str, file_hash: str) -> tuple:
except Exception as e:
logger.warning(f"Rust AST helper failed for {filepath}: {e}; falling back to regex")
# Fallback: Regex-based Rust parsing
logger.info(f" Falling back to regex parsing for {filepath}")
regex_chunks = _parse_rust_with_regex(filepath, code, lines)
chunks.extend(regex_chunks)
logger.info(f" Regex found {len(regex_chunks)} chunks")
# --- Import extraction --------------------------------------------
import_re = re.compile(r'^\s*use\s+([^;]+);', re.MULTILINE)
# Fallback: Regex-based Rust parsing
logger.info(f" Falling back to regex parsing for {filepath}")
regex_chunks = _parse_rust_with_regex(filepath, code, lines, import_re)
chunks.extend(regex_chunks)
logger.info(f" Regex found {len(regex_chunks)} chunks")
except Exception as e:
logger.warning(f"parse_rust_file failed {filepath}: {e}")
@@ -1641,13 +1645,13 @@ def parse_rust_file_cached(filepath_str: str, file_hash: str) -> tuple:
logger.info(f"📦 Final result: {len(final_result)} chunks with metadata")
return final_result
def _parse_rust_with_regex(filepath: Path, code: str, lines: list) -> list:
def _parse_rust_with_regex(filepath: Path, code: str, lines: list, import_re) -> list:
"""Fallback regex-based Rust parser."""
chunks = []
# Pattern for Rust functions (including async, unsafe, methods)
func_pattern = re.compile(
r'^(?:pub\s+)?(?:async\s+)?(?:unsafe\s+)?fn\s+(\w+)\s*[<(]',
r'^(?:pub\\s+)?(?:async\\s+)?(?:unsafe\\s+)?fn\\s+(\\w+)\\s*[\u003c(]',
re.MULTILINE
)
@@ -1683,15 +1687,20 @@ def _parse_rust_with_regex(filepath: Path, code: str, lines: list) -> list:
# Parse functions
for match in func_pattern.finditer(code):
func_name = match.group(1)
start_pos = match.start()
start_line = code[:start_pos].count('\n')
start_line = code[:start_pos].count('\\n')
end_line = _find_rust_brace_block_end(lines, start_line)
func_code = "".join(lines[start_line:end_line + 1])
# Enhanced function analysis
is_async = 'async' in match.group(0)
is_unsafe = 'unsafe' in match.group(0)
# Extract function name
func_name = match.group(1)
# Extract visibility (pub or private)
visibility = "pub" if "pub" in func_code else "private"
# Detect async/unsafe
is_async = "async" in func_code
is_unsafe = "unsafe" in func_code
is_pub = 'pub' in match.group(0)
chunk_text = f"File: {filepath}\nType: function\nName: {func_name}\n"
@@ -2263,8 +2272,17 @@ def build_indexes():
graph.add_edge(file_node_id, node_id, "contains")
# ---------- IMPORTS ----------
for imp in m.get("imports", []):
# Find an existing module node with this name.
# The imports metadata might be a list or a comma-separated string
# We need to handle both cases
imports_raw = m.get("imports", [])
if isinstance(imports_raw, str):
# Split the string back into a list
imports = [imp.strip() for imp in imports_raw.split(",") if imp.strip()]
else:
imports = imports_raw
for imp in imports:
# Try to find an existing node for this import
candidate_id = None
for node_id, data in created_nodes.items():
if data.get("type") in {"module", "import"} and data.get("name") == imp:
@@ -2272,14 +2290,10 @@ def build_indexes():
break
if not candidate_id:
# If nothing exists, fall back to a generic import node.
# No existing node found - create a placeholder
candidate_id = f"import::{imp}"
# ---- Import node --------------------------------------------
# For imports we want a node that mirrors the target module if
# it exists; otherwise we still create a stub with language &
# file attributes for consistency.
if candidate_id not in graph.graph.nodes:
# First try to find a module node with that name
# Double-check for a module node with this name
found = False
for n_id, n_data in created_nodes.items():
if n_data.get("name") == imp and n_data.get("type") == "module":
@@ -2287,8 +2301,7 @@ def build_indexes():
found = True
break
if not found:
# Generic import stub
candidate_id = f"import::{imp}"
# Create a generic import node
graph.add_node(
candidate_id,
type="Import",
@@ -2296,13 +2309,20 @@ def build_indexes():
lang="unknown",
file="",
)
graph.add_edge(file_node_id, candidate_id, "imports")
graph.add_edge(file_node_id, candidate_id, "imports")
# Create the connection
graph.add_edge(file_node_id, candidate_id, "imports")
# ---------- FUNCTION CALLS ----------
for call in m.get("calls", []):
# Try to find a function/method node with this name.
calls_raw = m.get("calls", [])
if isinstance(calls_raw, str):
# Split the string back into a list
calls = [c.strip() for c in calls_raw.split(",") if c.strip()]
else:
calls = calls_raw
for call in calls:
# Try to find the function/method being called
target_id = None
for node_id, data in created_nodes.items():
if data.get("type") in {"function", "method", "constructor"} and data.get("name") == call:
@@ -2310,14 +2330,10 @@ def build_indexes():
break
if not target_id:
# Fallback to a generic call node.
# No existing function found - create a placeholder
target_id = f"call::{call}"
# ---- Call node ---------------------------------------------
# If we already know the target node (by name), reuse it. Otherwise
# create a generic node that still carries language & file context
# so it can be displayed or filtered later.
if target_id not in graph.graph.nodes:
# Attempt a besteffort lookup for the actual function node
# Double-check for a matching function
found = False
for n_id, n_data in created_nodes.items():
if (
@@ -2328,8 +2344,7 @@ def build_indexes():
found = True
break
if not found:
# Fallback to a generic FunctionCall node
target_id = f"call::{call}"
# Create a generic function call node
graph.add_node(
target_id,
type="FunctionCall",
@@ -2337,8 +2352,8 @@ def build_indexes():
lang="unknown",
file="",
)
graph.add_edge(node_id, target_id, "calls")
graph.add_edge(node_id, target_id, "calls")
# Create the connection
graph.add_edge(node_id, target_id, "calls")
@@ -2517,7 +2532,7 @@ def _connect_impl_relationships(graph, node_id, node_data):
def build_bevy_relationships(graph, created_nodes):
"""Build Bevy-specific relationships"""
connections = 0
# Extract return type = 0
# Find all plugin structs and impls
plugin_structs = {}