context_creator/core/semantic/
analyzer.rs1use crate::utils::error::ContextCreatorError;
4use std::collections::HashSet;
5use std::path::{Path, PathBuf};
6
7pub type SemanticResult<T> = Result<T, ContextCreatorError>;
9
10#[derive(Debug, Clone)]
12pub struct SemanticContext {
13 pub current_file: PathBuf,
15 pub base_dir: PathBuf,
17 pub current_depth: usize,
19 pub max_depth: usize,
21 pub visited_files: HashSet<PathBuf>,
23}
24
25impl SemanticContext {
26 pub fn new(current_file: PathBuf, base_dir: PathBuf, max_depth: usize) -> Self {
28 Self {
29 current_file,
30 base_dir,
31 current_depth: 0,
32 max_depth,
33 visited_files: HashSet::new(),
34 }
35 }
36
37 pub fn at_max_depth(&self) -> bool {
39 self.current_depth >= self.max_depth
40 }
41
42 pub fn child_context(&self, file: PathBuf) -> Option<Self> {
44 if self.at_max_depth() || self.visited_files.contains(&file) {
45 return None;
46 }
47
48 let mut child = self.clone();
49 child.current_file = file.clone();
50 child.current_depth += 1;
51 child.visited_files.insert(file);
52 Some(child)
53 }
54}
55
56#[derive(Debug, Clone, PartialEq, Eq, Hash)]
58pub struct Import {
59 pub module: String,
61 pub items: Vec<String>,
63 pub is_relative: bool,
65 pub line: usize,
67}
68
69#[derive(Debug, Clone, PartialEq, Eq, Hash)]
71pub struct FunctionCall {
72 pub name: String,
74 pub module: Option<String>,
76 pub line: usize,
78}
79
80#[derive(Debug, Clone, PartialEq, Eq, Hash)]
82pub struct FunctionDefinition {
83 pub name: String,
85 pub is_exported: bool,
87 pub line: usize,
89}
90
91#[derive(Debug, Clone, PartialEq, Eq, Hash)]
93pub struct TypeReference {
94 pub name: String,
96 pub module: Option<String>,
98 pub line: usize,
100 pub definition_path: Option<PathBuf>,
102 pub is_external: bool,
104 pub external_package: Option<String>,
106}
107
108#[derive(Debug, Default, Clone)]
110pub struct AnalysisResult {
111 pub imports: Vec<Import>,
113 pub function_calls: Vec<FunctionCall>,
115 pub type_references: Vec<TypeReference>,
117 pub exported_functions: Vec<FunctionDefinition>,
119 pub errors: Vec<String>,
121}
122
123pub trait LanguageAnalyzer: Send + Sync {
125 fn language_name(&self) -> &'static str;
127
128 fn analyze_file(
130 &self,
131 path: &Path,
132 content: &str,
133 context: &SemanticContext,
134 ) -> SemanticResult<AnalysisResult>;
135
136 fn analyze_imports(
138 &self,
139 content: &str,
140 context: &SemanticContext,
141 ) -> SemanticResult<Vec<Import>> {
142 let result = self.analyze_file(&context.current_file, content, context)?;
144 Ok(result.imports)
145 }
146
147 fn analyze_function_calls(
149 &self,
150 content: &str,
151 context: &SemanticContext,
152 ) -> SemanticResult<Vec<FunctionCall>> {
153 let result = self.analyze_file(&context.current_file, content, context)?;
155 Ok(result.function_calls)
156 }
157
158 fn analyze_type_references(
160 &self,
161 content: &str,
162 context: &SemanticContext,
163 ) -> SemanticResult<Vec<TypeReference>> {
164 let result = self.analyze_file(&context.current_file, content, context)?;
166 Ok(result.type_references)
167 }
168
169 fn can_handle_extension(&self, extension: &str) -> bool;
171
172 fn supported_extensions(&self) -> Vec<&'static str>;
174
175 fn resolve_type_definition(
178 &self,
179 _type_ref: &TypeReference,
180 _context: &SemanticContext,
181 ) -> Option<PathBuf> {
182 None
185 }
186}