use debtmap::core::FunctionMetrics;
use debtmap::extraction_patterns::{
AccumulationOp, AnalysisContext, ExtractablePattern, ExtractionAnalyzer, ExtractionSuggestion,
GuardCheck, MatchedPattern, ReturnType, TransformStage, UnifiedExtractionAnalyzer,
VerbosityLevel,
};
use std::path::PathBuf;
#[test]
fn test_unified_extraction_analyzer_creation() {
let analyzer = UnifiedExtractionAnalyzer::new();
assert!(analyzer
.generate_recommendation(&create_test_suggestion(), VerbosityLevel::Summary)
.contains("confidence"));
}
#[test]
fn test_extraction_recommendation_generation() {
let analyzer = UnifiedExtractionAnalyzer::new();
let suggestion = create_test_suggestion();
let summary = analyzer.generate_recommendation(&suggestion, VerbosityLevel::Summary);
assert!(summary.contains("calculate_sum"));
assert!(summary.contains("85%"));
assert!(summary.contains("lines 10-20"));
let normal = analyzer.generate_recommendation(&suggestion, VerbosityLevel::Normal);
assert!(normal.contains("Parameters:"));
assert!(normal.contains("Returns:"));
assert!(normal.contains("Complexity reduction:"));
let detailed = analyzer.generate_recommendation(&suggestion, VerbosityLevel::Detailed);
assert!(detailed.contains("Example transformation:"));
assert!(detailed.contains("Extracted function complexity:"));
}
#[test]
fn test_confidence_scoring_high() {
let pattern = ExtractablePattern::AccumulationLoop {
iterator_binding: "item".to_string(),
accumulator: "sum".to_string(),
operation: AccumulationOp::Sum,
filter: None,
transform: None,
start_line: 10,
end_line: 20,
};
let context = AnalysisContext {
function_name: "test_func".to_string(),
file_path: "test.rs".to_string(),
language: "rust".to_string(),
complexity_before: 5,
has_side_effects: false,
data_dependencies: vec![],
};
let matched = MatchedPattern {
pattern,
confidence: 0.0,
context: context.clone(),
};
use debtmap::extraction_patterns::confidence::ConfidenceScorer;
let score = ConfidenceScorer::score_pattern(&matched, &context);
assert!(
score > 0.8,
"Accumulation loop without side effects should have high confidence"
);
}
#[test]
fn test_confidence_scoring_with_side_effects() {
let pattern = ExtractablePattern::TransformationPipeline {
stages: vec![TransformStage {
operation: "map".to_string(),
input: "item".to_string(),
output: "transformed".to_string(),
}],
input_binding: "data".to_string(),
output_type: "Vec<T>".to_string(),
start_line: 10,
end_line: 20,
};
let context_no_side_effects = AnalysisContext {
function_name: "test_func".to_string(),
file_path: "test.rs".to_string(),
language: "rust".to_string(),
complexity_before: 5,
has_side_effects: false,
data_dependencies: vec![],
};
let context_with_side_effects = AnalysisContext {
has_side_effects: true,
..context_no_side_effects.clone()
};
let matched_no_side = MatchedPattern {
pattern: pattern.clone(),
confidence: 0.0,
context: context_no_side_effects.clone(),
};
let matched_with_side = MatchedPattern {
pattern,
confidence: 0.0,
context: context_with_side_effects.clone(),
};
use debtmap::extraction_patterns::confidence::ConfidenceScorer;
let score_no_side = ConfidenceScorer::score_pattern(&matched_no_side, &context_no_side_effects);
let score_with_side =
ConfidenceScorer::score_pattern(&matched_with_side, &context_with_side_effects);
assert!(
score_no_side > score_with_side,
"Functions with side effects should have lower confidence"
);
}
#[test]
fn test_function_name_inference() {
use debtmap::extraction_patterns::naming::FunctionNameInferrer;
let acc_pattern = ExtractablePattern::AccumulationLoop {
iterator_binding: "item".to_string(),
accumulator: "total".to_string(),
operation: AccumulationOp::Sum,
filter: None,
transform: None,
start_line: 1,
end_line: 5,
};
let rust_name = FunctionNameInferrer::infer_name(&acc_pattern, "rust");
assert!(rust_name.contains("sum"));
assert_eq!(rust_name, "sum_item");
let guard_pattern = ExtractablePattern::GuardChainSequence {
checks: vec![GuardCheck {
condition: "value > 0".to_string(),
return_value: Some("Error".to_string()),
line: 1,
}],
early_return: ReturnType {
type_name: "Result<()>".to_string(),
is_early_return: true,
},
start_line: 1,
end_line: 5,
};
let guard_name = FunctionNameInferrer::infer_name(&guard_pattern, "rust");
assert!(guard_name.contains("validate"));
assert_eq!(guard_name, "validate_precondition");
let js_name = FunctionNameInferrer::infer_name(&guard_pattern, "javascript");
assert_eq!(js_name, "validatePrecondition");
}
#[test]
fn test_complexity_impact_calculation() {
let suggestion = create_test_suggestion();
assert_eq!(suggestion.complexity_reduction.current_cyclomatic, 15);
assert_eq!(suggestion.complexity_reduction.predicted_cyclomatic, 12);
assert_eq!(
suggestion
.complexity_reduction
.extracted_function_complexity,
3
);
}
#[test]
fn test_pattern_matching_for_different_languages() {
let analyzer = UnifiedExtractionAnalyzer::new();
let rust_func = FunctionMetrics {
name: "test_rust".to_string(),
file: PathBuf::from("test.rs"),
line: 10,
cyclomatic: 10,
cognitive: 15,
nesting: 2,
length: 50,
is_test: false,
visibility: Some("pub".to_string()),
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
purity_reason: None,
call_dependencies: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
};
let python_func = FunctionMetrics {
name: "test_python".to_string(),
file: PathBuf::from("test.py"),
line: 10,
cyclomatic: 10,
cognitive: 15,
nesting: 2,
length: 50,
is_test: false,
visibility: None,
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
purity_reason: None,
call_dependencies: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
};
let js_func = FunctionMetrics {
name: "testJavaScript".to_string(),
file: PathBuf::from("test.js"),
line: 10,
cyclomatic: 10,
cognitive: 15,
nesting: 2,
length: 50,
is_test: false,
visibility: None,
is_trait_method: false,
in_test_module: false,
entropy_score: None,
is_pure: None,
purity_confidence: None,
purity_reason: None,
call_dependencies: None,
detected_patterns: None,
upstream_callers: None,
downstream_callees: None,
mapping_pattern_result: None,
adjusted_complexity: None,
composition_metrics: None,
language_specific: None,
purity_level: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
};
let file_metrics = debtmap::core::FileMetrics {
path: std::path::PathBuf::from("test.rs"),
language: debtmap::core::Language::Rust,
complexity: debtmap::core::ComplexityMetrics::default(),
debt_items: vec![],
dependencies: vec![],
duplications: vec![],
total_lines: 0,
module_scope: None,
classes: None,
};
let rust_suggestions = analyzer.analyze_function(&rust_func, &file_metrics, None);
let python_suggestions = analyzer.analyze_function(&python_func, &file_metrics, None);
let js_suggestions = analyzer.analyze_function(&js_func, &file_metrics, None);
assert_eq!(rust_suggestions.len(), 0);
assert_eq!(python_suggestions.len(), 0);
assert_eq!(js_suggestions.len(), 0);
}
fn create_test_suggestion() -> ExtractionSuggestion {
use debtmap::extraction_patterns::{ComplexityImpact, Parameter};
ExtractionSuggestion {
pattern_type: ExtractablePattern::AccumulationLoop {
iterator_binding: "item".to_string(),
accumulator: "sum".to_string(),
operation: AccumulationOp::Sum,
filter: None,
transform: None,
start_line: 10,
end_line: 20,
},
start_line: 10,
end_line: 20,
suggested_name: "calculate_sum".to_string(),
confidence: 0.85,
parameters: vec![Parameter {
name: "items".to_string(),
type_hint: "Vec<i32>".to_string(),
is_mutable: false,
}],
return_type: "i32".to_string(),
complexity_reduction: ComplexityImpact {
current_cyclomatic: 15,
predicted_cyclomatic: 12,
current_cognitive: 20,
predicted_cognitive: 15,
extracted_function_complexity: 3,
},
example_transformation: "// Example transformation".to_string(),
}
}