Skip to main content

aster/map/
enhanced_generator.rs

1//! 增强版本体生成器
2//!
3//! 生成带有视图、引用关系和语义信息的增强版代码蓝图
4
5use 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
16/// 增强版本体生成器
17pub 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    /// 生成增强版代码蓝图
31    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            // 收集导出符号
101            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            // 构建导入
161            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
281/// 便捷函数:生成增强版蓝图
282pub 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
289/// 生成并保存增强版蓝图
290pub 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}