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 TypeReference {
83 pub name: String,
85 pub module: Option<String>,
87 pub line: usize,
89 pub definition_path: Option<PathBuf>,
91 pub is_external: bool,
93 pub external_package: Option<String>,
95}
96
97#[derive(Debug, Default)]
99pub struct AnalysisResult {
100 pub imports: Vec<Import>,
102 pub function_calls: Vec<FunctionCall>,
104 pub type_references: Vec<TypeReference>,
106 pub errors: Vec<String>,
108}
109
110pub trait LanguageAnalyzer: Send + Sync {
112 fn language_name(&self) -> &'static str;
114
115 fn analyze_file(
117 &self,
118 path: &Path,
119 content: &str,
120 context: &SemanticContext,
121 ) -> SemanticResult<AnalysisResult>;
122
123 fn analyze_imports(
125 &self,
126 content: &str,
127 context: &SemanticContext,
128 ) -> SemanticResult<Vec<Import>> {
129 let result = self.analyze_file(&context.current_file, content, context)?;
131 Ok(result.imports)
132 }
133
134 fn analyze_function_calls(
136 &self,
137 content: &str,
138 context: &SemanticContext,
139 ) -> SemanticResult<Vec<FunctionCall>> {
140 let result = self.analyze_file(&context.current_file, content, context)?;
142 Ok(result.function_calls)
143 }
144
145 fn analyze_type_references(
147 &self,
148 content: &str,
149 context: &SemanticContext,
150 ) -> SemanticResult<Vec<TypeReference>> {
151 let result = self.analyze_file(&context.current_file, content, context)?;
153 Ok(result.type_references)
154 }
155
156 fn can_handle_extension(&self, extension: &str) -> bool;
158
159 fn supported_extensions(&self) -> Vec<&'static str>;
161
162 fn resolve_type_definition(
165 &self,
166 _type_ref: &TypeReference,
167 _context: &SemanticContext,
168 ) -> Option<PathBuf> {
169 None
172 }
173}