lean_ctx/core/patterns/
semgrep.rs1use crate::core::compressor::strip_ansi;
9
10pub fn compress(_cmd: &str, output: &str) -> Option<String> {
11 let trimmed = output.trim();
12 if trimmed.is_empty() {
13 return Some("semgrep: ok".to_string());
14 }
15
16 let mut kept: Vec<String> = Vec::new();
17 for raw in trimmed.lines() {
18 let stripped = strip_ansi(raw);
19 let line = stripped.trim();
20 if line.is_empty() || is_noise(line) {
21 continue;
22 }
23 kept.push(line.to_string());
24 }
25
26 if kept.is_empty() {
27 return Some("semgrep: ok".to_string());
28 }
29 Some(kept.join("\n"))
30}
31
32fn is_noise(line: &str) -> bool {
33 if line.contains('┆') {
35 return true;
36 }
37 let first = line.chars().next().unwrap_or(' ');
39 if matches!(first, '┌' | '├' | '└' | '│' | '─' | '╷' | '╵') {
40 return true;
41 }
42 const PREFIXES: [&str; 6] = [
43 "Scanning",
44 "Loading rules",
45 "Fetching",
46 "Some files were skipped",
47 "partially analyzed",
48 "For a full list",
49 ];
50 PREFIXES.iter().any(|p| line.starts_with(p)) || line.contains("were skipped")
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 const SCAN: &str = "Scanning 120 files with 450 rules.\n\nFindings:\n\n src/app.py\n python.lang.security.audit.dangerous-subprocess-use\n Detected subprocess function 'call' with user-controlled data.\n\n 42┆ subprocess.call(user_input, shell=True)\n\nSome files were skipped or only partially analyzed.\n\nRan 450 rules on 120 files: 3 findings.\n";
58
59 #[test]
60 fn keeps_findings_and_summary_drops_noise() {
61 let r = compress("semgrep scan", SCAN).unwrap();
62 assert!(r.contains("dangerous-subprocess-use"), "keeps rule id: {r}");
63 assert!(r.contains("src/app.py"), "keeps file: {r}");
64 assert!(r.contains("3 findings"), "keeps summary: {r}");
65 assert!(!r.contains("42┆"), "drops code preview: {r}");
66 assert!(!r.contains("Scanning 120"), "drops scan banner: {r}");
67 assert!(!r.contains("Some files were skipped"), "{r}");
68 }
69
70 #[test]
71 fn empty_is_ok() {
72 assert_eq!(compress("semgrep scan", "").unwrap(), "semgrep: ok");
73 }
74}