vtcode_core/code/code_completion/context/
analyzer.rs1use super::CompletionContext;
2
3pub struct ContextAnalyzer;
5
6impl ContextAnalyzer {
7 pub fn new() -> Self {
8 Self
9 }
10
11 pub fn analyze(&mut self, source: &str, line: usize, column: usize) -> CompletionContext {
13 let language = self.detect_language(source);
14 let prefix = self.extract_prefix(source, line, column);
15
16 let mut context = CompletionContext::new(line, column, prefix, language);
17 context.scope = Vec::new();
18 context.imports = self.extract_imports(source);
19 context.recent_symbols = Vec::new();
20
21 context
22 }
23
24 fn detect_language(&self, source: &str) -> String {
25 let first_lines: String = source.lines().take(20).collect::<Vec<_>>().join("\n");
26 if first_lines.contains("use std::") || first_lines.contains("fn ") && first_lines.contains("->") {
27 "rust".into()
28 } else if first_lines.contains("import ") && first_lines.contains("from ") || first_lines.contains("def ") {
29 "python".into()
30 } else if first_lines.contains("interface ")
31 || first_lines.contains(": string")
32 || first_lines.contains(": number")
33 {
34 "typescript".into()
35 } else if first_lines.contains("function ")
36 || first_lines.contains("const ")
37 || first_lines.contains("require(")
38 {
39 "javascript".into()
40 } else if first_lines.contains("package ") && first_lines.contains("func ") {
41 "go".into()
42 } else if first_lines.contains("public class ") || first_lines.contains("import java.") {
43 "java".into()
44 } else if first_lines.starts_with("#!/bin/bash") || first_lines.starts_with("#!/bin/sh") {
45 "bash".into()
46 } else {
47 "rust".into()
48 }
49 }
50
51 fn extract_prefix(&self, source: &str, line: usize, column: usize) -> String {
52 let lines: Vec<&str> = source.lines().collect();
53 if line < lines.len() && column <= lines[line].len() {
54 lines[line][..column].into()
55 } else {
56 String::new()
57 }
58 }
59
60 fn extract_imports(&self, source: &str) -> Vec<String> {
62 source
63 .lines()
64 .filter(|line| {
65 let trimmed = line.trim();
66 trimmed.starts_with("use ")
67 || trimmed.starts_with("import ")
68 || trimmed.starts_with("from ")
69 || trimmed.starts_with("require(")
70 || trimmed.starts_with("const ") && trimmed.contains("require(")
71 })
72 .map(|s| s.to_string())
73 .collect()
74 }
75}
76
77impl Default for ContextAnalyzer {
78 fn default() -> Self {
79 Self::new()
80 }
81}