Skip to main content

vtcode_core/code/code_completion/engine/
mod.rs

1pub mod ranking;
2pub mod suggestions;
3
4pub use ranking::SuggestionRanker;
5pub use suggestions::CompletionSuggestion;
6
7use crate::code::code_completion::context::CompletionContext;
8use crate::code::code_completion::learning::CompletionLearningData;
9use hashbrown::HashMap;
10use serde::{Deserialize, Serialize};
11use std::sync::Arc;
12use tokio::sync::RwLock;
13
14/// Type of completion suggestion
15#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
16pub enum CompletionKind {
17    Function,
18    Method,
19    Variable,
20    Class,
21    Struct,
22    Enum,
23    Trait,
24    Module,
25    Keyword,
26    Snippet,
27    Import,
28    Type,
29}
30
31/// Code completion engine
32pub struct CompletionEngine {
33    suggestion_cache: Arc<RwLock<HashMap<String, Arc<Vec<CompletionSuggestion>>>>>,
34    learning_data: Arc<RwLock<CompletionLearningData>>,
35    performance_stats: Arc<RwLock<CompletionStats>>,
36}
37
38/// Performance statistics for completion engine
39#[derive(Debug, Clone, Default)]
40pub struct CompletionStats {
41    pub total_requests: usize,
42    pub cache_hits: usize,
43    pub average_response_time_ms: f64,
44    pub acceptance_rate: f64,
45}
46
47impl CompletionEngine {
48    pub fn new() -> Self {
49        Self {
50            suggestion_cache: Arc::new(RwLock::new(HashMap::new())),
51            learning_data: Arc::new(RwLock::new(CompletionLearningData::default())),
52            performance_stats: Arc::new(RwLock::new(CompletionStats::default())),
53        }
54    }
55
56    /// Generate completion suggestions for the given context
57    pub async fn complete(&self, context: &CompletionContext) -> Vec<CompletionSuggestion> {
58        let arc = self.complete_shared(context).await;
59        (*arc).clone()
60    }
61
62    /// Return a shared `Arc<Vec<CompletionSuggestion>>` to avoid cloning large collections
63    /// when the caller can accept shared ownership.
64    pub async fn complete_shared(&self, context: &CompletionContext) -> Arc<Vec<CompletionSuggestion>> {
65        let cache_key = format!("{}:{}:{}", context.language, context.line, context.column);
66
67        {
68            let cache = self.suggestion_cache.read().await;
69            if let Some(cached) = cache.get(&cache_key) {
70                return Arc::clone(cached);
71            }
72        }
73
74        // Generate new suggestions
75        let mut suggestions = Vec::new();
76        let keywords = self.get_language_keywords(&context.language);
77        for keyword in keywords {
78            if keyword.starts_with(&context.prefix) {
79                suggestions.push(CompletionSuggestion {
80                    text: keyword.to_string(),
81                    kind: CompletionKind::Keyword,
82                    confidence: 0.8,
83                    context: context.clone(),
84                    metadata: HashMap::new(),
85                    acceptance_rate: 0.0,
86                    learning_data: CompletionLearningData::default(),
87                    accepted_count: 0,
88                    rejected_count: 0,
89                });
90            }
91        }
92
93        let snippets = self.get_language_snippets(&context.language);
94        for snippet in snippets {
95            if snippet.label.starts_with(&context.prefix) {
96                suggestions.push(CompletionSuggestion {
97                    text: snippet.template,
98                    kind: CompletionKind::Snippet,
99                    confidence: 0.7,
100                    context: context.clone(),
101                    metadata: HashMap::from([
102                        ("label".to_owned(), snippet.label),
103                        ("description".to_owned(), snippet.description),
104                    ]),
105                    acceptance_rate: 0.0,
106                    learning_data: CompletionLearningData::default(),
107                    accepted_count: 0,
108                    rejected_count: 0,
109                });
110            }
111        }
112
113        // Insert into cache as Arc
114        let arc = Arc::new(suggestions);
115        {
116            let mut cache = self.suggestion_cache.write().await;
117            cache.insert(cache_key, Arc::clone(&arc));
118        }
119
120        arc
121    }
122
123    /// Record user feedback on a suggestion
124    pub async fn record_feedback(&self, suggestion_id: &str, accepted: bool) {
125        let mut learning_data = self.learning_data.write().await;
126
127        // Update acceptance statistics
128        let current_rate = learning_data.pattern_acceptance.get(suggestion_id).copied().unwrap_or(0.0);
129        let new_rate = if accepted {
130            (current_rate + 1.0) / 2.0
131        } else {
132            current_rate * 0.9
133        };
134        learning_data.pattern_acceptance.insert(suggestion_id.to_string(), new_rate);
135
136        // Update performance stats
137        let mut stats = self.performance_stats.write().await;
138        stats.total_requests += 1;
139        if accepted {
140            stats.acceptance_rate =
141                (stats.acceptance_rate * (stats.total_requests - 1) as f64 + 1.0) / stats.total_requests as f64;
142        }
143    }
144
145    /// Get language-specific keywords
146    fn get_language_keywords(&self, language: &str) -> Vec<&'static str> {
147        match language {
148            "rust" => vec![
149                "fn", "let", "mut", "const", "static", "struct", "enum", "impl", "trait", "mod", "use", "pub", "crate",
150                "super", "self", "Self", "async", "await", "move", "if", "else", "match", "loop", "while", "for", "in",
151                "break", "continue", "return", "as", "dyn", "where", "unsafe",
152            ],
153            "python" => vec![
154                "def", "class", "if", "elif", "else", "for", "while", "try", "except", "finally", "with", "as",
155                "import", "from", "return", "yield", "lambda", "and", "or", "not", "in", "is", "None", "True", "False",
156                "self", "super",
157            ],
158            "javascript" => vec![
159                "function",
160                "const",
161                "let",
162                "var",
163                "if",
164                "else",
165                "for",
166                "while",
167                "try",
168                "catch",
169                "finally",
170                "return",
171                "async",
172                "await",
173                "class",
174                "extends",
175                "import",
176                "export",
177                "from",
178                "as",
179                "this",
180                "super",
181                "new",
182                "typeof",
183                "instanceof",
184            ],
185            _ => vec![],
186        }
187    }
188
189    /// Get language-specific snippets
190    fn get_language_snippets(&self, language: &str) -> Vec<CodeSnippet> {
191        match language {
192            "rust" => vec![
193                CodeSnippet {
194                    label: "fn".to_string(),
195                    template: "fn ${1:name}(${2:params}) -> ${3:ReturnType} {\n\t${0:// body}\n}".to_string(),
196                    description: "Function declaration".to_string(),
197                },
198                CodeSnippet {
199                    label: "impl".to_string(),
200                    template: "impl ${1:Trait} for ${2:Type} {\n\t${0:// implementation}\n}".to_string(),
201                    description: "Implementation block".to_string(),
202                },
203            ],
204            "python" => vec![
205                CodeSnippet {
206                    label: "def".to_string(),
207                    template: "def ${1:name}(${2:params}):\n\t${0:# body}".to_string(),
208                    description: "Function definition".to_string(),
209                },
210                CodeSnippet {
211                    label: "class".to_string(),
212                    template: "class ${1:Name}:\n\tdef __init__(self${2:params}):\n\t\t${0:# initialization}"
213                        .to_string(),
214                    description: "Class definition".to_string(),
215                },
216            ],
217            "javascript" => vec![
218                CodeSnippet {
219                    label: "func".to_string(),
220                    template: "function ${1:name}(${2:params}) {\n\t${0:// body}\n}".to_string(),
221                    description: "Function declaration".to_string(),
222                },
223                CodeSnippet {
224                    label: "class".to_string(),
225                    template: "class ${1:Name} {\n\tconstructor(${2:params}) {\n\t\t${0:// initialization}\n\t}\n}"
226                        .to_string(),
227                    description: "Class declaration".to_string(),
228                },
229            ],
230            _ => vec![],
231        }
232    }
233}
234
235impl Default for CompletionEngine {
236    fn default() -> Self {
237        Self::new()
238    }
239}
240
241/// Code snippet template
242#[derive(Debug, Clone)]
243pub struct CodeSnippet {
244    pub label: String,
245    pub template: String,
246    pub description: String,
247}