import and call nodes fix
This commit is contained in:
+52
-37
@@ -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 best‑effort 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 = {}
|
||||
|
||||
Reference in New Issue
Block a user