1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Main TDG handler entry point and orchestration
/// Handle TDG analysis command with full MCP tool composition support
///
/// This handler supports three distinct modes:
/// 1. **Single File Mode**: Deep TDG analysis of one specific file
/// 2. **Multi-File Mode**: Process specific file lists for MCP tool chaining
/// 3. **Project Mode**: Analyze entire project with pattern filtering
///
/// # MCP Tool Composition Examples
///
/// ```no_run
/// # async fn example() -> anyhow::Result<()> {
/// use std::path::PathBuf;
/// use pmat::cli::enums::TdgOutputFormat;
/// use pmat::cli::handlers::tdg_handler::handle_analyze_tdg;
///
/// // Example 1: Find high TDG files for targeted refactoring
/// handle_analyze_tdg(
/// PathBuf::from("."),
/// None, // file
/// vec![], // files (empty = project mode)
/// 1.5, // threshold
/// 5, // top_files
/// TdgOutputFormat::Json, // format for parsing
/// false, // include_components
/// None, // output (stdout)
/// false, // critical_only
/// false, // verbose
/// vec![], // include patterns
/// false, // watch
/// ).await?;
///
/// // Example 2: Analyze specific hotspot files from another tool
/// let hotspot_files = vec![
/// PathBuf::from("src/complex_module.rs"),
/// PathBuf::from("src/legacy_code.rs"),
/// ];
///
/// handle_analyze_tdg(
/// PathBuf::from("."),
/// None, // file
/// hotspot_files, // files (MCP composition)
/// 1.0, // lower threshold
/// 0, // show all
/// TdgOutputFormat::Json, // format
/// true, // include_components
/// None, // output
/// false, // critical_only
/// true, // verbose
/// vec![], // include patterns
/// false, // watch
/// ).await?;
/// # Ok(())
/// # }
/// ```ignore
#[allow(clippy::too_many_arguments)]
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "path_exists")]
pub async fn handle_analyze_tdg(
project_path: PathBuf,
file: Option<PathBuf>,
files: Vec<PathBuf>,
threshold: f64,
top_files: usize,
format: TdgOutputFormat,
include_components: bool,
output: Option<PathBuf>,
critical_only: bool,
verbose: bool,
include: Vec<String>,
watch: bool,
) -> Result<()> {
if watch {
eprintln!("⏱️ Watch mode: Monitoring for file changes...");
eprintln!("Press Ctrl+C to stop watching");
// Watch mode continues with regular analysis
}
eprintln!("🔍 Analyzing Technical Debt Gradient...");
// Create TDG calculator
let calculator = TDGCalculator::new();
// Determine analysis mode and generate output
let output_content = if let Some(single_file) = file {
// Single file mode
analyze_single_file(
&calculator,
&project_path,
single_file,
threshold,
format,
include_components,
critical_only,
verbose,
).await?
} else if !files.is_empty() {
// Multiple files mode (MCP tool composition)
analyze_multiple_files(
&calculator,
&project_path,
files,
threshold,
top_files,
format,
include_components,
critical_only,
verbose,
).await?
} else {
// Project mode
analyze_project(
&calculator,
&project_path,
include,
threshold,
top_files,
format,
include_components,
critical_only,
verbose,
).await?
};
// Output results
if let Some(output_path) = output {
tokio::fs::write(&output_path, &output_content).await?;
eprintln!("📝 Results written to {}", output_path.display());
} else {
println!("{}", output_content);
}
eprintln!("✅ TDG analysis complete");
Ok(())
}