ricecoder_completion/
context.rs

1/// Context analysis for code completion
2///
3/// This module provides context analysis for code completion. It analyzes code context
4/// to determine available symbols, scopes, and expected types.
5///
6/// # Implementations
7///
8/// - [`GenericContextAnalyzer`]: Basic text-based context analysis
9/// - [`TreeSitterContextAnalyzer`]: Tree-sitter based scope and symbol detection
10use crate::types::*;
11use async_trait::async_trait;
12use tree_sitter::{Language, Parser};
13
14/// Context analyzer trait for analyzing code context
15///
16/// Implementations analyze code context to determine available symbols, scopes, and expected types.
17/// This information is used by the completion generator to provide relevant suggestions.
18///
19/// # Example
20///
21/// ```ignore
22/// use ricecoder_completion::context::*;
23/// use ricecoder_completion::types::*;
24///
25/// let analyzer = GenericContextAnalyzer;
26/// let context = analyzer.analyze_context(
27///     "fn main() { let x = ",
28///     Position::new(0, 20),
29///     "rust",
30/// ).await?;
31///
32/// println!("Scope: {:?}", context.scope);
33/// println!("Available symbols: {:?}", context.available_symbols);
34/// ```
35#[async_trait]
36pub trait ContextAnalyzer: Send + Sync {
37    /// Analyze the code context at the given position
38    ///
39    /// # Arguments
40    ///
41    /// * `code` - The source code to analyze
42    /// * `position` - The cursor position where context is requested
43    /// * `language` - The programming language identifier
44    ///
45    /// # Returns
46    ///
47    /// A `CompletionContext` containing scope, available symbols, and expected type information.
48    ///
49    /// # Errors
50    ///
51    /// Returns `CompletionError` if:
52    /// - The language is not supported
53    /// - Code parsing fails
54    /// - Context analysis fails
55    async fn analyze_context(
56        &self,
57        code: &str,
58        position: Position,
59        language: &str,
60    ) -> CompletionResult<CompletionContext>;
61
62    /// Get available symbols in the given context
63    ///
64    /// # Arguments
65    ///
66    /// * `context` - The completion context
67    /// * `code` - The source code
68    ///
69    /// # Returns
70    ///
71    /// A vector of symbols available in the given context.
72    fn get_available_symbols(&self, context: &CompletionContext, code: &str) -> Vec<Symbol>;
73
74    /// Infer the expected type at the given context
75    ///
76    /// # Arguments
77    ///
78    /// * `context` - The completion context
79    ///
80    /// # Returns
81    ///
82    /// The expected type at the cursor position, or `None` if it cannot be inferred.
83    fn infer_expected_type(&self, context: &CompletionContext) -> Option<Type>;
84}
85
86/// Tree-sitter based context analyzer for scope detection
87///
88/// This analyzer uses tree-sitter to parse code and detect scopes, available symbols,
89/// and expected types. It supports Rust, TypeScript, and Python.
90///
91/// # Supported Languages
92///
93/// - **Rust**: Full support with scope detection and symbol extraction
94/// - **TypeScript/JavaScript**: Full support with scope detection and symbol extraction
95/// - **Python**: Full support with scope detection and symbol extraction
96///
97/// # Example
98///
99/// ```ignore
100/// use ricecoder_completion::context::TreeSitterContextAnalyzer;
101/// use ricecoder_completion::types::Position;
102///
103/// let analyzer = TreeSitterContextAnalyzer;
104/// let context = analyzer.analyze_context(
105///     "fn main() { let x = ",
106///     Position::new(0, 20),
107///     "rust",
108/// ).await?;
109/// ```
110pub struct TreeSitterContextAnalyzer;
111
112impl TreeSitterContextAnalyzer {
113    /// Get the tree-sitter language for the given language identifier
114    fn get_language(language: &str) -> Option<Language> {
115        match language {
116            "rust" => Some(tree_sitter_rust::language()),
117            "typescript" | "ts" | "tsx" | "javascript" | "js" | "jsx" => {
118                Some(tree_sitter_typescript::language_typescript())
119            }
120            "python" | "py" => Some(tree_sitter_python::language()),
121            _ => None,
122        }
123    }
124
125    /// Get built-in symbols for a language
126    fn get_builtin_symbols(language: &str) -> Vec<Symbol> {
127        match language {
128            "rust" => vec![
129                Symbol {
130                    name: "String".to_string(),
131                    kind: SymbolKind::Type,
132                    scope: Scope {
133                        kind: ScopeKind::Global,
134                        name: None,
135                        range: Range::new(Position::new(0, 0), Position::new(0, 0)),
136                    },
137                    type_info: Some("std::string::String".to_string()),
138                    documentation: Some("A UTF-8 encoded string".to_string()),
139                },
140                Symbol {
141                    name: "Vec".to_string(),
142                    kind: SymbolKind::Type,
143                    scope: Scope {
144                        kind: ScopeKind::Global,
145                        name: None,
146                        range: Range::new(Position::new(0, 0), Position::new(0, 0)),
147                    },
148                    type_info: Some("std::vec::Vec".to_string()),
149                    documentation: Some("A growable array".to_string()),
150                },
151                Symbol {
152                    name: "Option".to_string(),
153                    kind: SymbolKind::Type,
154                    scope: Scope {
155                        kind: ScopeKind::Global,
156                        name: None,
157                        range: Range::new(Position::new(0, 0), Position::new(0, 0)),
158                    },
159                    type_info: Some("std::option::Option".to_string()),
160                    documentation: Some("An optional value".to_string()),
161                },
162                Symbol {
163                    name: "Result".to_string(),
164                    kind: SymbolKind::Type,
165                    scope: Scope {
166                        kind: ScopeKind::Global,
167                        name: None,
168                        range: Range::new(Position::new(0, 0), Position::new(0, 0)),
169                    },
170                    type_info: Some("std::result::Result".to_string()),
171                    documentation: Some("A result type for error handling".to_string()),
172                },
173            ],
174            "typescript" | "javascript" => vec![
175                Symbol {
176                    name: "Array".to_string(),
177                    kind: SymbolKind::Type,
178                    scope: Scope {
179                        kind: ScopeKind::Global,
180                        name: None,
181                        range: Range::new(Position::new(0, 0), Position::new(0, 0)),
182                    },
183                    type_info: Some("Array".to_string()),
184                    documentation: Some("A JavaScript array".to_string()),
185                },
186                Symbol {
187                    name: "Object".to_string(),
188                    kind: SymbolKind::Type,
189                    scope: Scope {
190                        kind: ScopeKind::Global,
191                        name: None,
192                        range: Range::new(Position::new(0, 0), Position::new(0, 0)),
193                    },
194                    type_info: Some("Object".to_string()),
195                    documentation: Some("A JavaScript object".to_string()),
196                },
197                Symbol {
198                    name: "Promise".to_string(),
199                    kind: SymbolKind::Type,
200                    scope: Scope {
201                        kind: ScopeKind::Global,
202                        name: None,
203                        range: Range::new(Position::new(0, 0), Position::new(0, 0)),
204                    },
205                    type_info: Some("Promise".to_string()),
206                    documentation: Some("A promise for async operations".to_string()),
207                },
208                Symbol {
209                    name: "Map".to_string(),
210                    kind: SymbolKind::Type,
211                    scope: Scope {
212                        kind: ScopeKind::Global,
213                        name: None,
214                        range: Range::new(Position::new(0, 0), Position::new(0, 0)),
215                    },
216                    type_info: Some("Map".to_string()),
217                    documentation: Some("A key-value map".to_string()),
218                },
219            ],
220            "python" => vec![
221                Symbol {
222                    name: "list".to_string(),
223                    kind: SymbolKind::Type,
224                    scope: Scope {
225                        kind: ScopeKind::Global,
226                        name: None,
227                        range: Range::new(Position::new(0, 0), Position::new(0, 0)),
228                    },
229                    type_info: Some("list".to_string()),
230                    documentation: Some("A Python list".to_string()),
231                },
232                Symbol {
233                    name: "dict".to_string(),
234                    kind: SymbolKind::Type,
235                    scope: Scope {
236                        kind: ScopeKind::Global,
237                        name: None,
238                        range: Range::new(Position::new(0, 0), Position::new(0, 0)),
239                    },
240                    type_info: Some("dict".to_string()),
241                    documentation: Some("A Python dictionary".to_string()),
242                },
243                Symbol {
244                    name: "str".to_string(),
245                    kind: SymbolKind::Type,
246                    scope: Scope {
247                        kind: ScopeKind::Global,
248                        name: None,
249                        range: Range::new(Position::new(0, 0), Position::new(0, 0)),
250                    },
251                    type_info: Some("str".to_string()),
252                    documentation: Some("A Python string".to_string()),
253                },
254                Symbol {
255                    name: "int".to_string(),
256                    kind: SymbolKind::Type,
257                    scope: Scope {
258                        kind: ScopeKind::Global,
259                        name: None,
260                        range: Range::new(Position::new(0, 0), Position::new(0, 0)),
261                    },
262                    type_info: Some("int".to_string()),
263                    documentation: Some("A Python integer".to_string()),
264                },
265            ],
266            _ => Vec::new(),
267        }
268    }
269
270    /// Collect symbols from imported modules
271    fn collect_imported_symbols(code: &str, language: &str) -> Vec<Symbol> {
272        let mut symbols = Vec::new();
273
274        match language {
275            "rust" => {
276                // Look for use statements
277                for line in code.lines() {
278                    if line.trim().starts_with("use ") {
279                        // Extract the imported item
280                        if let Some(imported) = Self::extract_rust_import(line) {
281                            symbols.push(Symbol {
282                                name: imported.clone(),
283                                kind: SymbolKind::Module,
284                                scope: Scope {
285                                    kind: ScopeKind::Global,
286                                    name: None,
287                                    range: Range::new(Position::new(0, 0), Position::new(0, 0)),
288                                },
289                                type_info: None,
290                                documentation: None,
291                            });
292                        }
293                    }
294                }
295            }
296            "typescript" | "javascript" => {
297                // Look for import statements
298                for line in code.lines() {
299                    if line.trim().starts_with("import ") {
300                        // Extract the imported items
301                        if let Some(imported) = Self::extract_typescript_import(line) {
302                            symbols.push(Symbol {
303                                name: imported.clone(),
304                                kind: SymbolKind::Module,
305                                scope: Scope {
306                                    kind: ScopeKind::Global,
307                                    name: None,
308                                    range: Range::new(Position::new(0, 0), Position::new(0, 0)),
309                                },
310                                type_info: None,
311                                documentation: None,
312                            });
313                        }
314                    }
315                }
316            }
317            "python" => {
318                // Look for import statements
319                for line in code.lines() {
320                    if line.trim().starts_with("import ") || line.trim().starts_with("from ") {
321                        // Extract the imported items
322                        if let Some(imported) = Self::extract_python_import(line) {
323                            symbols.push(Symbol {
324                                name: imported.clone(),
325                                kind: SymbolKind::Module,
326                                scope: Scope {
327                                    kind: ScopeKind::Global,
328                                    name: None,
329                                    range: Range::new(Position::new(0, 0), Position::new(0, 0)),
330                                },
331                                type_info: None,
332                                documentation: None,
333                            });
334                        }
335                    }
336                }
337            }
338            _ => {}
339        }
340
341        symbols
342    }
343
344    /// Extract Rust import name from use statement
345    fn extract_rust_import(line: &str) -> Option<String> {
346        let line = line.trim();
347        let import_part = line.strip_prefix("use ")?;
348        let import_part = import_part.trim_end_matches(';');
349
350        // Handle simple imports like "use std::vec::Vec;"
351        if let Some(last_colon) = import_part.rfind("::") {
352            let name = &import_part[last_colon + 2..];
353            if !name.is_empty() && !name.contains('{') {
354                return Some(name.to_string());
355            }
356        }
357
358        // Handle glob imports like "use std::*;"
359        if import_part.ends_with("::*") {
360            return Some("*".to_string());
361        }
362
363        // Handle simple module imports
364        if !import_part.contains("::") && !import_part.contains('{') {
365            return Some(import_part.to_string());
366        }
367
368        None
369    }
370
371    /// Extract TypeScript import name from import statement
372    fn extract_typescript_import(line: &str) -> Option<String> {
373        let line = line.trim();
374        let line = line.strip_prefix("import ")?;
375
376        // Handle "import { name } from 'module'"
377        if let Some(start) = line.find('{') {
378            if let Some(end) = line.find('}') {
379                let names = &line[start + 1..end];
380                // Get the first imported name
381                if let Some(name) = names.split(',').next() {
382                    return Some(name.trim().to_string());
383                }
384            }
385        }
386
387        // Handle "import name from 'module'"
388        if let Some(from_pos) = line.find(" from ") {
389            let import_part = &line[..from_pos];
390            return Some(import_part.trim().to_string());
391        }
392
393        None
394    }
395
396    /// Extract Python import name from import statement
397    fn extract_python_import(line: &str) -> Option<String> {
398        let line = line.trim();
399
400        if let Some(import_part) = line.strip_prefix("import ") {
401            // Handle "import module" or "import module as alias"
402            if let Some(as_pos) = import_part.find(" as ") {
403                return Some(import_part[as_pos + 4..].trim().to_string());
404            }
405            return Some(import_part.split(',').next()?.trim().to_string());
406        }
407
408        if let Some(rest) = line.strip_prefix("from ") {
409            // Handle "from module import name"
410            if let Some(import_pos) = rest.find(" import ") {
411                let import_part = &rest[import_pos + 8..];
412                // Get the first imported name
413                if let Some(name) = import_part.split(',').next() {
414                    return Some(name.trim().to_string());
415                }
416            }
417        }
418
419        None
420    }
421
422    /// Collect symbols from the current scope with full code access
423    fn collect_scope_symbols_with_code(context: &CompletionContext, code: &str) -> Vec<Symbol> {
424        let mut symbols = Vec::new();
425
426        match context.language.as_str() {
427            "rust" => {
428                symbols.extend(Self::collect_rust_scope_symbols(code, context));
429            }
430            "typescript" | "javascript" => {
431                symbols.extend(Self::collect_typescript_scope_symbols(code, context));
432            }
433            "python" => {
434                symbols.extend(Self::collect_python_scope_symbols(code, context));
435            }
436            _ => {}
437        }
438
439        symbols
440    }
441
442    /// Collect Rust scope symbols (variables, functions, types)
443    fn collect_rust_scope_symbols(code: &str, context: &CompletionContext) -> Vec<Symbol> {
444        let mut symbols = Vec::new();
445        let byte_offset = Self::position_to_byte_offset(code, context.position);
446        let code_before = &code[..byte_offset];
447
448        // Look for variable declarations: let, const, mut
449        for line in code_before.lines().rev() {
450            let trimmed = line.trim();
451
452            // Variable declaration: let x = ...
453            if trimmed.starts_with("let ") || trimmed.starts_with("let mut ") {
454                if let Some(name) = Self::extract_rust_variable_name(trimmed) {
455                    symbols.push(Symbol {
456                        name: name.clone(),
457                        kind: SymbolKind::Variable,
458                        scope: context.scope.clone(),
459                        type_info: None,
460                        documentation: None,
461                    });
462                }
463            }
464
465            // Const declaration: const X = ...
466            if trimmed.starts_with("const ") {
467                if let Some(name) = Self::extract_rust_variable_name(trimmed) {
468                    symbols.push(Symbol {
469                        name: name.clone(),
470                        kind: SymbolKind::Constant,
471                        scope: context.scope.clone(),
472                        type_info: None,
473                        documentation: None,
474                    });
475                }
476            }
477
478            // Function parameter (if in function scope)
479            if context.scope.kind == ScopeKind::Function && trimmed.starts_with("fn ") {
480                if let Some(params) = Self::extract_rust_function_params(trimmed) {
481                    for param in params {
482                        symbols.push(Symbol {
483                            name: param.clone(),
484                            kind: SymbolKind::Parameter,
485                            scope: context.scope.clone(),
486                            type_info: None,
487                            documentation: None,
488                        });
489                    }
490                }
491                break; // Stop at function definition
492            }
493        }
494
495        symbols
496    }
497
498    /// Extract Rust variable name from declaration
499    fn extract_rust_variable_name(line: &str) -> Option<String> {
500        let line = if let Some(stripped) = line.strip_prefix("let mut ") {
501            stripped
502        } else if let Some(stripped) = line.strip_prefix("let ") {
503            stripped
504        } else if let Some(stripped) = line.strip_prefix("const ") {
505            stripped
506        } else {
507            return None;
508        };
509
510        // Get the name before : or =
511        let name = if let Some(colon_pos) = line.find(':') {
512            &line[..colon_pos]
513        } else if let Some(eq_pos) = line.find('=') {
514            &line[..eq_pos]
515        } else {
516            line
517        };
518
519        let name = name.trim();
520        if !name.is_empty() && name.chars().all(|c| c.is_alphanumeric() || c == '_') {
521            Some(name.to_string())
522        } else {
523            None
524        }
525    }
526
527    /// Extract Rust function parameters
528    fn extract_rust_function_params(line: &str) -> Option<Vec<String>> {
529        if !line.starts_with("fn ") {
530            return None;
531        }
532
533        // Find the parameter list
534        if let Some(start) = line.find('(') {
535            if let Some(end) = line.find(')') {
536                let params_str = &line[start + 1..end];
537                let mut params = Vec::new();
538
539                for param in params_str.split(',') {
540                    let param = param.trim();
541                    if !param.is_empty() {
542                        // Extract name before :
543                        if let Some(colon_pos) = param.find(':') {
544                            let name = param[..colon_pos].trim();
545                            if !name.is_empty() {
546                                params.push(name.to_string());
547                            }
548                        }
549                    }
550                }
551
552                return Some(params);
553            }
554        }
555
556        None
557    }
558
559    /// Collect TypeScript scope symbols
560    fn collect_typescript_scope_symbols(code: &str, context: &CompletionContext) -> Vec<Symbol> {
561        let mut symbols = Vec::new();
562        let byte_offset = Self::position_to_byte_offset(code, context.position);
563        let code_before = &code[..byte_offset];
564
565        // Look for variable declarations: let, const, var
566        for line in code_before.lines().rev() {
567            let trimmed = line.trim();
568
569            // Variable declaration: let x = ...
570            if trimmed.starts_with("let ")
571                || trimmed.starts_with("const ")
572                || trimmed.starts_with("var ")
573            {
574                if let Some(name) = Self::extract_typescript_variable_name(trimmed) {
575                    let kind = if trimmed.starts_with("const ") {
576                        SymbolKind::Constant
577                    } else {
578                        SymbolKind::Variable
579                    };
580
581                    symbols.push(Symbol {
582                        name: name.clone(),
583                        kind,
584                        scope: context.scope.clone(),
585                        type_info: None,
586                        documentation: None,
587                    });
588                }
589            }
590
591            // Function parameter (if in function scope)
592            if context.scope.kind == ScopeKind::Function
593                && (trimmed.starts_with("function ") || trimmed.contains("=>"))
594            {
595                if let Some(params) = Self::extract_typescript_function_params(trimmed) {
596                    for param in params {
597                        symbols.push(Symbol {
598                            name: param.clone(),
599                            kind: SymbolKind::Parameter,
600                            scope: context.scope.clone(),
601                            type_info: None,
602                            documentation: None,
603                        });
604                    }
605                }
606                break; // Stop at function definition
607            }
608        }
609
610        symbols
611    }
612
613    /// Extract TypeScript variable name from declaration
614    fn extract_typescript_variable_name(line: &str) -> Option<String> {
615        let line = if let Some(stripped) = line.strip_prefix("let ") {
616            stripped
617        } else if let Some(stripped) = line.strip_prefix("const ") {
618            stripped
619        } else if let Some(stripped) = line.strip_prefix("var ") {
620            stripped
621        } else {
622            return None;
623        };
624
625        // Get the name before : or =
626        let name = if let Some(colon_pos) = line.find(':') {
627            &line[..colon_pos]
628        } else if let Some(eq_pos) = line.find('=') {
629            &line[..eq_pos]
630        } else {
631            line
632        };
633
634        let name = name.trim();
635        if !name.is_empty()
636            && name
637                .chars()
638                .all(|c| c.is_alphanumeric() || c == '_' || c == '$')
639        {
640            Some(name.to_string())
641        } else {
642            None
643        }
644    }
645
646    /// Extract TypeScript function parameters
647    fn extract_typescript_function_params(line: &str) -> Option<Vec<String>> {
648        // Find the parameter list
649        if let Some(start) = line.find('(') {
650            if let Some(end) = line.find(')') {
651                let params_str = &line[start + 1..end];
652                let mut params = Vec::new();
653
654                for param in params_str.split(',') {
655                    let param = param.trim();
656                    if !param.is_empty() {
657                        // Extract name before : or =
658                        let name = if let Some(colon_pos) = param.find(':') {
659                            &param[..colon_pos]
660                        } else if let Some(eq_pos) = param.find('=') {
661                            &param[..eq_pos]
662                        } else {
663                            param
664                        };
665
666                        let name = name.trim();
667                        if !name.is_empty() {
668                            params.push(name.to_string());
669                        }
670                    }
671                }
672
673                return Some(params);
674            }
675        }
676
677        None
678    }
679
680    /// Collect Python scope symbols
681    fn collect_python_scope_symbols(code: &str, context: &CompletionContext) -> Vec<Symbol> {
682        let mut symbols = Vec::new();
683        let byte_offset = Self::position_to_byte_offset(code, context.position);
684        let code_before = &code[..byte_offset];
685
686        // Look for variable assignments
687        for line in code_before.lines().rev() {
688            let trimmed = line.trim();
689
690            // Skip comments and empty lines
691            if trimmed.is_empty() || trimmed.starts_with('#') {
692                continue;
693            }
694
695            // Variable assignment: x = ...
696            if let Some(eq_pos) = trimmed.find('=') {
697                // Make sure it's not ==, !=, <=, >=
698                if eq_pos > 0 && eq_pos < trimmed.len() - 1 {
699                    let before = &trimmed[..eq_pos];
700                    let after = &trimmed[eq_pos + 1..eq_pos + 2];
701
702                    if after != "="
703                        && !before.ends_with('!')
704                        && !before.ends_with('<')
705                        && !before.ends_with('>')
706                    {
707                        if let Some(name) = Self::extract_python_variable_name(before) {
708                            symbols.push(Symbol {
709                                name: name.clone(),
710                                kind: SymbolKind::Variable,
711                                scope: context.scope.clone(),
712                                type_info: None,
713                                documentation: None,
714                            });
715                        }
716                    }
717                }
718            }
719
720            // Function parameter (if in function scope)
721            if context.scope.kind == ScopeKind::Function && trimmed.starts_with("def ") {
722                if let Some(params) = Self::extract_python_function_params(trimmed) {
723                    for param in params {
724                        symbols.push(Symbol {
725                            name: param.clone(),
726                            kind: SymbolKind::Parameter,
727                            scope: context.scope.clone(),
728                            type_info: None,
729                            documentation: None,
730                        });
731                    }
732                }
733                break; // Stop at function definition
734            }
735        }
736
737        symbols
738    }
739
740    /// Extract Python variable name from assignment
741    fn extract_python_variable_name(line: &str) -> Option<String> {
742        let name = line.trim();
743        if !name.is_empty() && name.chars().all(|c| c.is_alphanumeric() || c == '_') {
744            Some(name.to_string())
745        } else {
746            None
747        }
748    }
749
750    /// Extract Python function parameters
751    fn extract_python_function_params(line: &str) -> Option<Vec<String>> {
752        if !line.starts_with("def ") {
753            return None;
754        }
755
756        // Find the parameter list
757        if let Some(start) = line.find('(') {
758            if let Some(end) = line.find(')') {
759                let params_str = &line[start + 1..end];
760                let mut params = Vec::new();
761
762                for param in params_str.split(',') {
763                    let param = param.trim();
764                    if !param.is_empty() && param != "self" {
765                        // Extract name before : or =
766                        let name = if let Some(colon_pos) = param.find(':') {
767                            &param[..colon_pos]
768                        } else if let Some(eq_pos) = param.find('=') {
769                            &param[..eq_pos]
770                        } else {
771                            param
772                        };
773
774                        let name = name.trim();
775                        if !name.is_empty() {
776                            params.push(name.to_string());
777                        }
778                    }
779                }
780
781                return Some(params);
782            }
783        }
784
785        None
786    }
787
788    /// Parse code using tree-sitter
789    fn parse_code(code: &str, language: &str) -> CompletionResult<tree_sitter::Tree> {
790        let lang = Self::get_language(language).ok_or_else(|| {
791            CompletionError::UnsupportedLanguage(format!(
792                "Language {} not supported by tree-sitter",
793                language
794            ))
795        })?;
796
797        let mut parser = Parser::new();
798        parser.set_language(lang).map_err(|_| {
799            CompletionError::ContextAnalysisError("Failed to set parser language".to_string())
800        })?;
801
802        parser.parse(code, None).ok_or_else(|| {
803            CompletionError::ContextAnalysisError("Failed to parse code".to_string())
804        })
805    }
806
807    /// Detect the scope at the given position
808    fn detect_scope(
809        code: &str,
810        position: Position,
811        tree: &tree_sitter::Tree,
812        language: &str,
813    ) -> Scope {
814        let byte_offset = Self::position_to_byte_offset(code, position);
815        let root = tree.root_node();
816
817        // Find the deepest node at the position
818        let mut current_node = root;
819        let mut cursor = root.walk();
820
821        // Walk down the tree to find the deepest node at the position
822        loop {
823            let mut found_child = false;
824            for child in current_node.children(&mut cursor) {
825                if child.start_byte() <= byte_offset && byte_offset <= child.end_byte() {
826                    current_node = child;
827                    found_child = true;
828                    break;
829                }
830            }
831            if !found_child {
832                break;
833            }
834        }
835
836        // Walk up the tree to find scope-defining nodes
837        let mut scope_kind = ScopeKind::Global;
838        let mut scope_name = None;
839
840        let mut node = current_node;
841        loop {
842            let node_type = node.kind();
843
844            match language {
845                "rust" => match node_type {
846                    "function_item" => {
847                        scope_kind = ScopeKind::Function;
848                        scope_name = Self::extract_name_rust(node, code);
849                        break;
850                    }
851                    "struct_item" => {
852                        scope_kind = ScopeKind::Struct;
853                        scope_name = Self::extract_name_rust(node, code);
854                        break;
855                    }
856                    "impl_item" => {
857                        scope_kind = ScopeKind::Impl;
858                        scope_name = Self::extract_name_rust(node, code);
859                        break;
860                    }
861                    "mod_item" => {
862                        scope_kind = ScopeKind::Module;
863                        scope_name = Self::extract_name_rust(node, code);
864                        break;
865                    }
866                    "block" => {
867                        scope_kind = ScopeKind::Block;
868                    }
869                    _ => {}
870                },
871                "typescript" | "javascript" => match node_type {
872                    "function_declaration" | "function" => {
873                        scope_kind = ScopeKind::Function;
874                        scope_name = Self::extract_name_typescript(node, code);
875                        break;
876                    }
877                    "class_declaration" => {
878                        scope_kind = ScopeKind::Class;
879                        scope_name = Self::extract_name_typescript(node, code);
880                        break;
881                    }
882                    "method_definition" => {
883                        scope_kind = ScopeKind::Function;
884                        scope_name = Self::extract_name_typescript(node, code);
885                        break;
886                    }
887                    "block" => {
888                        scope_kind = ScopeKind::Block;
889                    }
890                    _ => {}
891                },
892                "python" => match node_type {
893                    "function_definition" => {
894                        scope_kind = ScopeKind::Function;
895                        scope_name = Self::extract_name_python(node, code);
896                        break;
897                    }
898                    "class_definition" => {
899                        scope_kind = ScopeKind::Class;
900                        scope_name = Self::extract_name_python(node, code);
901                        break;
902                    }
903                    "block" => {
904                        scope_kind = ScopeKind::Block;
905                    }
906                    _ => {}
907                },
908                _ => {}
909            }
910
911            if let Some(parent) = node.parent() {
912                node = parent;
913            } else {
914                break;
915            }
916        }
917
918        Scope {
919            kind: scope_kind,
920            name: scope_name,
921            range: Range::new(
922                Self::byte_offset_to_position(code, current_node.start_byte()),
923                Self::byte_offset_to_position(code, current_node.end_byte()),
924            ),
925        }
926    }
927
928    /// Extract the name from a Rust node
929    fn extract_name_rust(node: tree_sitter::Node, code: &str) -> Option<String> {
930        let mut cursor = node.walk();
931        for child in node.children(&mut cursor) {
932            if child.kind() == "identifier" {
933                if let Ok(text) = child.utf8_text(code.as_bytes()) {
934                    return Some(text.to_string());
935                }
936            }
937        }
938        None
939    }
940
941    /// Extract the name from a TypeScript node
942    fn extract_name_typescript(node: tree_sitter::Node, code: &str) -> Option<String> {
943        let mut cursor = node.walk();
944        for child in node.children(&mut cursor) {
945            if child.kind() == "identifier" {
946                if let Ok(text) = child.utf8_text(code.as_bytes()) {
947                    return Some(text.to_string());
948                }
949            }
950        }
951        None
952    }
953
954    /// Extract the name from a Python node
955    fn extract_name_python(node: tree_sitter::Node, code: &str) -> Option<String> {
956        let mut cursor = node.walk();
957        for child in node.children(&mut cursor) {
958            if child.kind() == "identifier" {
959                if let Ok(text) = child.utf8_text(code.as_bytes()) {
960                    return Some(text.to_string());
961                }
962            }
963        }
964        None
965    }
966
967    /// Convert a Position to a byte offset in the code
968    fn position_to_byte_offset(code: &str, position: Position) -> usize {
969        let mut byte_offset = 0;
970        let mut current_line = 0;
971        let mut current_char = 0;
972
973        for ch in code.chars() {
974            if current_line == position.line && current_char == position.character {
975                return byte_offset;
976            }
977
978            byte_offset += ch.len_utf8();
979
980            if ch == '\n' {
981                current_line += 1;
982                current_char = 0;
983            } else {
984                current_char += 1;
985            }
986        }
987
988        byte_offset
989    }
990
991    /// Convert a byte offset to a Position in the code
992    fn byte_offset_to_position(code: &str, byte_offset: usize) -> Position {
993        let mut current_line = 0;
994        let mut current_char = 0;
995        let mut current_byte = 0;
996
997        for ch in code.chars() {
998            if current_byte >= byte_offset {
999                return Position::new(current_line, current_char);
1000            }
1001
1002            current_byte += ch.len_utf8();
1003
1004            if ch == '\n' {
1005                current_line += 1;
1006                current_char = 0;
1007            } else {
1008                current_char += 1;
1009            }
1010        }
1011
1012        Position::new(current_line, current_char)
1013    }
1014
1015    /// Extract the prefix (partial word) at the cursor position
1016    fn extract_prefix(code: &str, position: Position) -> String {
1017        let byte_offset = Self::position_to_byte_offset(code, position);
1018        let mut prefix = String::new();
1019
1020        // Walk backwards from the position to find the start of the word
1021        for ch in code[..byte_offset].chars().rev() {
1022            if ch.is_alphanumeric() || ch == '_' {
1023                prefix.insert(0, ch);
1024            } else {
1025                break;
1026            }
1027        }
1028
1029        prefix
1030    }
1031}
1032
1033#[async_trait]
1034impl ContextAnalyzer for TreeSitterContextAnalyzer {
1035    async fn analyze_context(
1036        &self,
1037        code: &str,
1038        position: Position,
1039        language: &str,
1040    ) -> CompletionResult<CompletionContext> {
1041        // Parse the code
1042        let tree = Self::parse_code(code, language)?;
1043
1044        // Detect the scope at the position
1045        let scope = Self::detect_scope(code, position, &tree, language);
1046
1047        // Extract the prefix
1048        let prefix = Self::extract_prefix(code, position);
1049
1050        // Create the context
1051        let mut context = CompletionContext::new(language.to_string(), position, prefix);
1052        context.scope = scope;
1053
1054        // Collect available symbols
1055        context.available_symbols = self.get_available_symbols(&context, code);
1056
1057        // Infer expected type at the cursor position
1058        context.expected_type = self.infer_expected_type(&context);
1059
1060        Ok(context)
1061    }
1062
1063    fn get_available_symbols(&self, context: &CompletionContext, code: &str) -> Vec<Symbol> {
1064        // Collect symbols from the current scope
1065        let mut symbols = Vec::new();
1066
1067        // Add built-in symbols for the language
1068        symbols.extend(Self::get_builtin_symbols(&context.language));
1069
1070        // Add symbols from imported modules
1071        symbols.extend(Self::collect_imported_symbols(code, &context.language));
1072
1073        // Add symbols from the current scope
1074        symbols.extend(Self::collect_scope_symbols_with_code(context, code));
1075
1076        symbols
1077    }
1078
1079    fn infer_expected_type(&self, context: &CompletionContext) -> Option<Type> {
1080        Self::infer_type_from_context(context)
1081    }
1082}
1083
1084impl TreeSitterContextAnalyzer {
1085    /// Infer the expected type at the given context
1086    fn infer_type_from_context(context: &CompletionContext) -> Option<Type> {
1087        // Try to infer type from assignment context
1088        if let Some(type_info) = Self::infer_from_assignment(context) {
1089            return Some(type_info);
1090        }
1091
1092        // Try to infer type from function parameter context
1093        if let Some(type_info) = Self::infer_from_function_param(context) {
1094            return Some(type_info);
1095        }
1096
1097        // Try to infer type from return type context
1098        if let Some(type_info) = Self::infer_from_return_type(context) {
1099            return Some(type_info);
1100        }
1101
1102        None
1103    }
1104
1105    /// Infer type from assignment context (e.g., "let x: Type = ")
1106    fn infer_from_assignment(context: &CompletionContext) -> Option<Type> {
1107        match context.language.as_str() {
1108            "rust" => Self::infer_rust_assignment_type(context),
1109            "typescript" | "javascript" => Self::infer_typescript_assignment_type(context),
1110            "python" => Self::infer_python_assignment_type(context),
1111            _ => None,
1112        }
1113    }
1114
1115    /// Infer Rust assignment type from type annotations
1116    fn infer_rust_assignment_type(context: &CompletionContext) -> Option<Type> {
1117        // Look for patterns like "let x: Type = " or "let x: Type<T> = "
1118        // We need to find the line with the assignment and extract the type annotation
1119
1120        // For now, we'll use a simple pattern matching approach
1121        // In a full implementation, this would use the AST
1122
1123        // Check if we're in an assignment context by looking at the scope
1124        if context.scope.kind == ScopeKind::Function || context.scope.kind == ScopeKind::Block {
1125            // Try to infer from variable declarations with type annotations
1126            // This is a simplified implementation
1127
1128            // Common Rust types that might be inferred
1129            if context.prefix.contains("vec") || context.prefix.contains("Vec") {
1130                return Some(Type::new("Vec".to_string()).array());
1131            }
1132            if context.prefix.contains("string") || context.prefix.contains("String") {
1133                return Some(Type::new("String".to_string()));
1134            }
1135            if context.prefix.contains("option") || context.prefix.contains("Option") {
1136                return Some(Type::new("Option".to_string()).optional());
1137            }
1138            if context.prefix.contains("result") || context.prefix.contains("Result") {
1139                return Some(Type::new("Result".to_string()));
1140            }
1141        }
1142
1143        None
1144    }
1145
1146    /// Infer TypeScript assignment type from type annotations
1147    fn infer_typescript_assignment_type(context: &CompletionContext) -> Option<Type> {
1148        // Look for patterns like "let x: Type = " or "const x: Type = "
1149
1150        // Common TypeScript types that might be inferred
1151        if context.prefix.contains("array") || context.prefix.contains("Array") {
1152            return Some(Type::new("Array".to_string()).array());
1153        }
1154        if context.prefix.contains("string") || context.prefix.contains("String") {
1155            return Some(Type::new("string".to_string()));
1156        }
1157        if context.prefix.contains("number") || context.prefix.contains("Number") {
1158            return Some(Type::new("number".to_string()));
1159        }
1160        if context.prefix.contains("promise") || context.prefix.contains("Promise") {
1161            return Some(Type::new("Promise".to_string()));
1162        }
1163        if context.prefix.contains("map") || context.prefix.contains("Map") {
1164            return Some(Type::new("Map".to_string()));
1165        }
1166
1167        None
1168    }
1169
1170    /// Infer Python assignment type from type hints
1171    fn infer_python_assignment_type(context: &CompletionContext) -> Option<Type> {
1172        // Look for patterns like "x: Type = " or "x: Type[T] = "
1173
1174        // Common Python types that might be inferred
1175        if context.prefix.contains("list") || context.prefix.contains("List") {
1176            return Some(Type::new("list".to_string()).array());
1177        }
1178        if context.prefix.contains("dict") || context.prefix.contains("Dict") {
1179            return Some(Type::new("dict".to_string()));
1180        }
1181        if context.prefix.contains("str") || context.prefix.contains("String") {
1182            return Some(Type::new("str".to_string()));
1183        }
1184        if context.prefix.contains("int") || context.prefix.contains("Integer") {
1185            return Some(Type::new("int".to_string()));
1186        }
1187        if context.prefix.contains("tuple") || context.prefix.contains("Tuple") {
1188            return Some(Type::new("tuple".to_string()).array());
1189        }
1190
1191        None
1192    }
1193
1194    /// Infer type from function parameter context
1195    fn infer_from_function_param(context: &CompletionContext) -> Option<Type> {
1196        match context.language.as_str() {
1197            "rust" => Self::infer_rust_function_param_type(context),
1198            "typescript" | "javascript" => Self::infer_typescript_function_param_type(context),
1199            "python" => Self::infer_python_function_param_type(context),
1200            _ => None,
1201        }
1202    }
1203
1204    /// Infer Rust function parameter type
1205    fn infer_rust_function_param_type(context: &CompletionContext) -> Option<Type> {
1206        // If we're in a function scope, try to infer parameter types
1207        if context.scope.kind == ScopeKind::Function {
1208            // Look for common parameter patterns
1209            if context.prefix.contains("&str") {
1210                return Some(Type::new("&str".to_string()));
1211            }
1212            if context.prefix.contains("&mut") {
1213                return Some(Type::new("&mut".to_string()));
1214            }
1215            if context.prefix.contains("&") {
1216                return Some(Type::new("&".to_string()));
1217            }
1218        }
1219
1220        None
1221    }
1222
1223    /// Infer TypeScript function parameter type
1224    fn infer_typescript_function_param_type(context: &CompletionContext) -> Option<Type> {
1225        // If we're in a function scope, try to infer parameter types
1226        if context.scope.kind == ScopeKind::Function {
1227            // Look for common parameter patterns
1228            if context.prefix.contains("string") {
1229                return Some(Type::new("string".to_string()));
1230            }
1231            if context.prefix.contains("number") {
1232                return Some(Type::new("number".to_string()));
1233            }
1234            if context.prefix.contains("boolean") {
1235                return Some(Type::new("boolean".to_string()));
1236            }
1237            if context.prefix.contains("any") {
1238                return Some(Type::new("any".to_string()));
1239            }
1240        }
1241
1242        None
1243    }
1244
1245    /// Infer Python function parameter type
1246    fn infer_python_function_param_type(context: &CompletionContext) -> Option<Type> {
1247        // If we're in a function scope, try to infer parameter types
1248        if context.scope.kind == ScopeKind::Function {
1249            // Look for common parameter patterns
1250            if context.prefix.contains("str") {
1251                return Some(Type::new("str".to_string()));
1252            }
1253            if context.prefix.contains("int") {
1254                return Some(Type::new("int".to_string()));
1255            }
1256            if context.prefix.contains("float") {
1257                return Some(Type::new("float".to_string()));
1258            }
1259            if context.prefix.contains("bool") {
1260                return Some(Type::new("bool".to_string()));
1261            }
1262        }
1263
1264        None
1265    }
1266
1267    /// Infer type from return type context
1268    fn infer_from_return_type(context: &CompletionContext) -> Option<Type> {
1269        match context.language.as_str() {
1270            "rust" => Self::infer_rust_return_type(context),
1271            "typescript" | "javascript" => Self::infer_typescript_return_type(context),
1272            "python" => Self::infer_python_return_type(context),
1273            _ => None,
1274        }
1275    }
1276
1277    /// Infer Rust return type
1278    fn infer_rust_return_type(context: &CompletionContext) -> Option<Type> {
1279        // If we're in a function scope, try to infer return type
1280        if context.scope.kind == ScopeKind::Function {
1281            // Look for common return type patterns
1282            if context.prefix.contains("Result") {
1283                return Some(Type::new("Result".to_string()));
1284            }
1285            if context.prefix.contains("Option") {
1286                return Some(Type::new("Option".to_string()).optional());
1287            }
1288            if context.prefix.contains("Vec") {
1289                return Some(Type::new("Vec".to_string()).array());
1290            }
1291            if context.prefix.contains("String") {
1292                return Some(Type::new("String".to_string()));
1293            }
1294        }
1295
1296        None
1297    }
1298
1299    /// Infer TypeScript return type
1300    fn infer_typescript_return_type(context: &CompletionContext) -> Option<Type> {
1301        // If we're in a function scope, try to infer return type
1302        if context.scope.kind == ScopeKind::Function {
1303            // Look for common return type patterns
1304            if context.prefix.contains("Promise") {
1305                return Some(Type::new("Promise".to_string()));
1306            }
1307            if context.prefix.contains("Array") {
1308                return Some(Type::new("Array".to_string()).array());
1309            }
1310            if context.prefix.contains("string") {
1311                return Some(Type::new("string".to_string()));
1312            }
1313            if context.prefix.contains("number") {
1314                return Some(Type::new("number".to_string()));
1315            }
1316        }
1317
1318        None
1319    }
1320
1321    /// Infer Python return type
1322    fn infer_python_return_type(context: &CompletionContext) -> Option<Type> {
1323        // If we're in a function scope, try to infer return type
1324        if context.scope.kind == ScopeKind::Function {
1325            // Look for common return type patterns
1326            if context.prefix.contains("list") {
1327                return Some(Type::new("list".to_string()).array());
1328            }
1329            if context.prefix.contains("dict") {
1330                return Some(Type::new("dict".to_string()));
1331            }
1332            if context.prefix.contains("str") {
1333                return Some(Type::new("str".to_string()));
1334            }
1335            if context.prefix.contains("int") {
1336                return Some(Type::new("int".to_string()));
1337            }
1338        }
1339
1340        None
1341    }
1342
1343    /// Infer variable type from assignments and declarations
1344    pub fn infer_variable_type(code: &str, position: Position, language: &str) -> Option<Type> {
1345        let byte_offset = Self::position_to_byte_offset(code, position);
1346        let code_before = &code[..byte_offset];
1347
1348        match language {
1349            "rust" => Self::infer_rust_variable_type(code_before),
1350            "typescript" | "javascript" => Self::infer_typescript_variable_type(code_before),
1351            "python" => Self::infer_python_variable_type(code_before),
1352            _ => None,
1353        }
1354    }
1355
1356    /// Infer Rust variable type from assignments
1357    fn infer_rust_variable_type(code_before: &str) -> Option<Type> {
1358        // Look for the most recent variable declaration with type annotation
1359        for line in code_before.lines().rev() {
1360            let trimmed = line.trim();
1361
1362            // Pattern: let x: Type = ...
1363            if (trimmed.starts_with("let ") || trimmed.starts_with("let mut "))
1364                && trimmed.contains(':')
1365            {
1366                if let Some(type_str) = Self::extract_rust_type_annotation(trimmed) {
1367                    return Some(Self::parse_rust_type(&type_str));
1368                }
1369            }
1370
1371            // Pattern: const X: Type = ...
1372            if trimmed.starts_with("const ") && trimmed.contains(':') {
1373                if let Some(type_str) = Self::extract_rust_type_annotation(trimmed) {
1374                    return Some(Self::parse_rust_type(&type_str));
1375                }
1376            }
1377        }
1378
1379        None
1380    }
1381
1382    /// Extract Rust type annotation from a line
1383    fn extract_rust_type_annotation(line: &str) -> Option<String> {
1384        if let Some(colon_pos) = line.find(':') {
1385            if let Some(eq_pos) = line.find('=') {
1386                if colon_pos < eq_pos {
1387                    let type_str = &line[colon_pos + 1..eq_pos];
1388                    return Some(type_str.trim().to_string());
1389                }
1390            } else {
1391                let type_str = &line[colon_pos + 1..];
1392                return Some(type_str.trim().to_string());
1393            }
1394        }
1395        None
1396    }
1397
1398    /// Parse Rust type string into Type struct
1399    fn parse_rust_type(type_str: &str) -> Type {
1400        let type_str = type_str.trim();
1401
1402        // Handle Option<T>
1403        if type_str.starts_with("Option<") {
1404            let inner = &type_str[7..type_str.len() - 1];
1405            return Type::new(inner.to_string()).optional();
1406        }
1407
1408        // Handle Vec<T>
1409        if type_str.starts_with("Vec<") {
1410            let inner = &type_str[4..type_str.len() - 1];
1411            return Type::new(inner.to_string()).array();
1412        }
1413
1414        // Handle Result<T, E>
1415        if type_str.starts_with("Result<") {
1416            let inner = &type_str[7..type_str.len() - 1];
1417            return Type::new(inner.to_string());
1418        }
1419
1420        // Handle references
1421        if let Some(inner) = type_str.strip_prefix("&") {
1422            return Type::new(inner.to_string());
1423        }
1424
1425        // Simple type
1426        Type::new(type_str.to_string())
1427    }
1428
1429    /// Infer TypeScript variable type from assignments
1430    fn infer_typescript_variable_type(code_before: &str) -> Option<Type> {
1431        // Look for the most recent variable declaration with type annotation
1432        for line in code_before.lines().rev() {
1433            let trimmed = line.trim();
1434
1435            // Pattern: let x: Type = ...
1436            if (trimmed.starts_with("let ")
1437                || trimmed.starts_with("const ")
1438                || trimmed.starts_with("var "))
1439                && trimmed.contains(':')
1440            {
1441                if let Some(type_str) = Self::extract_typescript_type_annotation(trimmed) {
1442                    return Some(Self::parse_typescript_type(&type_str));
1443                }
1444            }
1445        }
1446
1447        None
1448    }
1449
1450    /// Extract TypeScript type annotation from a line
1451    fn extract_typescript_type_annotation(line: &str) -> Option<String> {
1452        if let Some(colon_pos) = line.find(':') {
1453            if let Some(eq_pos) = line.find('=') {
1454                if colon_pos < eq_pos {
1455                    let type_str = &line[colon_pos + 1..eq_pos];
1456                    return Some(type_str.trim().to_string());
1457                }
1458            } else {
1459                let type_str = &line[colon_pos + 1..];
1460                return Some(type_str.trim().to_string());
1461            }
1462        }
1463        None
1464    }
1465
1466    /// Parse TypeScript type string into Type struct
1467    fn parse_typescript_type(type_str: &str) -> Type {
1468        let type_str = type_str.trim();
1469
1470        // Handle Array<T>
1471        if type_str.starts_with("Array<") {
1472            let inner = &type_str[6..type_str.len() - 1];
1473            return Type::new(inner.to_string()).array();
1474        }
1475
1476        // Handle T[]
1477        if let Some(inner) = type_str.strip_suffix("[]") {
1478            return Type::new(inner.to_string()).array();
1479        }
1480
1481        // Handle Promise<T>
1482        if type_str.starts_with("Promise<") {
1483            let inner = &type_str[8..type_str.len() - 1];
1484            return Type::new(inner.to_string());
1485        }
1486
1487        // Simple type
1488        Type::new(type_str.to_string())
1489    }
1490
1491    /// Infer Python variable type from assignments
1492    fn infer_python_variable_type(code_before: &str) -> Option<Type> {
1493        // Look for the most recent variable declaration with type hint
1494        for line in code_before.lines().rev() {
1495            let trimmed = line.trim();
1496
1497            // Skip comments and empty lines
1498            if trimmed.is_empty() || trimmed.starts_with('#') {
1499                continue;
1500            }
1501
1502            // Pattern: x: Type = ...
1503            if trimmed.contains(':') && trimmed.contains('=') {
1504                if let Some(type_str) = Self::extract_python_type_annotation(trimmed) {
1505                    return Some(Self::parse_python_type(&type_str));
1506                }
1507            }
1508        }
1509
1510        None
1511    }
1512
1513    /// Extract Python type annotation from a line
1514    fn extract_python_type_annotation(line: &str) -> Option<String> {
1515        if let Some(colon_pos) = line.find(':') {
1516            if let Some(eq_pos) = line.find('=') {
1517                if colon_pos < eq_pos {
1518                    let type_str = &line[colon_pos + 1..eq_pos];
1519                    return Some(type_str.trim().to_string());
1520                }
1521            }
1522        }
1523        None
1524    }
1525
1526    /// Parse Python type string into Type struct
1527    fn parse_python_type(type_str: &str) -> Type {
1528        let type_str = type_str.trim();
1529
1530        // Handle List[T]
1531        if type_str.starts_with("List[") {
1532            let inner = &type_str[5..type_str.len() - 1];
1533            return Type::new(inner.to_string()).array();
1534        }
1535
1536        // Handle list
1537        if type_str == "list" {
1538            return Type::new("list".to_string()).array();
1539        }
1540
1541        // Handle Dict[K, V]
1542        if type_str.starts_with("Dict[") {
1543            let inner = &type_str[5..type_str.len() - 1];
1544            return Type::new(inner.to_string());
1545        }
1546
1547        // Handle Optional[T]
1548        if type_str.starts_with("Optional[") {
1549            let inner = &type_str[9..type_str.len() - 1];
1550            return Type::new(inner.to_string()).optional();
1551        }
1552
1553        // Handle Tuple[T, ...]
1554        if type_str.starts_with("Tuple[") {
1555            let inner = &type_str[6..type_str.len() - 1];
1556            return Type::new(inner.to_string()).array();
1557        }
1558
1559        // Simple type
1560        Type::new(type_str.to_string())
1561    }
1562
1563    /// Infer function return type from signature
1564    pub fn infer_function_return_type(
1565        code: &str,
1566        position: Position,
1567        language: &str,
1568    ) -> Option<Type> {
1569        let byte_offset = Self::position_to_byte_offset(code, position);
1570        let code_before = &code[..byte_offset];
1571
1572        match language {
1573            "rust" => Self::infer_rust_function_return_type(code_before),
1574            "typescript" | "javascript" => Self::infer_typescript_function_return_type(code_before),
1575            "python" => Self::infer_python_function_return_type(code_before),
1576            _ => None,
1577        }
1578    }
1579
1580    /// Infer Rust function return type from signature
1581    fn infer_rust_function_return_type(code_before: &str) -> Option<Type> {
1582        // Look for the most recent function definition
1583        for line in code_before.lines().rev() {
1584            let trimmed = line.trim();
1585
1586            // Pattern: fn name(...) -> Type { ... }
1587            if trimmed.starts_with("fn ") && trimmed.contains("->") {
1588                if let Some(return_type) = Self::extract_rust_return_type(trimmed) {
1589                    return Some(Self::parse_rust_type(&return_type));
1590                }
1591            }
1592        }
1593
1594        None
1595    }
1596
1597    /// Extract Rust return type from function signature
1598    fn extract_rust_return_type(line: &str) -> Option<String> {
1599        if let Some(arrow_pos) = line.find("->") {
1600            if let Some(brace_pos) = line.find('{') {
1601                let return_type = &line[arrow_pos + 2..brace_pos];
1602                return Some(return_type.trim().to_string());
1603            } else {
1604                let return_type = &line[arrow_pos + 2..];
1605                return Some(return_type.trim().to_string());
1606            }
1607        }
1608        None
1609    }
1610
1611    /// Infer TypeScript function return type from signature
1612    fn infer_typescript_function_return_type(code_before: &str) -> Option<Type> {
1613        // Look for the most recent function definition
1614        for line in code_before.lines().rev() {
1615            let trimmed = line.trim();
1616
1617            // Pattern: function name(...): Type { ... } or async function name(...): Type { ... } or (...): Type => ...
1618            if (trimmed.starts_with("function ")
1619                || trimmed.starts_with("async function ")
1620                || trimmed.contains("=>"))
1621                && trimmed.contains(':')
1622            {
1623                if let Some(return_type) = Self::extract_typescript_return_type(trimmed) {
1624                    return Some(Self::parse_typescript_type(&return_type));
1625                }
1626            }
1627        }
1628
1629        None
1630    }
1631
1632    /// Extract TypeScript return type from function signature
1633    fn extract_typescript_return_type(line: &str) -> Option<String> {
1634        // Look for pattern: ): Type { or ): Type =>
1635        if let Some(paren_pos) = line.rfind(')') {
1636            let after_paren = &line[paren_pos..];
1637
1638            // Look for : Type pattern
1639            if let Some(colon_pos) = after_paren.find(':') {
1640                let after_colon = &after_paren[colon_pos + 1..];
1641
1642                // Find the end of the type (either { or =>)
1643                let end_pos = if let Some(brace_pos) = after_colon.find('{') {
1644                    brace_pos
1645                } else if let Some(arrow_pos) = after_colon.find("=>") {
1646                    arrow_pos
1647                } else {
1648                    // No brace or arrow found, take until end of line
1649                    after_colon.len()
1650                };
1651
1652                let return_type = &after_colon[..end_pos];
1653                return Some(return_type.trim().to_string());
1654            }
1655        }
1656        None
1657    }
1658
1659    /// Infer Python function return type from signature
1660    fn infer_python_function_return_type(code_before: &str) -> Option<Type> {
1661        // Look for the most recent function definition
1662        for line in code_before.lines().rev() {
1663            let trimmed = line.trim();
1664
1665            // Pattern: def name(...) -> Type: ...
1666            if trimmed.starts_with("def ") && trimmed.contains("->") {
1667                if let Some(return_type) = Self::extract_python_return_type(trimmed) {
1668                    return Some(Self::parse_python_type(&return_type));
1669                }
1670            }
1671        }
1672
1673        None
1674    }
1675
1676    /// Extract Python return type from function signature
1677    fn extract_python_return_type(line: &str) -> Option<String> {
1678        if let Some(arrow_pos) = line.find("->") {
1679            if let Some(colon_pos) = line.find(':') {
1680                if arrow_pos < colon_pos {
1681                    let return_type = &line[arrow_pos + 2..colon_pos];
1682                    return Some(return_type.trim().to_string());
1683                }
1684            }
1685        }
1686        None
1687    }
1688}
1689
1690/// Generic context analyzer (fallback for unsupported languages)
1691pub struct GenericContextAnalyzer;
1692
1693impl GenericContextAnalyzer {
1694    /// Collect symbols from imported modules using text patterns
1695    fn collect_imported_symbols_generic(code: &str, language: &str) -> Vec<Symbol> {
1696        let mut symbols = Vec::new();
1697
1698        match language {
1699            "rust" => {
1700                // Look for use statements
1701                for line in code.lines() {
1702                    if line.trim().starts_with("use ") {
1703                        if let Some(imported) = TreeSitterContextAnalyzer::extract_rust_import(line)
1704                        {
1705                            symbols.push(Symbol {
1706                                name: imported.clone(),
1707                                kind: SymbolKind::Module,
1708                                scope: Scope {
1709                                    kind: ScopeKind::Global,
1710                                    name: None,
1711                                    range: Range::new(Position::new(0, 0), Position::new(0, 0)),
1712                                },
1713                                type_info: None,
1714                                documentation: None,
1715                            });
1716                        }
1717                    }
1718                }
1719            }
1720            "typescript" | "javascript" => {
1721                // Look for import statements
1722                for line in code.lines() {
1723                    if line.trim().starts_with("import ") {
1724                        if let Some(imported) =
1725                            TreeSitterContextAnalyzer::extract_typescript_import(line)
1726                        {
1727                            symbols.push(Symbol {
1728                                name: imported.clone(),
1729                                kind: SymbolKind::Module,
1730                                scope: Scope {
1731                                    kind: ScopeKind::Global,
1732                                    name: None,
1733                                    range: Range::new(Position::new(0, 0), Position::new(0, 0)),
1734                                },
1735                                type_info: None,
1736                                documentation: None,
1737                            });
1738                        }
1739                    }
1740                }
1741            }
1742            "python" => {
1743                // Look for import statements
1744                for line in code.lines() {
1745                    if line.trim().starts_with("import ") || line.trim().starts_with("from ") {
1746                        if let Some(imported) =
1747                            TreeSitterContextAnalyzer::extract_python_import(line)
1748                        {
1749                            symbols.push(Symbol {
1750                                name: imported.clone(),
1751                                kind: SymbolKind::Module,
1752                                scope: Scope {
1753                                    kind: ScopeKind::Global,
1754                                    name: None,
1755                                    range: Range::new(Position::new(0, 0), Position::new(0, 0)),
1756                                },
1757                                type_info: None,
1758                                documentation: None,
1759                            });
1760                        }
1761                    }
1762                }
1763            }
1764            _ => {}
1765        }
1766
1767        symbols
1768    }
1769
1770    /// Collect symbols from the current scope using text patterns
1771    fn collect_scope_symbols_generic(context: &CompletionContext, code: &str) -> Vec<Symbol> {
1772        let mut symbols = Vec::new();
1773
1774        match context.language.as_str() {
1775            "rust" => {
1776                symbols.extend(TreeSitterContextAnalyzer::collect_rust_scope_symbols(
1777                    code, context,
1778                ));
1779            }
1780            "typescript" | "javascript" => {
1781                symbols.extend(TreeSitterContextAnalyzer::collect_typescript_scope_symbols(
1782                    code, context,
1783                ));
1784            }
1785            "python" => {
1786                symbols.extend(TreeSitterContextAnalyzer::collect_python_scope_symbols(
1787                    code, context,
1788                ));
1789            }
1790            _ => {}
1791        }
1792
1793        symbols
1794    }
1795}
1796
1797#[async_trait]
1798impl ContextAnalyzer for GenericContextAnalyzer {
1799    async fn analyze_context(
1800        &self,
1801        code: &str,
1802        position: Position,
1803        language: &str,
1804    ) -> CompletionResult<CompletionContext> {
1805        // Extract the prefix using simple text-based approach
1806        let prefix = Self::extract_prefix_generic(code, position);
1807
1808        // Create the context
1809        let mut context = CompletionContext::new(language.to_string(), position, prefix);
1810
1811        // Detect scope using simple text patterns
1812        context.scope = Self::detect_scope_generic(code, position);
1813
1814        // Collect available symbols
1815        context.available_symbols = self.get_available_symbols(&context, code);
1816
1817        // Infer expected type at the cursor position
1818        context.expected_type = self.infer_expected_type(&context);
1819
1820        Ok(context)
1821    }
1822
1823    fn get_available_symbols(&self, context: &CompletionContext, code: &str) -> Vec<Symbol> {
1824        // Collect symbols from the current scope
1825        let mut symbols = Vec::new();
1826
1827        // Add built-in symbols for the language
1828        symbols.extend(Self::get_builtin_symbols(&context.language));
1829
1830        // Add symbols from imported modules
1831        symbols.extend(Self::collect_imported_symbols_generic(
1832            code,
1833            &context.language,
1834        ));
1835
1836        // Add symbols from the current scope
1837        symbols.extend(Self::collect_scope_symbols_generic(context, code));
1838
1839        symbols
1840    }
1841
1842    fn infer_expected_type(&self, context: &CompletionContext) -> Option<Type> {
1843        Self::infer_type_from_context_generic(context)
1844    }
1845}
1846
1847impl GenericContextAnalyzer {
1848    /// Infer the expected type at the given context using text patterns
1849    fn infer_type_from_context_generic(context: &CompletionContext) -> Option<Type> {
1850        // Try to infer type from assignment context
1851        if let Some(type_info) = Self::infer_from_assignment_generic(context) {
1852            return Some(type_info);
1853        }
1854
1855        // Try to infer type from function parameter context
1856        if let Some(type_info) = Self::infer_from_function_param_generic(context) {
1857            return Some(type_info);
1858        }
1859
1860        // Try to infer type from return type context
1861        if let Some(type_info) = Self::infer_from_return_type_generic(context) {
1862            return Some(type_info);
1863        }
1864
1865        None
1866    }
1867
1868    /// Infer type from assignment context using text patterns
1869    fn infer_from_assignment_generic(context: &CompletionContext) -> Option<Type> {
1870        match context.language.as_str() {
1871            "rust" => TreeSitterContextAnalyzer::infer_rust_assignment_type(context),
1872            "typescript" | "javascript" => {
1873                TreeSitterContextAnalyzer::infer_typescript_assignment_type(context)
1874            }
1875            "python" => TreeSitterContextAnalyzer::infer_python_assignment_type(context),
1876            _ => None,
1877        }
1878    }
1879
1880    /// Infer type from function parameter context using text patterns
1881    fn infer_from_function_param_generic(context: &CompletionContext) -> Option<Type> {
1882        match context.language.as_str() {
1883            "rust" => TreeSitterContextAnalyzer::infer_rust_function_param_type(context),
1884            "typescript" | "javascript" => {
1885                TreeSitterContextAnalyzer::infer_typescript_function_param_type(context)
1886            }
1887            "python" => TreeSitterContextAnalyzer::infer_python_function_param_type(context),
1888            _ => None,
1889        }
1890    }
1891
1892    /// Infer type from return type context using text patterns
1893    fn infer_from_return_type_generic(context: &CompletionContext) -> Option<Type> {
1894        match context.language.as_str() {
1895            "rust" => TreeSitterContextAnalyzer::infer_rust_return_type(context),
1896            "typescript" | "javascript" => {
1897                TreeSitterContextAnalyzer::infer_typescript_return_type(context)
1898            }
1899            "python" => TreeSitterContextAnalyzer::infer_python_return_type(context),
1900            _ => None,
1901        }
1902    }
1903    /// Extract the prefix using simple text-based approach
1904    fn extract_prefix_generic(code: &str, position: Position) -> String {
1905        let byte_offset = TreeSitterContextAnalyzer::position_to_byte_offset(code, position);
1906        let mut prefix = String::new();
1907
1908        // Walk backwards from the position to find the start of the word
1909        for ch in code[..byte_offset].chars().rev() {
1910            if ch.is_alphanumeric() || ch == '_' {
1911                prefix.insert(0, ch);
1912            } else {
1913                break;
1914            }
1915        }
1916
1917        prefix
1918    }
1919
1920    /// Detect scope using simple text patterns
1921    fn detect_scope_generic(code: &str, position: Position) -> Scope {
1922        let byte_offset = TreeSitterContextAnalyzer::position_to_byte_offset(code, position);
1923        let code_before = &code[..byte_offset];
1924
1925        // Count braces to determine if we're in a block
1926        let open_braces = code_before.matches('{').count();
1927        let close_braces = code_before.matches('}').count();
1928        let in_block = open_braces > close_braces;
1929
1930        // Try to detect function or class definitions
1931        let scope_kind = if code_before.contains("fn ") || code_before.contains("function ") {
1932            ScopeKind::Function
1933        } else if code_before.contains("class ") || code_before.contains("struct ") {
1934            ScopeKind::Class
1935        } else if in_block {
1936            ScopeKind::Block
1937        } else {
1938            ScopeKind::Global
1939        };
1940
1941        Scope {
1942            kind: scope_kind,
1943            name: None,
1944            range: Range::new(Position::new(0, 0), position),
1945        }
1946    }
1947
1948    /// Get built-in symbols for a language
1949    fn get_builtin_symbols(language: &str) -> Vec<Symbol> {
1950        TreeSitterContextAnalyzer::get_builtin_symbols(language)
1951    }
1952}
1953
1954#[cfg(test)]
1955mod tests {
1956    use super::*;
1957
1958    #[test]
1959    fn test_position_to_byte_offset() {
1960        let code = "hello\nworld";
1961        let pos = Position::new(1, 2);
1962        let offset = TreeSitterContextAnalyzer::position_to_byte_offset(code, pos);
1963        assert_eq!(offset, 8); // "hello\nwo"
1964    }
1965
1966    #[test]
1967    fn test_byte_offset_to_position() {
1968        let code = "hello\nworld";
1969        let pos = TreeSitterContextAnalyzer::byte_offset_to_position(code, 8);
1970        assert_eq!(pos, Position::new(1, 2));
1971    }
1972
1973    #[test]
1974    fn test_extract_prefix() {
1975        let code = "let my_var = ";
1976        let pos = Position::new(0, 13);
1977        let prefix = TreeSitterContextAnalyzer::extract_prefix(code, pos);
1978        assert_eq!(prefix, "");
1979    }
1980
1981    #[test]
1982    fn test_extract_prefix_with_word() {
1983        let code = "let my_var = my";
1984        let pos = Position::new(0, 15);
1985        let prefix = TreeSitterContextAnalyzer::extract_prefix(code, pos);
1986        assert_eq!(prefix, "my");
1987    }
1988
1989    #[test]
1990    fn test_generic_extract_prefix() {
1991        let code = "let my_var = my";
1992        let pos = Position::new(0, 15);
1993        let prefix = GenericContextAnalyzer::extract_prefix_generic(code, pos);
1994        assert_eq!(prefix, "my");
1995    }
1996
1997    #[test]
1998    fn test_generic_detect_scope_global() {
1999        let code = "let x = 5;";
2000        let pos = Position::new(0, 5);
2001        let scope = GenericContextAnalyzer::detect_scope_generic(code, pos);
2002        assert_eq!(scope.kind, ScopeKind::Global);
2003    }
2004
2005    #[test]
2006    fn test_generic_detect_scope_function() {
2007        let code = "fn main() { let x = 5; }";
2008        let pos = Position::new(0, 15);
2009        let scope = GenericContextAnalyzer::detect_scope_generic(code, pos);
2010        assert_eq!(scope.kind, ScopeKind::Function);
2011    }
2012
2013    #[test]
2014    fn test_generic_detect_scope_block() {
2015        let code = "{ let x = 5; }";
2016        let pos = Position::new(0, 10);
2017        let scope = GenericContextAnalyzer::detect_scope_generic(code, pos);
2018        assert_eq!(scope.kind, ScopeKind::Block);
2019    }
2020
2021    // Type inference tests
2022    #[test]
2023    fn test_infer_rust_variable_type_simple() {
2024        let code = "let x: String = ";
2025        let ty = TreeSitterContextAnalyzer::infer_rust_variable_type(code);
2026        assert!(ty.is_some());
2027        let ty = ty.unwrap();
2028        assert_eq!(ty.name, "String");
2029    }
2030
2031    #[test]
2032    fn test_infer_rust_variable_type_vec() {
2033        let code = "let items: Vec<i32> = ";
2034        let ty = TreeSitterContextAnalyzer::infer_rust_variable_type(code);
2035        assert!(ty.is_some());
2036        let ty = ty.unwrap();
2037        assert_eq!(ty.name, "i32");
2038        assert!(ty.is_array);
2039    }
2040
2041    #[test]
2042    fn test_infer_rust_variable_type_option() {
2043        let code = "let maybe: Option<String> = ";
2044        let ty = TreeSitterContextAnalyzer::infer_rust_variable_type(code);
2045        assert!(ty.is_some());
2046        let ty = ty.unwrap();
2047        assert_eq!(ty.name, "String");
2048        assert!(ty.is_optional);
2049    }
2050
2051    #[test]
2052    fn test_infer_rust_variable_type_reference() {
2053        let code = "let reference: &str = ";
2054        let ty = TreeSitterContextAnalyzer::infer_rust_variable_type(code);
2055        assert!(ty.is_some());
2056        let ty = ty.unwrap();
2057        assert_eq!(ty.name, "str");
2058    }
2059
2060    #[test]
2061    fn test_infer_typescript_variable_type_simple() {
2062        let code = "let x: string = ";
2063        let ty = TreeSitterContextAnalyzer::infer_typescript_variable_type(code);
2064        assert!(ty.is_some());
2065        let ty = ty.unwrap();
2066        assert_eq!(ty.name, "string");
2067    }
2068
2069    #[test]
2070    fn test_infer_typescript_variable_type_array() {
2071        let code = "let items: number[] = ";
2072        let ty = TreeSitterContextAnalyzer::infer_typescript_variable_type(code);
2073        assert!(ty.is_some());
2074        let ty = ty.unwrap();
2075        assert_eq!(ty.name, "number");
2076        assert!(ty.is_array);
2077    }
2078
2079    #[test]
2080    fn test_infer_typescript_variable_type_array_generic() {
2081        let code = "let items: Array<string> = ";
2082        let ty = TreeSitterContextAnalyzer::infer_typescript_variable_type(code);
2083        assert!(ty.is_some());
2084        let ty = ty.unwrap();
2085        assert_eq!(ty.name, "string");
2086        assert!(ty.is_array);
2087    }
2088
2089    #[test]
2090    fn test_infer_python_variable_type_simple() {
2091        let code = "x: str = ";
2092        let ty = TreeSitterContextAnalyzer::infer_python_variable_type(code);
2093        assert!(ty.is_some());
2094        let ty = ty.unwrap();
2095        assert_eq!(ty.name, "str");
2096    }
2097
2098    #[test]
2099    fn test_infer_python_variable_type_list() {
2100        let code = "items: List[int] = ";
2101        let ty = TreeSitterContextAnalyzer::infer_python_variable_type(code);
2102        assert!(ty.is_some());
2103        let ty = ty.unwrap();
2104        assert_eq!(ty.name, "int");
2105        assert!(ty.is_array);
2106    }
2107
2108    #[test]
2109    fn test_infer_python_variable_type_optional() {
2110        let code = "maybe: Optional[str] = ";
2111        let ty = TreeSitterContextAnalyzer::infer_python_variable_type(code);
2112        assert!(ty.is_some());
2113        let ty = ty.unwrap();
2114        assert_eq!(ty.name, "str");
2115        assert!(ty.is_optional);
2116    }
2117
2118    #[test]
2119    fn test_infer_rust_function_return_type() {
2120        let code = "fn get_name() -> String { ";
2121        let ty = TreeSitterContextAnalyzer::infer_rust_function_return_type(code);
2122        assert!(ty.is_some());
2123        let ty = ty.unwrap();
2124        assert_eq!(ty.name, "String");
2125    }
2126
2127    #[test]
2128    fn test_infer_rust_function_return_type_result() {
2129        let code = "fn process() -> Result<i32, String> { ";
2130        let ty = TreeSitterContextAnalyzer::infer_rust_function_return_type(code);
2131        assert!(ty.is_some());
2132        let ty = ty.unwrap();
2133        assert_eq!(ty.name, "i32, String");
2134    }
2135
2136    #[test]
2137    fn test_infer_typescript_function_return_type() {
2138        let code = "function getName(): string { ";
2139        let ty = TreeSitterContextAnalyzer::infer_typescript_function_return_type(code);
2140        assert!(ty.is_some());
2141        let ty = ty.unwrap();
2142        assert_eq!(ty.name, "string");
2143    }
2144
2145    #[test]
2146    fn test_infer_typescript_function_return_type_promise() {
2147        let code = "async function fetch(): Promise<string> { ";
2148        let ty = TreeSitterContextAnalyzer::infer_typescript_function_return_type(code);
2149        assert!(ty.is_some());
2150        let ty = ty.unwrap();
2151        assert_eq!(ty.name, "string");
2152    }
2153
2154    #[test]
2155    fn test_infer_python_function_return_type() {
2156        let code = "def get_name() -> str: ";
2157        let ty = TreeSitterContextAnalyzer::infer_python_function_return_type(code);
2158        assert!(ty.is_some());
2159        let ty = ty.unwrap();
2160        assert_eq!(ty.name, "str");
2161    }
2162
2163    #[test]
2164    fn test_infer_python_function_return_type_list() {
2165        let code = "def get_items() -> List[int]: ";
2166        let ty = TreeSitterContextAnalyzer::infer_python_function_return_type(code);
2167        assert!(ty.is_some());
2168        let ty = ty.unwrap();
2169        assert_eq!(ty.name, "int");
2170        assert!(ty.is_array);
2171    }
2172
2173    #[test]
2174    fn test_parse_rust_type_simple() {
2175        let ty = TreeSitterContextAnalyzer::parse_rust_type("String");
2176        assert_eq!(ty.name, "String");
2177        assert!(!ty.is_optional);
2178        assert!(!ty.is_array);
2179    }
2180
2181    #[test]
2182    fn test_parse_rust_type_vec() {
2183        let ty = TreeSitterContextAnalyzer::parse_rust_type("Vec<i32>");
2184        assert_eq!(ty.name, "i32");
2185        assert!(ty.is_array);
2186    }
2187
2188    #[test]
2189    fn test_parse_rust_type_option() {
2190        let ty = TreeSitterContextAnalyzer::parse_rust_type("Option<String>");
2191        assert_eq!(ty.name, "String");
2192        assert!(ty.is_optional);
2193    }
2194
2195    #[test]
2196    fn test_parse_typescript_type_array() {
2197        let ty = TreeSitterContextAnalyzer::parse_typescript_type("string[]");
2198        assert_eq!(ty.name, "string");
2199        assert!(ty.is_array);
2200    }
2201
2202    #[test]
2203    fn test_parse_typescript_type_array_generic() {
2204        let ty = TreeSitterContextAnalyzer::parse_typescript_type("Array<number>");
2205        assert_eq!(ty.name, "number");
2206        assert!(ty.is_array);
2207    }
2208
2209    #[test]
2210    fn test_parse_python_type_list() {
2211        let ty = TreeSitterContextAnalyzer::parse_python_type("List[str]");
2212        assert_eq!(ty.name, "str");
2213        assert!(ty.is_array);
2214    }
2215
2216    #[test]
2217    fn test_parse_python_type_optional() {
2218        let ty = TreeSitterContextAnalyzer::parse_python_type("Optional[int]");
2219        assert_eq!(ty.name, "int");
2220        assert!(ty.is_optional);
2221    }
2222
2223    #[test]
2224    fn test_extract_rust_type_annotation() {
2225        let line = "let x: String = value;";
2226        let ty = TreeSitterContextAnalyzer::extract_rust_type_annotation(line);
2227        assert!(ty.is_some());
2228        assert_eq!(ty.unwrap(), "String");
2229    }
2230
2231    #[test]
2232    fn test_extract_rust_type_annotation_complex() {
2233        let line = "let items: Vec<i32> = vec![];";
2234        let ty = TreeSitterContextAnalyzer::extract_rust_type_annotation(line);
2235        assert!(ty.is_some());
2236        assert_eq!(ty.unwrap(), "Vec<i32>");
2237    }
2238
2239    #[test]
2240    fn test_extract_typescript_type_annotation() {
2241        let line = "let x: string = value;";
2242        let ty = TreeSitterContextAnalyzer::extract_typescript_type_annotation(line);
2243        assert!(ty.is_some());
2244        assert_eq!(ty.unwrap(), "string");
2245    }
2246
2247    #[test]
2248    fn test_extract_python_type_annotation() {
2249        let line = "x: str = value";
2250        let ty = TreeSitterContextAnalyzer::extract_python_type_annotation(line);
2251        assert!(ty.is_some());
2252        assert_eq!(ty.unwrap(), "str");
2253    }
2254}