impl SATDDetector {
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn is_false_positive_line(&self, line: &str) -> bool {
let trimmed = line.trim();
self.is_string_literal(trimmed)
|| self.is_raw_string_literal(trimmed)
|| self.is_satd_processing_code(trimmed)
|| self.is_assignment_with_satd(trimmed)
|| self.is_format_string(trimmed)
|| self.is_url_or_path(trimmed)
|| self.is_markdown_header(trimmed)
|| self.is_security_documentation(trimmed)
|| self.is_pattern_definition(trimmed)
|| self.is_enum_or_struct_field(trimmed)
|| self.is_functional_description(trimmed)
}
fn is_string_literal(&self, trimmed: &str) -> bool {
trimmed.contains(r#""TODO"#)
|| trimmed.contains(r#""FIXME"#)
|| trimmed.contains(r#""HACK"#)
|| trimmed.contains(r#"'TODO'"#)
|| trimmed.contains(r#"'FIXME'"#)
|| trimmed.contains(r#"'HACK'"#)
}
fn is_raw_string_literal(&self, trimmed: &str) -> bool {
trimmed.contains("r#\"") || trimmed.contains("r\"")
}
fn is_satd_processing_code(&self, trimmed: &str) -> bool {
trimmed.contains(".matches(")
|| trimmed.contains("regex:")
|| trimmed.contains("DebtPattern")
|| trimmed.contains("comment_text:")
|| trimmed.contains("classify_comment")
|| trimmed.contains("debt_classifier")
|| trimmed.contains("SATDAnalysis")
}
fn is_assignment_with_satd(&self, trimmed: &str) -> bool {
trimmed.contains(" = ") && (trimmed.contains("TODO") || trimmed.contains("FIXME"))
}
fn is_format_string(&self, trimmed: &str) -> bool {
(trimmed.contains("format!")
|| trimmed.contains("println!")
|| trimmed.contains("write!")
|| trimmed.contains("{}"))
&& (trimmed.contains("TODO") || trimmed.contains("FIXME"))
}
fn is_url_or_path(&self, trimmed: &str) -> bool {
(trimmed.contains("http://")
|| trimmed.contains("https://")
|| trimmed.contains("file://")
|| trimmed.contains(".com/")
|| (trimmed.contains('/') && !trimmed.starts_with("//"))
|| trimmed.contains('\\'))
&& (trimmed.contains("TODO") || trimmed.contains("FIXME"))
}
fn is_security_documentation(&self, trimmed: &str) -> bool {
(trimmed.contains("Security") || trimmed.contains("security"))
&& (trimmed.contains("check")
|| trimmed.contains("validation")
|| trimmed.contains("properties")
|| trimmed.contains("vulnerabilities")
|| trimmed.contains("patterns")
|| trimmed.contains("issues")
|| trimmed.contains("concerns")
|| trimmed.starts_with("//")
|| trimmed.starts_with('*')
|| trimmed.starts_with('/'))
}
fn is_pattern_definition(&self, trimmed: &str) -> bool {
trimmed.contains("let valid_patterns")
|| trimmed.contains("let patterns")
|| trimmed.contains("vec![\"")
|| (trimmed.contains("\"TODO\"") && trimmed.contains('['))
|| (trimmed.contains("FIXME") && trimmed.contains("regex"))
}
fn is_enum_or_struct_field(&self, trimmed: &str) -> bool {
(trimmed.contains("Security") || trimmed.contains("Design") || trimmed.contains("Defect"))
&& (trimmed.contains(',') || trimmed.contains('=') || trimmed.contains("::"))
}
fn is_markdown_header(&self, trimmed: &str) -> bool {
let starts_with_hash = trimmed.starts_with('#');
if !starts_with_hash {
return false;
}
let content = trimmed.trim_start_matches('#').trim();
content == "Security"
|| content == "Added"
|| content == "Changed"
|| content == "Deprecated"
|| content == "Removed"
|| content == "Fixed"
|| content == "Unreleased"
|| content == "Changelog"
|| content == "CHANGELOG"
|| content.starts_with('[') }
fn is_functional_description(&self, trimmed: &str) -> bool {
if trimmed.starts_with("//") {
let comment_text = trimmed.trim_start_matches("//").trim().to_lowercase();
if comment_text.contains("===")
|| comment_text.contains("---")
|| comment_text.contains("───")
{
return true;
}
if comment_text.contains("\u{00d7}")
|| comment_text.contains("\u{2211}")
|| comment_text.contains("^t ")
|| comment_text.contains("^t\u{00d7}")
{
return true;
}
if comment_text.contains("mitigation")
|| comment_text.contains("isolation")
|| comment_text.starts_with("output ")
|| comment_text.starts_with("input ")
|| comment_text.starts_with("all ")
{
return true;
}
if comment_text.contains("xxx-xxx") || comment_text.contains("xxx.xxx") {
return true;
}
comment_text.starts_with("check for")
|| comment_text.starts_with("handle ")
|| comment_text.starts_with("phase ")
|| comment_text.starts_with("load ")
|| comment_text.starts_with("create ")
|| comment_text.starts_with("process ")
|| comment_text.starts_with("detect ")
|| comment_text.starts_with("scan ")
|| comment_text.starts_with("parse ")
|| comment_text.starts_with("analyze ")
|| comment_text.starts_with("extract ")
|| comment_text.starts_with("find ")
|| comment_text.starts_with("search ")
|| comment_text.starts_with("identify ")
|| comment_text.starts_with("validate ")
|| comment_text.starts_with("verify ")
|| comment_text.contains("relative links")
|| comment_text.contains("special modes")
|| comment_text.contains("documentation issues")
|| comment_text.contains("single file")
|| (comment_text.contains("broken") && comment_text.contains("links"))
|| (comment_text.contains("bug") && comment_text.contains("report"))
|| (comment_text.contains("broken") && comment_text.contains("dep"))
|| (comment_text.contains("bug") && comment_text.contains("fix") && (comment_text.contains("pattern") || comment_text.contains("patterns")))
|| (comment_text.contains("bug") && comment_text.contains("fix") && (comment_text.contains("claim") || comment_text.contains("claims")))
|| (comment_text.contains("bug") && comment_text.contains("fix") && comment_text.contains("commit"))
|| (comment_text.contains("describes functionality") && comment_text.contains("bug"))
|| (comment_text.contains("extract") && comment_text.contains("bug"))
|| self.is_bug_tracking_id(&comment_text)
|| self.is_fixed_bug_description(&comment_text)
|| (comment_text.contains("bug") && comment_text.contains("estimate"))
|| (comment_text.contains("marker") && !comment_text.contains("add"))
|| (comment_text.contains("detection") && !comment_text.contains("need"))
|| (comment_text.contains("pattern") && comment_text.contains("match"))
} else {
false
}
}
fn is_bug_tracking_id(&self, text: &str) -> bool {
let text_lower = text.to_lowercase();
if text_lower.contains("bug-") {
if let Some(pos) = text_lower.find("bug-") {
let after_dash = &text[pos + 4..];
if after_dash.chars().take(3).all(|c| c.is_ascii_digit()) {
return true;
}
}
}
if text_lower.contains("-bug-") {
return true;
}
if text_lower.contains("bug-") && (text_lower.contains(" fix:") || text_lower.contains(":"))
{
return true;
}
false
}
fn is_fixed_bug_description(&self, text: &str) -> bool {
let text_lower = text.to_lowercase();
if text_lower.starts_with("bug:") && text_lower.contains("previous") {
return true;
}
if text_lower.contains(" fix:") {
return true;
}
if text_lower.contains("bug:")
&& (text_lower.contains("ensure") || text_lower.contains("prevent"))
{
return true;
}
if text_lower.contains("root cause") {
return true;
}
false
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub(crate) fn is_documentation_or_metadata(&self, line: &str) -> bool {
let trimmed = line.trim();
self.is_documentation_comment(trimmed)
|| self.is_test_code(trimmed)
|| self.is_log_message(trimmed)
|| self.is_error_description(trimmed)
}
fn is_documentation_comment(&self, trimmed: &str) -> bool {
self.is_module_documentation(trimmed)
|| self.is_technical_debt_documentation(trimmed)
|| self.is_api_documentation(trimmed)
|| self.is_doctest_example(trimmed)
}
fn is_module_documentation(&self, trimmed: &str) -> bool {
trimmed.starts_with("//!") || trimmed.starts_with("///")
}
fn is_technical_debt_documentation(&self, trimmed: &str) -> bool {
let lower = trimmed.to_lowercase();
let mentions_td_concepts = lower.contains("technical debt")
|| trimmed.contains("TDG")
|| trimmed.contains("SATD")
|| lower.contains("self-admitted")
|| lower.contains("debt marker")
|| lower.contains("debt detection")
|| lower.contains("debt pattern");
let is_comment =
trimmed.starts_with("//") || trimmed.starts_with('*') || trimmed.starts_with('/');
mentions_td_concepts && is_comment
}
fn is_api_documentation(&self, trimmed: &str) -> bool {
let is_doc_marker = trimmed.starts_with('*')
|| trimmed.contains("@param")
|| trimmed.contains("@return")
|| trimmed.contains("Example:")
|| trimmed.contains("# Examples")
|| trimmed.contains("# Parameters");
let mentions_markers =
trimmed.contains("TODO") || trimmed.contains("FIXME") || trimmed.contains("security");
is_doc_marker && mentions_markers
}
fn is_doctest_example(&self, trimmed: &str) -> bool {
let has_comment_marker = trimmed.contains("// ");
let has_debt_marker = trimmed.contains("TODO") || trimmed.contains("FIXME");
let has_code_marker =
trimmed.contains("let ") || trimmed.contains("assert") || trimmed.contains("unwrap");
has_comment_marker && has_debt_marker && has_code_marker
}
fn is_test_code(&self, trimmed: &str) -> bool {
(trimmed.contains("assert")
|| trimmed.contains("expect")
|| trimmed.contains(".unwrap()")
|| trimmed.contains("panic!"))
&& (trimmed.contains("TODO") || trimmed.contains("FIXME"))
}
fn is_log_message(&self, trimmed: &str) -> bool {
(trimmed.contains("log::")
|| trimmed.contains("debug!")
|| trimmed.contains("info!")
|| trimmed.contains("warn!")
|| trimmed.contains("error!")
|| trimmed.contains("trace!"))
&& (trimmed.contains("TODO") || trimmed.contains("FIXME"))
}
fn is_error_description(&self, trimmed: &str) -> bool {
(trimmed.contains("Error:")
|| trimmed.contains("error:")
|| trimmed.contains("message:")
|| trimmed.contains("description:"))
&& (trimmed.contains("TODO") || trimmed.contains("FIXME"))
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "path_exists")]
pub(crate) fn is_likely_test_data_or_pattern(&self, line: &str, file_path: &Path) -> bool {
if self.should_exclude_file(file_path) {
return true;
}
if self.is_false_positive_line(line) {
return true;
}
if self.is_documentation_or_metadata(line) {
return true;
}
false
}
}