1use std::collections::HashMap;
6use std::path::Path;
7
8use super::analyzer::CodeMapAnalyzer;
9use super::call_graph_builder::build_call_graph;
10use super::dependency_analyzer::analyze_dependencies;
11use super::layer_classifier::LayerClassifier;
12use super::types::{CallGraph, DependencyGraph, FileStat, GenerateOptions, ModuleNode};
13use super::types_enhanced::*;
14use super::view_builder::ViewBuilder;
15
16pub struct EnhancedOntologyGenerator {
18 root_path: String,
19 options: EnhancedGenerateOptions,
20}
21
22impl EnhancedOntologyGenerator {
23 pub fn new(root_path: impl AsRef<Path>, options: Option<EnhancedGenerateOptions>) -> Self {
24 Self {
25 root_path: root_path.as_ref().to_string_lossy().to_string(),
26 options: options.unwrap_or_default(),
27 }
28 }
29
30 pub fn generate(&self) -> EnhancedCodeBlueprint {
32 let gen_opts = GenerateOptions {
33 include: self.options.include.clone(),
34 exclude: self.options.exclude.clone(),
35 concurrency: self.options.concurrency,
36 ..Default::default()
37 };
38
39 let analyzer = CodeMapAnalyzer::from_options(&self.root_path, &gen_opts);
40 let modules = analyzer.analyze_files(None);
41
42 let call_graph = build_call_graph(&modules);
43 let dep_graph = analyze_dependencies(&modules);
44
45 let view_builder = ViewBuilder::new();
46 let views = view_builder.build_views(&modules);
47
48 let (enhanced_modules, symbols) = self.build_enhanced_modules(&modules);
49 let references = self.build_references(&modules, &call_graph, &dep_graph);
50 let statistics = self.compute_statistics(&modules, &symbols, &references);
51
52 EnhancedCodeBlueprint {
53 format: "enhanced".to_string(),
54 meta: BlueprintMeta {
55 version: "2.0.0".to_string(),
56 generated_at: chrono::Utc::now().to_rfc3339(),
57 generator_version: env!("CARGO_PKG_VERSION").to_string(),
58 semantic_version: None,
59 },
60 project: EnhancedProjectInfo {
61 name: Path::new(&self.root_path)
62 .file_name()
63 .map(|n| n.to_string_lossy().to_string())
64 .unwrap_or_default(),
65 root_path: self.root_path.clone(),
66 semantic: None,
67 languages: self.collect_languages(&modules),
68 technologies: None,
69 },
70 views,
71 modules: enhanced_modules,
72 symbols,
73 references,
74 statistics,
75 }
76 }
77
78 fn collect_languages(&self, modules: &[ModuleNode]) -> Vec<String> {
79 let mut langs: std::collections::HashSet<String> = std::collections::HashSet::new();
80 for m in modules {
81 langs.insert(m.language.clone());
82 }
83 langs.into_iter().collect()
84 }
85
86 fn build_enhanced_modules(
87 &self,
88 modules: &[ModuleNode],
89 ) -> (
90 HashMap<String, EnhancedModule>,
91 HashMap<String, SymbolEntry>,
92 ) {
93 let mut enhanced = HashMap::new();
94 let mut symbols = HashMap::new();
95 let classifier = LayerClassifier::new();
96
97 for module in modules {
98 let classification = classifier.classify(module);
99
100 let mut exports = Vec::new();
102 for func in &module.functions {
103 if func.is_exported {
104 exports.push(func.id.clone());
105 symbols.insert(
106 func.id.clone(),
107 SymbolEntry {
108 id: func.id.clone(),
109 name: func.name.clone(),
110 kind: SymbolKind::Function,
111 module_id: module.id.clone(),
112 location: func.location.clone(),
113 signature: Some(func.signature.clone()),
114 semantic: None,
115 children: None,
116 parent: None,
117 },
118 );
119 }
120 }
121
122 for cls in &module.classes {
123 if cls.is_exported {
124 exports.push(cls.id.clone());
125 let children: Vec<String> = cls.methods.iter().map(|m| m.id.clone()).collect();
126 symbols.insert(
127 cls.id.clone(),
128 SymbolEntry {
129 id: cls.id.clone(),
130 name: cls.name.clone(),
131 kind: SymbolKind::Class,
132 module_id: module.id.clone(),
133 location: cls.location.clone(),
134 signature: None,
135 semantic: None,
136 children: Some(children),
137 parent: None,
138 },
139 );
140
141 for method in &cls.methods {
142 symbols.insert(
143 method.id.clone(),
144 SymbolEntry {
145 id: method.id.clone(),
146 name: method.name.clone(),
147 kind: SymbolKind::Method,
148 module_id: module.id.clone(),
149 location: method.location.clone(),
150 signature: Some(method.signature.clone()),
151 semantic: None,
152 children: None,
153 parent: Some(cls.id.clone()),
154 },
155 );
156 }
157 }
158 }
159
160 let imports: Vec<ModuleImport> = module
162 .imports
163 .iter()
164 .map(|imp| ModuleImport {
165 source: imp.source.clone(),
166 symbols: imp.symbols.clone(),
167 is_external: !imp.source.starts_with('.') && !imp.source.starts_with('/'),
168 is_type_only: Some(imp.symbols.iter().any(|s| s.starts_with("type "))),
169 })
170 .collect();
171
172 enhanced.insert(
173 module.id.clone(),
174 EnhancedModule {
175 id: module.id.clone(),
176 name: module.name.clone(),
177 path: module.path.clone(),
178 language: module.language.clone(),
179 lines: module.lines,
180 size: module.size,
181 semantic: Some(SemanticInfo {
182 description: String::new(),
183 responsibility: String::new(),
184 business_domain: None,
185 architecture_layer: classification.layer,
186 tags: Vec::new(),
187 confidence: classification.confidence,
188 generated_at: chrono::Utc::now().to_rfc3339(),
189 }),
190 exports,
191 imports,
192 },
193 );
194 }
195
196 (enhanced, symbols)
197 }
198
199 fn build_references(
200 &self,
201 _modules: &[ModuleNode],
202 call_graph: &CallGraph,
203 dep_graph: &DependencyGraph,
204 ) -> References {
205 let module_deps: Vec<ModuleDependency> = dep_graph
206 .edges
207 .iter()
208 .map(|e| ModuleDependency {
209 source: e.source.clone(),
210 target: e.target.clone(),
211 dep_type: format!("{:?}", e.edge_type).to_lowercase(),
212 symbols: e.symbols.clone(),
213 is_type_only: e.is_type_only,
214 })
215 .collect();
216
217 let symbol_calls: Vec<SymbolCall> = call_graph
218 .edges
219 .iter()
220 .map(|e| SymbolCall {
221 caller: e.source.clone(),
222 callee: e.target.clone(),
223 call_type: format!("{:?}", e.edge_type).to_lowercase(),
224 locations: e.locations.clone(),
225 })
226 .collect();
227
228 References {
229 module_deps,
230 symbol_calls,
231 type_refs: Vec::new(),
232 }
233 }
234
235 fn compute_statistics(
236 &self,
237 modules: &[ModuleNode],
238 symbols: &HashMap<String, SymbolEntry>,
239 references: &References,
240 ) -> EnhancedStatistics {
241 let mut layer_dist: HashMap<String, usize> = HashMap::new();
242 let mut lang_breakdown: HashMap<String, usize> = HashMap::new();
243 let classifier = LayerClassifier::new();
244
245 for module in modules {
246 let result = classifier.classify(module);
247 let layer_name = format!("{:?}", result.layer).to_lowercase();
248 *layer_dist.entry(layer_name).or_insert(0) += 1;
249 *lang_breakdown.entry(module.language.clone()).or_insert(0) += 1;
250 }
251
252 let mut largest: Vec<_> = modules
253 .iter()
254 .map(|m| FileStat {
255 path: m.id.clone(),
256 lines: m.lines,
257 size: m.size,
258 })
259 .collect();
260 largest.sort_by(|a, b| b.lines.cmp(&a.lines));
261
262 EnhancedStatistics {
263 total_modules: modules.len(),
264 total_symbols: symbols.len(),
265 total_lines: modules.iter().map(|m| m.lines).sum(),
266 semantic_coverage: SemanticCoverage::default(),
267 reference_stats: ReferenceStats {
268 total_module_deps: references.module_deps.len(),
269 total_symbol_calls: references.symbol_calls.len(),
270 total_type_refs: references.type_refs.len(),
271 },
272 layer_distribution: layer_dist,
273 language_breakdown: lang_breakdown,
274 largest_files: largest.into_iter().take(10).collect(),
275 most_called_symbols: Vec::new(),
276 most_imported_modules: Vec::new(),
277 }
278 }
279}
280
281pub fn generate_enhanced_blueprint(
283 root_path: impl AsRef<Path>,
284 options: Option<EnhancedGenerateOptions>,
285) -> EnhancedCodeBlueprint {
286 EnhancedOntologyGenerator::new(root_path, options).generate()
287}
288
289pub fn generate_and_save_enhanced_blueprint(
291 root_path: impl AsRef<Path>,
292 output_path: impl AsRef<Path>,
293 options: Option<EnhancedGenerateOptions>,
294) -> std::io::Result<EnhancedCodeBlueprint> {
295 let blueprint = generate_enhanced_blueprint(root_path, options);
296 let json = serde_json::to_string_pretty(&blueprint)?;
297 std::fs::write(output_path, json)?;
298 Ok(blueprint)
299}