Skip to main content

tycode_core/analyzer/
mod.rs

1pub mod get_type_docs;
2pub mod rust_analyzer;
3pub mod search_types;
4
5use std::path::PathBuf;
6use std::sync::Arc;
7
8use anyhow::Result;
9use async_trait::async_trait;
10use tokio::sync::Mutex;
11
12use crate::file::resolver::Resolver;
13use crate::module::ContextComponent;
14use crate::module::PromptComponent;
15use crate::module::{Module, SessionStateComponent};
16use crate::tools::r#trait::ToolExecutor;
17
18use get_type_docs::GetTypeDocsTool;
19use search_types::SearchTypesTool;
20
21#[derive(Debug, Clone)]
22pub struct BuildStatus {
23    pub errors: Vec<String>,
24    pub warnings: Vec<String>,
25}
26
27#[async_trait]
28pub trait TypeAnalyzer: Send {
29    async fn search_types_by_name(&mut self, type_name: &str) -> Result<Vec<String>>;
30    async fn get_type_docs(&mut self, type_path: &str) -> Result<String>;
31    async fn get_build_status(&mut self) -> Result<BuildStatus>;
32}
33
34#[derive(Clone)]
35pub struct SharedTypeAnalyzer {
36    inner: Arc<Mutex<Box<dyn TypeAnalyzer>>>,
37}
38
39impl SharedTypeAnalyzer {
40    pub fn new(analyzer: Box<dyn TypeAnalyzer>) -> Self {
41        Self {
42            inner: Arc::new(Mutex::new(analyzer)),
43        }
44    }
45
46    pub async fn search_types_by_name(&self, type_name: &str) -> anyhow::Result<Vec<String>> {
47        let mut analyzer = self.inner.lock().await;
48        analyzer.search_types_by_name(type_name).await
49    }
50
51    pub async fn get_type_docs(&self, type_path: &str) -> anyhow::Result<String> {
52        let mut analyzer = self.inner.lock().await;
53        analyzer.get_type_docs(type_path).await
54    }
55
56    pub async fn get_build_status(&self) -> anyhow::Result<BuildStatus> {
57        let mut analyzer = self.inner.lock().await;
58        analyzer.get_build_status().await
59    }
60}
61
62/// Supported languages for type analysis
63#[derive(Debug, Clone, Copy, PartialEq, Eq)]
64pub enum SupportedLanguage {
65    Rust,
66}
67
68impl SupportedLanguage {
69    pub fn from_str(s: &str) -> Option<Self> {
70        match s.to_lowercase().as_str() {
71            "rust" => Some(Self::Rust),
72            _ => None,
73        }
74    }
75
76    pub fn all() -> &'static [&'static str] {
77        &["rust"]
78    }
79}
80
81pub struct AnalyzerModule {
82    resolver: Resolver,
83}
84
85impl AnalyzerModule {
86    pub fn new(workspace_roots: Vec<PathBuf>) -> Result<Self> {
87        let resolver = Resolver::new(workspace_roots)?;
88        Ok(Self { resolver })
89    }
90}
91
92impl Module for AnalyzerModule {
93    fn prompt_components(&self) -> Vec<Arc<dyn PromptComponent>> {
94        Vec::new()
95    }
96
97    fn context_components(&self) -> Vec<Arc<dyn ContextComponent>> {
98        Vec::new()
99    }
100
101    fn tools(&self) -> Vec<Arc<dyn ToolExecutor>> {
102        vec![
103            Arc::new(SearchTypesTool::new(self.resolver.clone())),
104            Arc::new(GetTypeDocsTool::new(self.resolver.clone())),
105        ]
106    }
107
108    fn session_state(&self) -> Option<Arc<dyn SessionStateComponent>> {
109        None
110    }
111}