Skip to main content

lean_ctx_patterns/
swift.rs

1// SPDX-License-Identifier: Apache-2.0
2
3pub fn compress(cmd: &str, output: &str) -> Option<String> {
4    let trimmed = output.trim();
5    if trimmed.is_empty() {
6        return Some("ok".to_string());
7    }
8
9    if cmd.contains("test") {
10        return Some(compress_test(trimmed));
11    }
12    if cmd.contains("build") {
13        return Some(compress_build(trimmed));
14    }
15    if cmd.contains("package resolve") || cmd.contains("package update") {
16        return Some(compress_resolve(trimmed));
17    }
18
19    Some(compact_lines(trimmed, 15))
20}
21
22fn compress_test(output: &str) -> String {
23    let mut passed = 0u32;
24    let mut failed = 0u32;
25    let mut failures = Vec::new();
26    let mut time = String::new();
27
28    for line in output.lines() {
29        let trimmed = line.trim();
30        if trimmed.contains("Test Case") && trimmed.contains("passed") {
31            passed += 1;
32        } else if trimmed.contains("Test Case") && trimmed.contains("failed") {
33            failed += 1;
34            failures.push(trimmed.to_string());
35        }
36        if trimmed.starts_with("Test Suite") && trimmed.contains("Executed") {
37            time = trimmed.to_string();
38        }
39        if trimmed.contains("Executed")
40            && trimmed.contains("tests")
41            && let Some(pos) = trimmed.find("Executed")
42        {
43            time = trimmed[pos..].to_string();
44        }
45    }
46
47    if passed == 0 && failed == 0 {
48        return compact_lines(output, 10);
49    }
50
51    let mut result = format!("swift test: {passed} passed");
52    if failed > 0 {
53        result.push_str(&format!(", {failed} failed"));
54    }
55    if !time.is_empty() {
56        result.push_str(&format!("\n  {time}"));
57    }
58    for f in failures.iter().take(5) {
59        result.push_str(&format!("\n  FAIL: {f}"));
60    }
61    result
62}
63
64fn compress_build(output: &str) -> String {
65    let mut compiling = 0u32;
66    let mut linking = false;
67    let mut errors = Vec::new();
68    let mut warnings = 0u32;
69
70    for line in output.lines() {
71        let trimmed = line.trim();
72        if trimmed.starts_with("Compiling") || trimmed.contains('[') && trimmed.contains(']') {
73            compiling += 1;
74        }
75        if trimmed.starts_with("Linking") || trimmed.contains("Linking") {
76            linking = true;
77        }
78        if trimmed.contains("error:") {
79            errors.push(trimmed.to_string());
80        }
81        if trimmed.contains("warning:") {
82            warnings += 1;
83        }
84    }
85
86    if !errors.is_empty() {
87        let mut result = format!("{} errors", errors.len());
88        if warnings > 0 {
89            result.push_str(&format!(", {warnings} warnings"));
90        }
91        for e in errors.iter().take(10) {
92            result.push_str(&format!("\n  {e}"));
93        }
94        return result;
95    }
96
97    let mut result = format!("Build ok ({compiling} compiled");
98    if linking {
99        result.push_str(", linked");
100    }
101    if warnings > 0 {
102        result.push_str(&format!(", {warnings} warnings"));
103    }
104    result.push(')');
105    result
106}
107
108fn compress_resolve(output: &str) -> String {
109    let mut fetched = 0u32;
110    let mut resolved = 0u32;
111    for line in output.lines() {
112        if line.contains("Fetching") {
113            fetched += 1;
114        }
115        if line.contains("Resolving") || line.contains("resolved") {
116            resolved += 1;
117        }
118    }
119    if fetched == 0 && resolved == 0 {
120        return compact_lines(output, 5);
121    }
122    format!("{fetched} fetched, {resolved} resolved")
123}
124
125fn compact_lines(text: &str, max: usize) -> String {
126    let lines: Vec<&str> = text.lines().filter(|l| !l.trim().is_empty()).collect();
127    if lines.len() <= max {
128        return lines.join("\n");
129    }
130    format!(
131        "{}\n{}",
132        lines[..max].join("\n"),
133        super::elision_marker(lines.len() - max)
134    )
135}