pub fn extract_suppressed_kinds(line: &str) -> Vec<String> {
let body = line
.trim()
.trim_start_matches("///")
.trim_start_matches("//")
.trim_start_matches("/*")
.trim_start_matches('*')
.trim();
let rest = if let Some(r) = body.strip_prefix("padlock:") {
r.trim_start()
} else {
return Vec::new();
};
let rest = if let Some(r) = rest.strip_prefix("ignore[") {
r
} else {
return Vec::new();
};
if let Some(end) = rest.find(']') {
rest[..end]
.split(',')
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
.collect()
} else {
Vec::new()
}
}
pub fn suppressed_from_preceding_source(source: &str, node_start_byte: usize) -> Vec<String> {
let before = &source[..node_start_byte.min(source.len())];
let mut result = Vec::new();
let mut found_any_comment = false;
for line in before.lines().rev() {
let trimmed = line.trim();
if trimmed.is_empty() {
continue; }
if trimmed.starts_with("//") || trimmed.starts_with("/*") || trimmed.starts_with('*') {
let kinds = extract_suppressed_kinds(trimmed);
if !kinds.is_empty() {
result.extend(kinds);
found_any_comment = true;
continue;
}
break;
}
break; }
let _ = found_any_comment;
result
}
pub fn suppressed_from_source_line(source: &str, struct_line: u32) -> Vec<String> {
if struct_line == 0 {
return Vec::new();
}
let mut line_start = 0usize;
for (i, line) in source.lines().enumerate() {
if i + 1 == struct_line as usize {
break;
}
line_start += line.len() + 1; }
suppressed_from_preceding_source(source, line_start)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parses_single_kind() {
let kinds = extract_suppressed_kinds("// padlock: ignore[ReorderSuggestion]");
assert_eq!(kinds, vec!["ReorderSuggestion"]);
}
#[test]
fn parses_multiple_kinds() {
let kinds = extract_suppressed_kinds("// padlock: ignore[PaddingWaste, FalseSharing]");
assert_eq!(kinds, vec!["PaddingWaste", "FalseSharing"]);
}
#[test]
fn parses_no_space_variant() {
let kinds = extract_suppressed_kinds("// padlock:ignore[LocalityIssue]");
assert_eq!(kinds, vec!["LocalityIssue"]);
}
#[test]
fn returns_empty_for_unrelated_comment() {
assert!(extract_suppressed_kinds("// some other comment").is_empty());
assert!(extract_suppressed_kinds("// padlock:guard=mu").is_empty());
assert!(extract_suppressed_kinds("// padlock:ignore").is_empty()); }
#[test]
fn parses_doc_comment_style() {
let kinds = extract_suppressed_kinds("/// padlock: ignore[FalseSharing]");
assert_eq!(kinds, vec!["FalseSharing"]);
}
#[test]
fn preceding_source_finds_immediately_before() {
let source =
"struct Other { int x; };\n// padlock: ignore[ReorderSuggestion]\nstruct Foo {";
let byte = source.find("struct Foo").unwrap();
let kinds = suppressed_from_preceding_source(source, byte);
assert_eq!(kinds, vec!["ReorderSuggestion"]);
}
#[test]
fn preceding_source_skips_blank_lines() {
let source = "// padlock: ignore[FalseSharing]\n\nstruct Foo {";
let byte = source.find("struct Foo").unwrap();
let kinds = suppressed_from_preceding_source(source, byte);
assert_eq!(kinds, vec!["FalseSharing"]);
}
#[test]
fn preceding_source_stops_at_non_suppress_comment() {
let source = "// padlock: ignore[ReorderSuggestion]\n// Some other doc\nstruct Foo {";
let byte = source.find("struct Foo").unwrap();
let kinds = suppressed_from_preceding_source(source, byte);
assert!(kinds.is_empty());
}
#[test]
fn preceding_source_returns_empty_when_no_directive() {
let source = "struct Bar { int x; };\nstruct Foo {";
let byte = source.find("struct Foo").unwrap();
let kinds = suppressed_from_preceding_source(source, byte);
assert!(kinds.is_empty());
}
}