1use std::collections::HashMap;
2use std::time::{Duration, Instant};
3
4pub struct CodeAnalyzer {
6 config: AnalyzerConfig,
8 history: AnalysisHistory,
10 baselines: HashMap<String, QualityBaseline>,
12}
13
14#[derive(Debug, Clone)]
16pub struct AnalyzerConfig {
17 pub analysis_depth: AnalysisDepth,
19 pub track_trends: bool,
21 pub max_analysis_time: Duration,
23 pub thresholds: QualityThresholds,
25}
26
27#[derive(Debug, Clone, PartialEq)]
29pub enum AnalysisDepth {
30 Surface,
32 Standard,
34 Deep,
36 Exhaustive,
38}
39
40#[derive(Debug, Clone)]
42pub struct QualityThresholds {
43 pub min_quality_score: f64,
45 pub max_complexity: u32,
47 pub min_coverage: f64,
49 pub max_technical_debt: f64,
51}
52
53#[derive(Debug)]
55struct AnalysisHistory {
56 results: Vec<AnalysisResult>,
58 max_entries: usize,
60}
61
62#[derive(Debug, Clone)]
64pub struct QualityBaseline {
65 pub component: String,
67 pub quality_score: f64,
69 pub complexity: u32,
71 pub performance: BaselinePerformance,
73 pub timestamp: Instant,
75}
76
77#[derive(Debug, Clone)]
79pub struct BaselinePerformance {
80 pub avg_execution_time: Duration,
82 pub memory_per_operation: usize,
84 pub error_rate: f64,
86}
87
88#[derive(Debug, Clone)]
90pub struct AnalysisReport {
91 pub component: String,
93 pub quality_assessment: QualityAssessment,
95 pub metrics: Vec<QualityMetric>,
97 pub issues: Vec<QualityIssue>,
99 pub performance_analysis: PerformanceAnalysis,
101 pub recommendations: Vec<Recommendation>,
103 pub trend_analysis: Option<TrendAnalysis>,
105 pub analysis_duration: Duration,
107}
108
109#[derive(Debug, Clone)]
111pub struct QualityAssessment {
112 pub overall_score: f64,
114 pub grade: QualityGrade,
116 pub confidence: f64,
118 pub strengths: Vec<String>,
120 pub weaknesses: Vec<String>,
122}
123
124#[derive(Debug, Clone, PartialEq)]
126pub enum QualityGrade {
127 A,
129 B,
131 C,
133 D,
135 F,
137}
138
139impl PartialOrd for QualityGrade {
140 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
141 Some(self.cmp(other))
142 }
143}
144
145impl Ord for QualityGrade {
146 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
147 let self_score = match self {
148 QualityGrade::A => 5,
149 QualityGrade::B => 4,
150 QualityGrade::C => 3,
151 QualityGrade::D => 2,
152 QualityGrade::F => 1,
153 };
154 let other_score = match other {
155 QualityGrade::A => 5,
156 QualityGrade::B => 4,
157 QualityGrade::C => 3,
158 QualityGrade::D => 2,
159 QualityGrade::F => 1,
160 };
161 self_score.cmp(&other_score)
162 }
163}
164
165impl Eq for QualityGrade {}
166
167#[derive(Debug, Clone)]
169pub struct QualityMetric {
170 pub name: String,
172 pub category: MetricCategory,
174 pub value: f64,
176 pub target: f64,
178 pub meets_target: bool,
180 pub weight: f64,
182 pub trend: TrendDirection,
184}
185
186#[derive(Debug, Clone, PartialEq)]
188pub enum MetricCategory {
189 Performance,
191 Reliability,
193 Maintainability,
195 Security,
197 Efficiency,
199}
200
201#[derive(Debug, Clone)]
203pub struct QualityIssue {
204 pub id: String,
206 pub title: String,
208 pub description: String,
210 pub severity: IssueSeverity,
212 pub category: IssueCategory,
214 pub location: Option<String>,
216 pub fix_effort: FixEffort,
218 pub impact: ImpactLevel,
220}
221
222#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
224pub enum IssueSeverity {
225 Minor,
227 Moderate,
229 Major,
231 Critical,
233 Blocker,
235}
236
237#[derive(Debug, Clone, PartialEq)]
239pub enum IssueCategory {
240 MemoryManagement,
242 Performance,
244 ThreadSafety,
246 ErrorHandling,
248 CodeStyle,
250 Design,
252}
253
254#[derive(Debug, Clone, PartialEq)]
256pub enum FixEffort {
257 Trivial,
259 Easy,
261 Medium,
263 Hard,
265 VeryHard,
267}
268
269#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
271pub enum ImpactLevel {
272 Minimal,
274 Low,
276 Medium,
278 High,
280 Critical,
282}
283
284#[derive(Debug, Clone)]
286pub struct PerformanceAnalysis {
287 pub score: f64,
289 pub bottlenecks: Vec<PerformanceBottleneck>,
291 pub memory_efficiency: f64,
293 pub cpu_efficiency: f64,
295 pub scalability: ScalabilityAssessment,
297}
298
299#[derive(Debug, Clone)]
301pub struct PerformanceBottleneck {
302 pub location: String,
304 pub bottleneck_type: BottleneckType,
306 pub severity: f64,
308 pub description: String,
310 pub optimization: String,
312}
313
314#[derive(Debug, Clone, PartialEq)]
316pub enum BottleneckType {
317 CpuBound,
319 MemoryBound,
321 IoBound,
323 LockContention,
325 CacheMiss,
327 AlgorithmInefficiency,
329}
330
331#[derive(Debug, Clone)]
333pub struct ScalabilityAssessment {
334 pub score: f64,
336 pub scaling_behavior: ScalingBehavior,
338 pub resource_scaling: ResourceScaling,
340 pub limitations: Vec<String>,
342}
343
344#[derive(Debug, Clone, PartialEq)]
346pub enum ScalingBehavior {
347 Constant,
349 Linear,
351 Logarithmic,
353 Quadratic,
355 Exponential,
357}
358
359#[derive(Debug, Clone)]
361pub struct ResourceScaling {
362 pub memory_factor: f64,
364 pub cpu_factor: f64,
366 pub network_factor: f64,
368}
369
370#[derive(Debug, Clone)]
372pub struct Recommendation {
373 pub title: String,
375 pub description: String,
377 pub priority: RecommendationPriority,
379 pub impact: ImpactLevel,
381 pub effort: FixEffort,
383 pub related_issues: Vec<String>,
385}
386
387#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
389pub enum RecommendationPriority {
390 Low,
392 Medium,
394 High,
396 Critical,
398}
399
400#[derive(Debug, Clone)]
402pub struct TrendAnalysis {
403 pub quality_trend: TrendDirection,
405 pub performance_trend: TrendDirection,
407 pub complexity_trend: TrendDirection,
409 pub confidence: f64,
411 pub time_period: Duration,
413}
414
415#[derive(Debug, Clone, PartialEq)]
417pub enum TrendDirection {
418 Improving,
420 Stable,
422 Declining,
424 Unknown,
426}
427
428#[derive(Debug, Clone)]
430struct AnalysisResult {
431 component: String,
432 quality_score: f64,
433}
434
435impl CodeAnalyzer {
436 pub fn new() -> Self {
438 Self {
439 config: AnalyzerConfig::default(),
440 history: AnalysisHistory {
441 results: Vec::new(),
442 max_entries: 100,
443 },
444 baselines: HashMap::new(),
445 }
446 }
447
448 pub fn with_config(config: AnalyzerConfig) -> Self {
450 Self {
451 config,
452 history: AnalysisHistory {
453 results: Vec::new(),
454 max_entries: 100,
455 },
456 baselines: HashMap::new(),
457 }
458 }
459
460 pub fn set_baseline(&mut self, component: &str, baseline: QualityBaseline) {
462 self.baselines.insert(component.to_string(), baseline);
463 }
464
465 pub fn analyze_quality(
467 &mut self,
468 component: &str,
469 context: &AnalysisContext,
470 ) -> AnalysisReport {
471 let start_time = Instant::now();
472
473 let metrics = self.calculate_quality_metrics(context);
475 let issues = self.detect_quality_issues(context);
476 let performance_analysis = self.analyze_performance(context);
477 let quality_assessment = self.assess_overall_quality(&metrics, &issues);
478 let recommendations = self.generate_recommendations(&issues, &performance_analysis);
479 let trend_analysis = if self.config.track_trends {
480 Some(self.analyze_trends(component))
481 } else {
482 None
483 };
484
485 let analysis_duration = start_time.elapsed();
486
487 self.store_analysis_result(component, &quality_assessment, &metrics);
489
490 AnalysisReport {
491 component: component.to_string(),
492 quality_assessment,
493 metrics,
494 issues,
495 performance_analysis,
496 recommendations,
497 trend_analysis,
498 analysis_duration,
499 }
500 }
501
502 fn calculate_quality_metrics(&self, context: &AnalysisContext) -> Vec<QualityMetric> {
503 vec![
504 QualityMetric {
506 name: "allocation_efficiency".to_string(),
507 category: MetricCategory::Performance,
508 value: context.performance_data.allocation_efficiency,
509 target: 0.95,
510 meets_target: context.performance_data.allocation_efficiency >= 0.95,
511 weight: 0.3,
512 trend: TrendDirection::Unknown,
513 },
514 QualityMetric {
516 name: "error_rate".to_string(),
517 category: MetricCategory::Reliability,
518 value: context.reliability_data.error_rate,
519 target: 0.01, meets_target: context.reliability_data.error_rate <= 0.01,
521 weight: 0.25,
522 trend: TrendDirection::Unknown,
523 },
524 QualityMetric {
526 name: "memory_efficiency".to_string(),
527 category: MetricCategory::Efficiency,
528 value: context.memory_data.efficiency_ratio,
529 target: 0.9,
530 meets_target: context.memory_data.efficiency_ratio >= 0.9,
531 weight: 0.2,
532 trend: TrendDirection::Unknown,
533 },
534 ]
535 }
536
537 fn detect_quality_issues(&self, context: &AnalysisContext) -> Vec<QualityIssue> {
538 let mut issues = Vec::new();
539
540 if context.memory_data.growth_rate > 1024.0 * 1024.0 {
542 issues.push(QualityIssue {
544 id: "memory_leak_detected".to_string(),
545 title: "Potential Memory Leak".to_string(),
546 description: format!(
547 "High memory growth rate: {:.2}MB/sec",
548 context.memory_data.growth_rate / (1024.0 * 1024.0)
549 ),
550 severity: IssueSeverity::Major,
551 category: IssueCategory::MemoryManagement,
552 location: Some("memory_tracking".to_string()),
553 fix_effort: FixEffort::Medium,
554 impact: ImpactLevel::High,
555 });
556 }
557
558 if context.performance_data.avg_latency > Duration::from_micros(100) {
560 issues.push(QualityIssue {
561 id: "high_latency".to_string(),
562 title: "High Operation Latency".to_string(),
563 description: format!(
564 "Average latency {:.2}µs exceeds threshold",
565 context.performance_data.avg_latency.as_micros()
566 ),
567 severity: IssueSeverity::Moderate,
568 category: IssueCategory::Performance,
569 location: Some("allocation_tracking".to_string()),
570 fix_effort: FixEffort::Easy,
571 impact: ImpactLevel::Medium,
572 });
573 }
574
575 issues
576 }
577
578 fn analyze_performance(&self, context: &AnalysisContext) -> PerformanceAnalysis {
579 let bottlenecks = self.identify_bottlenecks(context);
580 let memory_efficiency = context.memory_data.efficiency_ratio;
581 let cpu_efficiency = 1.0 - (context.performance_data.cpu_usage / 100.0);
582
583 let scalability = ScalabilityAssessment {
584 score: 0.8, scaling_behavior: ScalingBehavior::Linear,
586 resource_scaling: ResourceScaling {
587 memory_factor: 1.2,
588 cpu_factor: 1.1,
589 network_factor: 1.0,
590 },
591 limitations: vec!["Memory bandwidth may become bottleneck at scale".to_string()],
592 };
593
594 let score = (memory_efficiency + cpu_efficiency + scalability.score) / 3.0;
595
596 PerformanceAnalysis {
597 score,
598 bottlenecks,
599 memory_efficiency,
600 cpu_efficiency,
601 scalability,
602 }
603 }
604
605 fn identify_bottlenecks(&self, context: &AnalysisContext) -> Vec<PerformanceBottleneck> {
606 let mut bottlenecks = Vec::new();
607
608 if context.performance_data.cpu_usage > 80.0 {
609 bottlenecks.push(PerformanceBottleneck {
610 location: "allocation_tracking".to_string(),
611 bottleneck_type: BottleneckType::CpuBound,
612 severity: context.performance_data.cpu_usage / 100.0,
613 description: "High CPU usage in allocation tracking".to_string(),
614 optimization: "Consider optimizing hot paths or using faster data structures"
615 .to_string(),
616 });
617 }
618
619 if context.memory_data.fragmentation_ratio > 0.3 {
620 bottlenecks.push(PerformanceBottleneck {
621 location: "memory_management".to_string(),
622 bottleneck_type: BottleneckType::MemoryBound,
623 severity: context.memory_data.fragmentation_ratio,
624 description: "High memory fragmentation".to_string(),
625 optimization: "Implement memory compaction or use memory pools".to_string(),
626 });
627 }
628
629 bottlenecks
630 }
631
632 fn assess_overall_quality(
633 &self,
634 metrics: &[QualityMetric],
635 issues: &[QualityIssue],
636 ) -> QualityAssessment {
637 let weighted_score: f64 = metrics
639 .iter()
640 .map(|m| {
641 if m.meets_target {
642 m.weight
643 } else {
644 m.weight * (m.value / m.target)
645 }
646 })
647 .sum();
648
649 let total_weight: f64 = metrics.iter().map(|m| m.weight).sum();
650 let overall_score = if total_weight > 0.0 {
651 weighted_score / total_weight
652 } else {
653 0.0
654 };
655
656 let critical_penalty = issues
658 .iter()
659 .filter(|i| i.severity >= IssueSeverity::Critical)
660 .count() as f64
661 * 0.1;
662
663 let adjusted_score = (overall_score - critical_penalty).max(0.0);
664
665 let grade = match adjusted_score {
666 s if s >= 0.9 => QualityGrade::A,
667 s if s >= 0.8 => QualityGrade::B,
668 s if s >= 0.7 => QualityGrade::C,
669 s if s >= 0.6 => QualityGrade::D,
670 _ => QualityGrade::F,
671 };
672
673 let strengths = metrics
674 .iter()
675 .filter(|m| m.meets_target && m.value > m.target * 1.1)
676 .map(|m| format!("Excellent {}", m.name))
677 .collect();
678
679 let weaknesses = issues
680 .iter()
681 .filter(|i| i.severity >= IssueSeverity::Major)
682 .map(|i| i.title.clone())
683 .collect();
684
685 QualityAssessment {
686 overall_score: adjusted_score,
687 grade,
688 confidence: 0.85, strengths,
690 weaknesses,
691 }
692 }
693
694 fn generate_recommendations(
695 &self,
696 issues: &[QualityIssue],
697 performance: &PerformanceAnalysis,
698 ) -> Vec<Recommendation> {
699 let mut recommendations = Vec::new();
700
701 for issue in issues {
703 if issue.severity >= IssueSeverity::Major {
704 recommendations.push(Recommendation {
705 title: format!("Fix {}", issue.title),
706 description: format!("Address {} to improve quality", issue.description),
707 priority: match issue.severity {
708 IssueSeverity::Critical | IssueSeverity::Blocker => {
709 RecommendationPriority::Critical
710 }
711 IssueSeverity::Major => RecommendationPriority::High,
712 _ => RecommendationPriority::Medium,
713 },
714 impact: issue.impact.clone(),
715 effort: issue.fix_effort.clone(),
716 related_issues: vec![issue.id.clone()],
717 });
718 }
719 }
720
721 if performance.score < 0.8 {
723 recommendations.push(Recommendation {
724 title: "Improve Performance".to_string(),
725 description: "Overall performance score is below target".to_string(),
726 priority: RecommendationPriority::High,
727 impact: ImpactLevel::High,
728 effort: FixEffort::Medium,
729 related_issues: vec![],
730 });
731 }
732
733 recommendations
734 }
735
736 fn analyze_trends(&self, component: &str) -> TrendAnalysis {
737 let recent_results: Vec<_> = self
738 .history
739 .results
740 .iter()
741 .filter(|r| r.component == component)
742 .rev()
743 .take(10)
744 .collect();
745
746 if recent_results.len() < 3 {
747 return TrendAnalysis {
748 quality_trend: TrendDirection::Unknown,
749 performance_trend: TrendDirection::Unknown,
750 complexity_trend: TrendDirection::Unknown,
751 confidence: 0.0,
752 time_period: Duration::ZERO,
753 };
754 }
755
756 let scores: Vec<f64> = recent_results.iter().map(|r| r.quality_score).collect();
758 let quality_trend = if scores.first() > scores.last() {
759 TrendDirection::Improving
760 } else if scores.first() < scores.last() {
761 TrendDirection::Declining
762 } else {
763 TrendDirection::Stable
764 };
765
766 TrendAnalysis {
767 quality_trend,
768 performance_trend: TrendDirection::Stable,
769 complexity_trend: TrendDirection::Stable,
770 confidence: 0.7,
771 time_period: Duration::from_secs(3600), }
773 }
774
775 fn store_analysis_result(
776 &mut self,
777 component: &str,
778 assessment: &QualityAssessment,
779 _metrics: &[QualityMetric],
780 ) {
781 let result = AnalysisResult {
782 component: component.to_string(),
783 quality_score: assessment.overall_score,
784 };
785
786 self.history.results.push(result);
787
788 if self.history.results.len() > self.history.max_entries {
790 self.history
791 .results
792 .drain(0..self.history.results.len() - self.history.max_entries);
793 }
794 }
795}
796
797#[derive(Debug)]
799pub struct AnalysisContext {
800 pub performance_data: PerformanceData,
802 pub memory_data: MemoryData,
804 pub reliability_data: ReliabilityData,
806}
807
808#[derive(Debug)]
810pub struct PerformanceData {
811 pub avg_latency: Duration,
813 pub cpu_usage: f64,
815 pub allocation_efficiency: f64,
817 pub throughput: f64,
819}
820
821#[derive(Debug)]
823pub struct MemoryData {
824 pub current_usage: usize,
826 pub growth_rate: f64,
828 pub efficiency_ratio: f64,
830 pub fragmentation_ratio: f64,
832}
833
834#[derive(Debug)]
836pub struct ReliabilityData {
837 pub error_rate: f64,
839 pub success_rate: f64,
841 pub mtbf: Duration,
843}
844
845impl Default for AnalyzerConfig {
846 fn default() -> Self {
847 Self {
848 analysis_depth: AnalysisDepth::Standard,
849 track_trends: true,
850 max_analysis_time: Duration::from_secs(30),
851 thresholds: QualityThresholds::default(),
852 }
853 }
854}
855
856impl Default for QualityThresholds {
857 fn default() -> Self {
858 Self {
859 min_quality_score: 0.8,
860 max_complexity: 10,
861 min_coverage: 0.8,
862 max_technical_debt: 0.2,
863 }
864 }
865}
866
867impl Default for CodeAnalyzer {
868 fn default() -> Self {
869 Self::new()
870 }
871}
872
873#[cfg(test)]
874mod tests {
875 use super::*;
876
877 #[test]
878 fn test_code_analyzer_creation() {
879 let analyzer = CodeAnalyzer::new();
880 assert_eq!(analyzer.config.analysis_depth, AnalysisDepth::Standard);
881 assert!(analyzer.config.track_trends);
882 }
883
884 #[test]
885 fn test_quality_assessment() {
886 let analyzer = CodeAnalyzer::new();
887
888 let metrics = vec![QualityMetric {
889 name: "test_metric".to_string(),
890 category: MetricCategory::Performance,
891 value: 0.9,
892 target: 0.8,
893 meets_target: true,
894 weight: 1.0,
895 trend: TrendDirection::Stable,
896 }];
897
898 let issues = vec![];
899 let assessment = analyzer.assess_overall_quality(&metrics, &issues);
900
901 assert!(assessment.overall_score >= 0.8);
902 assert_eq!(assessment.grade, QualityGrade::A);
903 }
904
905 #[test]
906 fn test_quality_grades() {
907 assert!(QualityGrade::A > QualityGrade::B);
908 assert!(QualityGrade::B > QualityGrade::C);
909 assert!(QualityGrade::F < QualityGrade::D);
910 }
911}