Skip to main content
Glama

CodeGraph CLI MCP Server

by Jakedismo
mod.rs7.3 kB
use crate::AstToGraphConverter; use codegraph_core::{EdgeType, Language, NodeType}; use tree_sitter::Parser; // Additional test modules can be added here as needed #[cfg(test)] mod integration_tests { use super::*; use tree_sitter_python; use tree_sitter_rust; use tree_sitter_typescript; #[test] fn test_full_rust_conversion() { let rust_code = r#" use std::collections::HashMap; pub struct Config { name: String, values: HashMap<String, i32>, } impl Config { pub fn new(name: String) -> Self { Self { name, values: HashMap::new(), } } pub fn add_value(&mut self, key: String, value: i32) { self.values.insert(key, value); } pub fn get_value(&self, key: &str) -> Option<&i32> { self.values.get(key) } } pub fn create_config(name: &str) -> Config { Config::new(name.to_string()) } pub fn process_config(mut config: Config) -> HashMap<String, i32> { config.add_value("default".to_string(), 42); config.values } "#; let mut parser = Parser::new(); let language = unsafe { tree_sitter::Language::from_raw(tree_sitter_rust::LANGUAGE.into_raw()() as *const _) }; parser.set_language(&language).unwrap(); if let Some(tree) = parser.parse(rust_code, None) { let mut converter = AstToGraphConverter::new( Language::Rust, "test.rs".to_string(), rust_code.to_string(), ); converter.convert(tree.root_node()).unwrap(); let nodes = converter.get_nodes(); let edges = converter.get_edges(); // Verify we extracted the correct entities assert!(nodes.iter().any(|n| &*n.name == "Config")); assert!(nodes.iter().any(|n| &*n.name == "new")); assert!(nodes.iter().any(|n| &*n.name == "add_value")); assert!(nodes.iter().any(|n| &*n.name == "get_value")); assert!(nodes.iter().any(|n| &*n.name == "create_config")); assert!(nodes.iter().any(|n| &*n.name == "process_config")); // Verify we have relationships assert!(!edges.is_empty()); // Verify relationship types assert!(edges.iter().any(|e| matches!(e.edge_type, EdgeType::Calls))); assert!(edges.iter().any(|e| matches!(e.edge_type, EdgeType::Uses))); println!("Extracted {} nodes and {} edges", nodes.len(), edges.len()); for node in &nodes { println!("Node: {} ({:?})", node.name, node.node_type); } for edge in &edges { println!( "Edge: {:?} -> {:?} ({:?})", edge.from, edge.to, edge.edge_type ); } } } #[test] fn test_typescript_conversion() { let ts_code = r#" import { Component } from 'react'; interface UserProps { name: string; age: number; } class User extends Component<UserProps> { constructor(props: UserProps) { super(props); } getName(): string { return this.props.name; } getAge(): number { return this.props.age; } } function createUser(name: string, age: number): User { return new User({ name, age }); } export default User; "#; let mut parser = Parser::new(); let language = unsafe { tree_sitter::Language::from_raw( tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into_raw()() as *const _, ) }; parser.set_language(&language).unwrap(); if let Some(tree) = parser.parse(ts_code, None) { let mut converter = AstToGraphConverter::new( Language::TypeScript, "User.tsx".to_string(), ts_code.to_string(), ); converter.convert(tree.root_node()).unwrap(); let nodes = converter.get_nodes(); let edges = converter.get_edges(); // Verify TypeScript-specific entities assert!(nodes.iter().any( |n| &*n.name == "UserProps" && matches!(n.node_type, Some(NodeType::Interface)) )); assert!(nodes .iter() .any(|n| &*n.name == "User" && matches!(n.node_type, Some(NodeType::Class)))); assert!(nodes.iter().any( |n| &*n.name == "createUser" && matches!(n.node_type, Some(NodeType::Function)) )); // Verify inheritance relationship assert!(edges .iter() .any(|e| matches!(e.edge_type, EdgeType::Extends))); println!( "TypeScript: Extracted {} nodes and {} edges", nodes.len(), edges.len() ); } } #[test] fn test_python_conversion() { let py_code = r#" import json from typing import Dict, List, Optional class DataProcessor: def __init__(self, name: str): self.name = name self.data: Dict[str, List[int]] = {} def add_data(self, key: str, values: List[int]) -> None: self.data[key] = values def get_data(self, key: str) -> Optional[List[int]]: return self.data.get(key) def process_all(self) -> Dict[str, int]: result = {} for key, values in self.data.items(): result[key] = sum(values) return result def create_processor(name: str) -> DataProcessor: return DataProcessor(name) def save_to_file(processor: DataProcessor, filename: str) -> None: data = processor.process_all() with open(filename, 'w') as f: json.dump(data, f) "#; let mut parser = Parser::new(); let language = unsafe { tree_sitter::Language::from_raw(tree_sitter_python::LANGUAGE.into_raw()() as *const _) }; parser.set_language(&language).unwrap(); if let Some(tree) = parser.parse(py_code, None) { let mut converter = AstToGraphConverter::new( Language::Python, "processor.py".to_string(), py_code.to_string(), ); converter.convert(tree.root_node()).unwrap(); let nodes = converter.get_nodes(); let edges = converter.get_edges(); // Verify Python-specific entities assert!(nodes.iter().any( |n| &*n.name == "DataProcessor" && matches!(n.node_type, Some(NodeType::Class)) )); assert!(nodes.iter().any(|n| &*n.name == "create_processor" && matches!(n.node_type, Some(NodeType::Function)))); assert!(nodes .iter() .any(|n| &*n.name == "save_to_file" && matches!(n.node_type, Some(NodeType::Function)))); // Verify usage of imported entities assert!(edges.iter().any(|e| matches!(e.edge_type, EdgeType::Uses) || matches!(e.edge_type, EdgeType::References))); println!( "Python: Extracted {} nodes and {} edges", nodes.len(), edges.len() ); } } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Jakedismo/codegraph-rust'

If you have feedback or need assistance with the MCP directory API, please join our Discord server