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
136
137
138
139
// SATD checking functions - extracted from quality_checks_part1.rs (CB-040)
/// Detects self-admitted technical debt (SATD) in source code.
///
/// Scans for technical debt markers like TODO, FIXME, HACK, etc.
///
/// # Arguments
///
/// * `project_path` - Path to the project directory to analyze
///
/// # Returns
///
/// A vector of quality violations for each SATD comment found
///
/// # Examples
///
/// ```no_run
/// # use std::path::Path;
/// # use pmat::cli::analysis_utilities::{check_satd, QualityViolation};
/// # async fn example() -> anyhow::Result<()> {
/// let violations = check_satd(Path::new(".")).await?;
///
/// // Group by severity
/// let mut by_severity = std::collections::HashMap::new();
/// for violation in violations {
/// *by_severity.entry(violation.severity.clone()).or_insert(0) += 1;
/// }
///
/// for (severity, count) in by_severity {
/// println!("{} SATD items with severity: {}", count, severity);
/// }
/// # Ok(())
/// # }
/// ```
///
/// # Property Tests
///
/// ```rust,no_run
/// # tokio_test::block_on(async {
/// use std::path::Path;
/// use pmat::cli::analysis_utilities::check_satd;
///
/// // Property: All detected items should have valid SATD patterns
/// let violations = check_satd(Path::new(".")).await.unwrap();
///
/// let valid_patterns = ["TODO", "FIXME", "HACK", "XXX", "BUG", "REFACTOR"];
/// for violation in violations {
/// assert_eq!(violation.check_type, "satd");
/// assert!(violation.line.is_some()); // Should have line numbers
///
/// // Check that message contains a valid SATD type (case-insensitive)
/// let message_upper = violation.message.to_uppercase();
/// let has_valid_pattern = valid_patterns.iter()
/// .any(|&pattern| message_upper.contains(pattern));
/// if !has_valid_pattern {
/// eprintln!("Violation message doesn't contain expected pattern: {}", violation.message);
/// }
/// }
/// # });
/// ```
pub async
/// SATD findings for ONE file, from the same detector and the same severity
/// scale `check_satd` uses.
///
/// `pmat quality-gate --file` used to run its own hardcoded regex
/// (`check_single_file_satd`) that stamped `severity:"warning"` on every marker
/// it matched, so the same `// TODO` was `info` from the project gate and
/// `warning` from the file gate — a second severity scale silently deciding
/// pass/fail once the verdict began reading severity. That regex is deleted;
/// this is the only single-file SATD check.
pub async
/// The ONE mapping from detector severity to gate severity.
///
/// Every SATD row every quality-gate surface reports comes through here, so
/// "which severities are verdict-bearing" (`is_verdict_bearing`) is asked of one
/// scale rather than of two that disagree.