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
//! Uncached complexity analysis and cache key computation.
use Path;
use FileComplexityMetrics;
/// Cache key computation for complexity metrics
/// Computes a cache key for complexity analysis based on file path and content
///
/// # Examples
///
/// ```rust,no_run
/// use pmat::services::complexity::compute_complexity_cache_key;
/// use std::path::Path;
///
/// let path = Path::new("src/main.rs");
/// let content = b"fn main() { println!(\"Hello\"); }";
///
/// let key = compute_complexity_cache_key(path, content);
/// assert!(key.starts_with("cx:"));
/// assert!(key.len() > 10);
/// ```
/// Analyze file complexity WITHOUT using TDG cache (Issue #67 fix)
///
/// This function performs fresh analysis and always reports accurate
/// line numbers from the current file location. Use this for:
/// - `--file` parameter (single file analysis)
/// - `--force-refresh` flag
/// - Pre-commit hooks requiring accurate line numbers
///
/// # Root Cause (Issue #67)
///
/// The TDG cache uses content hash as the primary key. When functions are
/// extracted from one file to another, the content hash remains the same,
/// causing line numbers from the OLD location to be reported for the NEW file.
///
/// # Solution
///
/// This function bypasses the TDG cache entirely and performs fresh AST/heuristic
/// analysis, ensuring line numbers reflect the actual current file location.
///
/// # Arguments
///
/// * `path` - File path to analyze
/// * `content` - Optional file content (reads from disk if None)
///
/// # Returns
///
/// Fresh `FileComplexityMetrics` with accurate line numbers
///
/// # Examples
///
/// ```rust,no_run
/// use pmat::services::complexity::analyze_file_complexity_uncached;
/// use std::path::Path;
///
/// # async fn example() -> anyhow::Result<()> {
/// // Analyze file with fresh line numbers (bypasses cache)
/// let path = Path::new("src/extracted_functions.rs");
/// let metrics = analyze_file_complexity_uncached(path, None).await?;
///
/// // Line numbers reflect CURRENT file location
/// for func in &metrics.functions {
/// println!("{} at lines {}-{}", func.name, func.line_start, func.line_end);
/// }
/// # Ok(())
/// # }
/// ```
///
/// # See Also
///
/// - Issue #67: https://github.com/paiml/paiml-mcp-agent-toolkit/issues/67
/// - Test suite: `complexity_file_extraction_tests.rs`
pub async