Update mcp_codebase.py
This commit is contained in:
+137
-136
@@ -2096,83 +2096,117 @@ def build_indexes():
|
||||
block_type = m.get("block_type", "")
|
||||
component_name = m.get("component_name")
|
||||
|
||||
# Skip empty/invalid nodes
|
||||
if not name or node_type == "unknown":
|
||||
continue
|
||||
|
||||
# Ensure file node exists
|
||||
file_node_id = f"file::{fpath}"
|
||||
graph.add_node(file_node_id, type="File", path=fpath, lang=lang)
|
||||
|
||||
# Create node ID with language
|
||||
node_id = f"{lang}::{node_type}::{fpath}::{name}"
|
||||
|
||||
# Base attributes for all nodes
|
||||
base_attrs = {
|
||||
"name": name,
|
||||
"file": fpath,
|
||||
"line": m.get("line"),
|
||||
"lang": lang # Always include language
|
||||
}
|
||||
|
||||
# Create appropriate node based on type
|
||||
if node_type in ["function", "method", "constructor"]:
|
||||
# Function-like entities
|
||||
if node_type == "method" and "class" in m:
|
||||
# Method belongs to a class
|
||||
# Method belongs to a class - use compound ID
|
||||
node_id = f"{lang}::{node_type}::{fpath}::{m['class']}.{name}"
|
||||
graph.add_node(node_id, type=node_type, name=name, file=fpath,
|
||||
class_name=m.get("class"), line=m.get("line"),
|
||||
return_type=m.get("return_type"), parameters=m.get("parameters", []))
|
||||
graph.add_node(node_id, **base_attrs, type=node_type,
|
||||
class_name=m.get("class"),
|
||||
return_type=m.get("return_type"),
|
||||
parameters=m.get("parameters", []))
|
||||
|
||||
# Connect method to its class
|
||||
class_node_id = f"{lang}::class::{fpath}::{m['class']}"
|
||||
graph.add_edge(class_node_id, node_id, "contains")
|
||||
|
||||
# Connect return type if available
|
||||
return_type = m.get("return_type")
|
||||
if return_type and return_type != "void":
|
||||
# Try to find return type class/interface
|
||||
for type_id, type_data in graph.find_nodes(name=return_type):
|
||||
graph.add_edge(node_id, type_id, "returns")
|
||||
else:
|
||||
# Regular function
|
||||
node_id = f"{lang}::{node_type}::{fpath}::{name}"
|
||||
graph.add_node(node_id, type=node_type, name=name, file=fpath, line=m.get("line"),
|
||||
return_type=m.get("return_type"), parameters=m.get("parameters", []))
|
||||
graph.add_node(node_id, **base_attrs, type=node_type,
|
||||
return_type=m.get("return_type"),
|
||||
parameters=m.get("parameters", []))
|
||||
graph.add_edge(file_node_id, node_id, "contains")
|
||||
|
||||
elif node_type in ["class", "struct", "interface", "enum"]:
|
||||
# Type definitions
|
||||
node_id = f"{lang}::{node_type}::{fpath}::{name}"
|
||||
graph.add_node(node_id, type=node_type, name=name, file=fpath, line=m.get("line"),
|
||||
extends=m.get("extends"), implements=m.get("implements", []))
|
||||
graph.add_node(node_id, **base_attrs, type=node_type,
|
||||
extends=m.get("extends"),
|
||||
implements=m.get("implements", []),
|
||||
fields=m.get("fields", []), # Store fields as metadata, not separate nodes
|
||||
variants=m.get("variants", [])) # For enums
|
||||
|
||||
graph.add_edge(file_node_id, node_id, "contains")
|
||||
|
||||
# Inheritance relationships
|
||||
extends_class = m.get("extends")
|
||||
if extends_class:
|
||||
# Try to find the parent class node
|
||||
for parent_id, parent_data in graph.find_nodes(type="class", name=extends_class):
|
||||
for parent_id, parent_data in graph.find_nodes(name=extends_class):
|
||||
graph.add_edge(node_id, parent_id, "extends")
|
||||
|
||||
# Interface implementation
|
||||
implements_interfaces = m.get("implements", [])
|
||||
for interface_name in implements_interfaces:
|
||||
for interface_id, interface_data in graph.find_nodes(type="interface", name=interface_name):
|
||||
for interface_id, interface_data in graph.find_nodes(name=interface_name):
|
||||
graph.add_edge(node_id, interface_id, "implements")
|
||||
|
||||
elif node_type == "field":
|
||||
# Class/struct fields
|
||||
node_id = f"{lang}::field::{fpath}::{name}"
|
||||
graph.add_node(node_id, type=node_type, name=name, file=fpath, line=m.get("line"),
|
||||
field_type=m.get("field_type"))
|
||||
# If we have class context, connect to class
|
||||
if "class" in m:
|
||||
class_node_id = f"{lang}::class::{fpath}::{m['class']}"
|
||||
graph.add_edge(class_node_id, node_id, "contains")
|
||||
else:
|
||||
# Bevy-specific: Plugin implementation detection
|
||||
if node_type == "struct" and name.endswith("Plugin"):
|
||||
graph.add_node(node_id, **base_attrs, type=node_type, is_bevy_plugin=True)
|
||||
|
||||
elif node_type == "impl":
|
||||
# Implementation blocks
|
||||
target = m.get("target", "unknown")
|
||||
node_id = f"{lang}::{node_type}::{fpath}::{target}"
|
||||
|
||||
graph.add_node(node_id, **base_attrs, type=node_type,
|
||||
target=target,
|
||||
traits=m.get("traits", []),
|
||||
methods=m.get("methods", []))
|
||||
|
||||
graph.add_edge(file_node_id, node_id, "contains")
|
||||
|
||||
field_type = m.get("field_type")
|
||||
if field_type and field_type != "unknown":
|
||||
# Try to find the field type class
|
||||
for type_id, type_data in graph.find_nodes(name=field_type):
|
||||
graph.add_edge(node_id, type_id, "type_reference")
|
||||
# Connect to target type
|
||||
for target_id, target_data in graph.find_nodes(name=target):
|
||||
graph.add_edge(node_id, target_id, "implements_for")
|
||||
|
||||
elif node_type in ["style", "markup", "code_block"]:
|
||||
# Code blocks and stylistic elements
|
||||
block_type = m.get("block_type", node_type)
|
||||
node_id = f"{lang}::{block_type}::{fpath}::{name}"
|
||||
graph.add_node(node_id, type=node_type, name=name, file=fpath,
|
||||
line=m.get("line"), block_type=block_type)
|
||||
# Connect to implemented traits
|
||||
for trait_name in m.get("traits", []):
|
||||
for trait_id, trait_data in graph.find_nodes(name=trait_name):
|
||||
graph.add_edge(node_id, trait_id, "implements")
|
||||
|
||||
# Bevy-specific: Plugin detection
|
||||
if target.endswith("Plugin"):
|
||||
graph.add_node(node_id, **base_attrs, type=node_type, is_bevy_plugin_impl=True)
|
||||
|
||||
elif node_type == "trait":
|
||||
# Traits
|
||||
graph.add_node(node_id, **base_attrs, type=node_type,
|
||||
methods=m.get("methods", []))
|
||||
graph.add_edge(file_node_id, node_id, "contains")
|
||||
|
||||
elif node_type == "module":
|
||||
# Modules
|
||||
graph.add_node(node_id, **base_attrs, type=node_type)
|
||||
graph.add_edge(file_node_id, node_id, "contains")
|
||||
|
||||
else:
|
||||
# Generic code element fallback
|
||||
node_id = f"{lang}::{node_type}::{fpath}::{name}"
|
||||
graph.add_node(node_id, type=node_type, name=name, file=fpath, line=m.get("line"))
|
||||
graph.add_node(node_id, **base_attrs, type=node_type)
|
||||
graph.add_edge(file_node_id, node_id, "contains")
|
||||
|
||||
# Handle imports if present
|
||||
@@ -2183,115 +2217,82 @@ def build_indexes():
|
||||
for call in m.get("calls", []):
|
||||
graph.add_edge(node_id, call, "calls")
|
||||
|
||||
# Go-specific relationships
|
||||
if lang == "go":
|
||||
if node_type == "method":
|
||||
# Connect method to its receiver type
|
||||
receiver_type = m.get("receiver_base_type")
|
||||
if receiver_type:
|
||||
# Try to find the receiver type (struct/interface)
|
||||
for type_id, type_data in graph.find_nodes(type="struct", name=receiver_type):
|
||||
graph.add_edge(type_id, node_id, "has_method")
|
||||
for type_id, type_data in graph.find_nodes(type="interface", name=receiver_type):
|
||||
graph.add_edge(type_id, node_id, "has_method")
|
||||
|
||||
elif node_type == "struct":
|
||||
# Connect struct to its fields (if we had field type info)
|
||||
fields = m.get("fields", [])
|
||||
# Could potentially connect fields to their types if we extract field types
|
||||
|
||||
elif node_type == "interface":
|
||||
# Connect interface to its required methods
|
||||
interface_methods = m.get("interface_methods", [])
|
||||
# This helps identify what types implement this interface
|
||||
|
||||
elif lang == "svelte" and component_name:
|
||||
# Create component node if it doesn't exist
|
||||
component_node_id = f"svelte::component::{fpath}::{component_name}"
|
||||
if component_node_id not in graph.graph:
|
||||
graph.add_node(component_node_id, type="component", name=component_name,
|
||||
file=fpath, language="svelte")
|
||||
graph.add_edge(file_node_id, component_node_id, "contains")
|
||||
|
||||
# Connect different parts to the component
|
||||
if node_type in ["script", "script_module", "style", "markup"]:
|
||||
graph.add_edge(component_node_id, node_id, "contains")
|
||||
|
||||
# Component props and interface
|
||||
if node_type == "prop":
|
||||
graph.add_edge(component_node_id, node_id, "has_prop")
|
||||
|
||||
# Component usage relationships
|
||||
if node_type == "markup":
|
||||
used_components = m.get("used_components", [])
|
||||
for used_comp in used_components:
|
||||
# Try to find the used component in the graph
|
||||
for comp_id, comp_data in graph.find_nodes(type="component", name=used_comp):
|
||||
graph.add_edge(component_node_id, comp_id, "uses_component")
|
||||
|
||||
# Event handler relationships
|
||||
event_handlers = m.get("event_handlers", [])
|
||||
for event in event_handlers:
|
||||
graph.add_edge(component_node_id, f"event::{event}", "handles_event")
|
||||
|
||||
# Svelte script relationships (TypeScript)
|
||||
elif lang == "typescript" and block_type in ["script", "script_module"]:
|
||||
# Connect TypeScript declarations to their Svelte component
|
||||
if component_name:
|
||||
component_node_id = f"svelte::component::{fpath}::{component_name}"
|
||||
graph.add_edge(component_node_id, node_id, "contains")
|
||||
|
||||
# Import relationships
|
||||
for imp in m.get("imports", []):
|
||||
# Try to resolve imports to other components/files
|
||||
if imp.endswith('.svelte'):
|
||||
imported_component = Path(imp).stem
|
||||
if imported_component[0].islower():
|
||||
imported_component = imported_component[0].upper() + imported_component[1:]
|
||||
# Look for the imported component
|
||||
for comp_id, comp_data in graph.find_nodes(type="component", name=imported_component):
|
||||
graph.add_edge(node_id, comp_id, "imports")
|
||||
elif lang == "rust":
|
||||
# Rust-specific relationships
|
||||
if lang == "rust":
|
||||
if node_type == "struct":
|
||||
# Connect struct to its fields
|
||||
# Connect struct fields as metadata, not separate nodes
|
||||
fields = m.get("fields", [])
|
||||
for field in fields:
|
||||
graph.add_edge(node_id, f"rust::field::{fpath}::{name}.{field}", "has_field")
|
||||
# Store field info as node attribute instead of creating separate nodes
|
||||
if "field_types" not in graph.nodes[node_id]:
|
||||
graph.nodes[node_id]["field_types"] = []
|
||||
graph.nodes[node_id]["field_types"].append(field)
|
||||
|
||||
elif node_type == "enum":
|
||||
# Connect enum to its variants
|
||||
# Connect enum variants as metadata
|
||||
variants = m.get("variants", [])
|
||||
for variant in variants:
|
||||
graph.add_edge(node_id, f"rust::variant::{fpath}::{name}::{variant}", "has_variant")
|
||||
|
||||
elif node_type == "trait":
|
||||
# Connect trait to its required methods
|
||||
methods = m.get("methods", [])
|
||||
for method in methods:
|
||||
graph.add_edge(node_id, f"rust::trait_method::{name}::{method}", "requires_method")
|
||||
|
||||
elif node_type == "impl":
|
||||
# Connect impl block to its target type
|
||||
target = m.get("target")
|
||||
if target:
|
||||
# Try to find the target struct/enum
|
||||
for target_id, target_data in graph.find_nodes(name=target):
|
||||
graph.add_edge(node_id, target_id, "implements_for")
|
||||
|
||||
# Connect impl block to implemented traits
|
||||
traits = m.get("traits", [])
|
||||
for trait_name in traits:
|
||||
for trait_id, trait_data in graph.find_nodes(type="trait", name=trait_name):
|
||||
graph.add_edge(node_id, trait_id, "implements")
|
||||
if "variants" not in graph.nodes[node_id]:
|
||||
graph.nodes[node_id]["variants"] = []
|
||||
graph.nodes[node_id]["variants"].append(variant)
|
||||
|
||||
elif node_type == "function":
|
||||
# Connect function to its return type
|
||||
return_type = m.get("return_type")
|
||||
if return_type:
|
||||
# Try to find return type in graph
|
||||
for type_id, type_data in graph.find_nodes(name=return_type):
|
||||
graph.add_edge(node_id, type_id, "returns")
|
||||
# Connect function parameters to their types
|
||||
parameters = m.get("parameters", [])
|
||||
for param in parameters:
|
||||
# Extract type from "Type param_name" format
|
||||
param_parts = param.split()
|
||||
if len(param_parts) >= 2:
|
||||
param_type = param_parts[0]
|
||||
if param_type not in ['self', '&self', '&mut self', 'mut']:
|
||||
for type_id, type_data in graph.find_nodes(name=param_type):
|
||||
graph.add_edge(node_id, type_id, "uses_parameter")
|
||||
|
||||
# Bevy-specific relationship detection
|
||||
if lang == "rust" and node_type == "function":
|
||||
# Detect Bevy system functions
|
||||
function_name = name.lower()
|
||||
if any(keyword in function_name for keyword in ['system', 'plugin', 'build', 'update']):
|
||||
graph.nodes[node_id]["is_bevy_system"] = True
|
||||
|
||||
# Detect query parameters for system dependencies
|
||||
parameters = m.get("parameters", [])
|
||||
for param in parameters:
|
||||
if 'Query' in param:
|
||||
graph.nodes[node_id]["has_bevy_query"] = True
|
||||
if 'Res<' in param or 'ResMut<' in param:
|
||||
graph.nodes[node_id]["has_bevy_resource"] = True
|
||||
if 'Commands' in param:
|
||||
graph.nodes[node_id]["has_bevy_commands"] = True
|
||||
|
||||
# Second pass for Bevy-specific relationships
|
||||
bevy_connections = 0
|
||||
|
||||
for node_id, node_data in graph.graph.nodes(data=True):
|
||||
if node_data.get('lang') == 'rust':
|
||||
# Connect Plugin impls to their build functions
|
||||
if node_data.get('type') == 'impl' and node_data.get('is_bevy_plugin_impl'):
|
||||
plugin_struct = node_data.get('target')
|
||||
if plugin_struct:
|
||||
# Find the build method in this impl
|
||||
for method_id, method_data in graph.find_nodes(type="method", class_name=plugin_struct):
|
||||
if method_data.get('name') == 'build':
|
||||
graph.add_edge(node_id, method_id, "defines_plugin")
|
||||
bevy_connections += 1
|
||||
|
||||
# Connect systems to their plugins
|
||||
elif node_data.get('is_bevy_system'):
|
||||
# Try to find which plugin this system belongs to
|
||||
file_path = node_data.get('file', '')
|
||||
if file_path:
|
||||
# Look for plugins in the same file
|
||||
for plugin_id, plugin_data in graph.find_nodes(type="struct", file=file_path):
|
||||
if plugin_data.get('name', '').endswith('Plugin'):
|
||||
graph.add_edge(plugin_id, node_id, "contains_system")
|
||||
bevy_connections += 1
|
||||
|
||||
if bevy_connections > 0:
|
||||
logger.info(f"Added {bevy_connections} Bevy-specific relationships")
|
||||
logger.info("Building method parameter type relationships...")
|
||||
param_connections = 0
|
||||
for node_id, node_data in graph.graph.nodes(data=True):
|
||||
|
||||
Reference in New Issue
Block a user