feat: project symbol extraction integration test

- extract_project_symbols against tempdir with Rust/TypeScript/Python
  sources — walk_directory, detect_language, hidden/vendor dir skipping,
  ProjectSymbol field population, docstring extraction
This commit is contained in:
2026-03-24 17:24:39 +00:00
parent 2a87be9167
commit ecf0ead7c7

View File

@@ -5884,6 +5884,96 @@ mod research_extended_tests {
assert_eq!(total_calls, 3);
}
#[test]
fn test_extract_project_symbols_from_sol_src() {
// Point at Sol's own src/context.rs — small, known content
use crate::code_index::symbols;
let dir = tempfile::TempDir::new().unwrap();
let src = dir.path().join("src");
std::fs::create_dir_all(&src).unwrap();
// Write a small Rust file
std::fs::write(src.join("lib.rs"), r#"
/// A greeting function.
pub fn hello(name: &str) -> String {
format!("Hello, {name}!")
}
/// A simple struct.
pub struct Config {
pub name: String,
pub port: u16,
}
impl Config {
pub fn new() -> Self {
Self { name: "test".into(), port: 8080 }
}
}
"#).unwrap();
// Write a TypeScript file
std::fs::write(src.join("app.ts"), r#"
/** Main application entry point. */
export function main(): void {
console.log("hello");
}
/** User interface. */
export interface User {
name: string;
email: string;
}
"#).unwrap();
// Write a Python file
std::fs::write(src.join("util.py"), r#"
"""Utility functions."""
def add(a: int, b: int) -> int:
"""Add two numbers."""
return a + b
class Calculator:
"""A simple calculator."""
def multiply(self, a: int, b: int) -> int:
return a * b
"#).unwrap();
// Also write a file that should be skipped (hidden dir, node_modules)
let hidden = dir.path().join(".hidden");
std::fs::create_dir_all(&hidden).unwrap();
std::fs::write(hidden.join("secret.rs"), "pub fn secret() {}").unwrap();
let nm = dir.path().join("node_modules");
std::fs::create_dir_all(&nm).unwrap();
std::fs::write(nm.join("dep.ts"), "export function dep() {}").unwrap();
let symbols = symbols::extract_project_symbols(dir.path().to_str().unwrap());
// Should find symbols from all 3 source files
let names: Vec<&str> = symbols.iter().map(|s| s.name.as_str()).collect();
assert!(names.contains(&"hello"), "Should find Rust function 'hello'");
assert!(names.contains(&"Config"), "Should find Rust struct 'Config'");
assert!(names.contains(&"main"), "Should find TS function 'main'");
assert!(names.contains(&"add"), "Should find Python function 'add'");
assert!(names.contains(&"Calculator"), "Should find Python class 'Calculator'");
// Should NOT find hidden/vendor files
assert!(!names.contains(&"secret"), "Should skip hidden directory");
assert!(!names.contains(&"dep"), "Should skip node_modules");
// Verify ProjectSymbol fields
let hello = symbols.iter().find(|s| s.name == "hello").unwrap();
assert_eq!(hello.language, "rust");
assert_eq!(hello.kind, "function");
assert!(hello.signature.contains("pub fn hello"));
assert!(hello.docstring.contains("greeting"));
assert!(hello.file_path.contains("lib.rs"));
assert!(!hello.content.is_empty());
}
#[tokio::test]
async fn test_research_execute_single_task() {
let env_path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join(".env");