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(
65        &self,
66        context: &CompletionContext,
67    ) -> Arc<Vec<CompletionSuggestion>> {
68        let cache_key = format!("{}:{}:{}", context.language, context.line, context.column);
69
70        {
71            let cache = self.suggestion_cache.read().await;
72            if let Some(cached) = cache.get(&cache_key) {
73                return Arc::clone(cached);
74            }
75        }
76
77        // Generate new suggestions
78        let mut suggestions = Vec::new();
79        let keywords = self.get_language_keywords(&context.language);
80        for keyword in keywords {
81            if keyword.starts_with(&context.prefix) {
82                suggestions.push(CompletionSuggestion {
83                    text: keyword.to_string(),
84                    kind: CompletionKind::Keyword,
85                    confidence: 0.8,
86                    context: context.clone(),
87                    metadata: HashMap::new(),
88                    acceptance_rate: 0.0,
89                    learning_data: CompletionLearningData::default(),
90                    accepted_count: 0,
91                    rejected_count: 0,
92                });
93            }
94        }
95
96        let snippets = self.get_language_snippets(&context.language);
97        for snippet in snippets {
98            if snippet.label.starts_with(&context.prefix) {
99                suggestions.push(CompletionSuggestion {
100                    text: snippet.template,
101                    kind: CompletionKind::Snippet,
102                    confidence: 0.7,
103                    context: context.clone(),
104                    metadata: HashMap::from([
105                        ("label".to_owned(), snippet.label),
106                        ("description".to_owned(), snippet.description),
107                    ]),
108                    acceptance_rate: 0.0,
109                    learning_data: CompletionLearningData::default(),
110                    accepted_count: 0,
111                    rejected_count: 0,
112                });
113            }
114        }
115
116        // Insert into cache as Arc
117        let arc = Arc::new(suggestions);
118        {
119            let mut cache = self.suggestion_cache.write().await;
120            cache.insert(cache_key, Arc::clone(&arc));
121        }
122
123        arc
124    }
125
126    /// Record user feedback on a suggestion
127    pub async fn record_feedback(&self, suggestion_id: &str, accepted: bool) {
128        let mut learning_data = self.learning_data.write().await;
129
130        // Update acceptance statistics
131        let current_rate = learning_data
132            .pattern_acceptance
133            .get(suggestion_id)
134            .copied()
135            .unwrap_or(0.0);
136        let new_rate = if accepted {
137            (current_rate + 1.0) / 2.0
138        } else {
139            current_rate * 0.9
140        };
141        learning_data
142            .pattern_acceptance
143            .insert(suggestion_id.to_string(), new_rate);
144
145        // Update performance stats
146        let mut stats = self.performance_stats.write().await;
147        stats.total_requests += 1;
148        if accepted {
149            stats.acceptance_rate = (stats.acceptance_rate * (stats.total_requests - 1) as f64
150                + 1.0)
151                / stats.total_requests as f64;
152        }
153    }
154
155    /// Get language-specific keywords
156    fn get_language_keywords(&self, language: &str) -> Vec<&'static str> {
157        match language {
158            "rust" => vec![
159                "fn", "let", "mut", "const", "static", "struct", "enum", "impl", "trait", "mod",
160                "use", "pub", "crate", "super", "self", "Self", "async", "await", "move", "if",
161                "else", "match", "loop", "while", "for", "in", "break", "continue", "return", "as",
162                "dyn", "where", "unsafe",
163            ],
164            "python" => vec![
165                "def", "class", "if", "elif", "else", "for", "while", "try", "except", "finally",
166                "with", "as", "import", "from", "return", "yield", "lambda", "and", "or", "not",
167                "in", "is", "None", "True", "False", "self", "super",
168            ],
169            "javascript" => vec![
170                "function",
171                "const",
172                "let",
173                "var",
174                "if",
175                "else",
176                "for",
177                "while",
178                "try",
179                "catch",
180                "finally",
181                "return",
182                "async",
183                "await",
184                "class",
185                "extends",
186                "import",
187                "export",
188                "from",
189                "as",
190                "this",
191                "super",
192                "new",
193                "typeof",
194                "instanceof",
195            ],
196            _ => vec![],
197        }
198    }
199
200    /// Get language-specific snippets
201    fn get_language_snippets(&self, language: &str) -> Vec<CodeSnippet> {
202        match language {
203            "rust" => vec![
204                CodeSnippet {
205                    label: "fn".to_string(),
206                    template: "fn ${1:name}(${2:params}) -> ${3:ReturnType} {\n\t${0:// body}\n}".to_string(),
207                    description: "Function declaration".to_string(),
208                },
209                CodeSnippet {
210                    label: "impl".to_string(),
211                    template: "impl ${1:Trait} for ${2:Type} {\n\t${0:// implementation}\n}".to_string(),
212                    description: "Implementation block".to_string(),
213                },
214            ],
215            "python" => vec![
216                CodeSnippet {
217                    label: "def".to_string(),
218                    template: "def ${1:name}(${2:params}):\n\t${0:# body}".to_string(),
219                    description: "Function definition".to_string(),
220                },
221                CodeSnippet {
222                    label: "class".to_string(),
223                    template: "class ${1:Name}:\n\tdef __init__(self${2:params}):\n\t\t${0:# initialization}".to_string(),
224                    description: "Class definition".to_string(),
225                },
226            ],
227            "javascript" => vec![
228                CodeSnippet {
229                    label: "func".to_string(),
230                    template: "function ${1:name}(${2:params}) {\n\t${0:// body}\n}".to_string(),
231                    description: "Function declaration".to_string(),
232                },
233                CodeSnippet {
234                    label: "class".to_string(),
235                    template: "class ${1:Name} {\n\tconstructor(${2:params}) {\n\t\t${0:// initialization}\n\t}\n}".to_string(),
236                    description: "Class declaration".to_string(),
237                },
238            ],
239            _ => vec![],
240        }
241    }
242}
243
244impl Default for CompletionEngine {
245    fn default() -> Self {
246        Self::new()
247    }
248}
249
250/// Code snippet template
251#[derive(Debug, Clone)]
252pub struct CodeSnippet {
253    pub label: String,
254    pub template: String,
255    pub description: String,
256}