Skip to content

Commit 78c37d6

Browse files
committed
WIP: Move reports to another module
1 parent 64bdb1b commit 78c37d6

File tree

2 files changed

+178
-168
lines changed

2 files changed

+178
-168
lines changed
Lines changed: 3 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
use anyhow::{Context as _, Result};
22
use octocrab::Octocrab;
3-
use std::collections::HashMap;
43

54
mod analyzer;
65
mod config;
6+
mod report_generator;
77

8-
use crate::analyzer::{AnalysisResult, Analyzer};
8+
use crate::analyzer::Analyzer;
99
use crate::config::ConfigBuilder;
10+
use crate::report_generator::generate_report;
1011

1112
#[tokio::main]
1213
async fn main() -> Result<()> {
@@ -142,169 +143,3 @@ async fn find_existing_comment(
142143
// No matching comment found
143144
Ok(None)
144145
}
145-
146-
/// Generate a detailed report for PR comment
147-
fn generate_report(
148-
analysis: &AnalysisResult,
149-
rules: &[String],
150-
repository: &str,
151-
base_branch: &str,
152-
head_branch: &str,
153-
) -> String {
154-
let mut report = String::from("## Clippy Allow Annotation Report\n\n");
155-
156-
// Add branch information with link to base branch
157-
report.push_str("Comparing clippy allow annotations between branches:\n");
158-
report.push_str(&format!(
159-
"- **Base Branch**: [{}](https://github.com/{}/tree/{})\n",
160-
base_branch, repository, base_branch
161-
));
162-
report.push_str(&format!("- **PR Branch**: {}\n\n", head_branch));
163-
164-
// Summary table by rule
165-
report.push_str("### Summary by Rule\n\n");
166-
report.push_str("| Rule | Base Branch | PR Branch | Change |\n");
167-
report.push_str("|------|------------|-----------|--------|\n");
168-
169-
let mut total_base = 0;
170-
let mut total_head = 0;
171-
172-
for rule in rules {
173-
let base_count = *analysis.base_counts.get(rule).unwrap_or(&0);
174-
let head_count = *analysis.head_counts.get(rule).unwrap_or(&0);
175-
let change = head_count as isize - base_count as isize;
176-
177-
total_base += base_count;
178-
total_head += head_count;
179-
180-
// Calculate percentage change
181-
let percent_change = if base_count > 0 {
182-
(change as f64 / base_count as f64) * 100.0
183-
} else if change > 0 {
184-
// If base count is 0 and there's an increase, it's an infinite increase
185-
// but we'll display it as N/A or a large number
186-
f64::INFINITY
187-
} else {
188-
// No change if both are 0
189-
0.0
190-
};
191-
192-
// Format the change string with percentage
193-
let change_str = if change > 0 {
194-
if percent_change.is_infinite() {
195-
format!("⚠️ +{} (N/A)", change)
196-
} else {
197-
format!("⚠️ +{} (+{:.1}%)", change, percent_change)
198-
}
199-
} else if change < 0 {
200-
format!("✅ {} ({:.1}%)", change, percent_change)
201-
} else {
202-
"No change (0%)".to_string()
203-
};
204-
205-
report.push_str(&format!(
206-
"| `{}` | {} | {} | {} |\n",
207-
rule, base_count, head_count, change_str
208-
));
209-
}
210-
211-
// Add total row with percentage
212-
let total_change = total_head as isize - total_base as isize;
213-
let total_percent_change = if total_base > 0 {
214-
(total_change as f64 / total_base as f64) * 100.0
215-
} else if total_change > 0 {
216-
f64::INFINITY
217-
} else {
218-
0.0
219-
};
220-
221-
let total_change_str = if total_change > 0 {
222-
if total_percent_change.is_infinite() {
223-
format!("⚠️ +{} (N/A)", total_change)
224-
} else {
225-
format!("⚠️ +{} (+{:.1}%)", total_change, total_percent_change)
226-
}
227-
} else if total_change < 0 {
228-
format!("✅ {} ({:.1}%)", total_change, total_percent_change)
229-
} else {
230-
"No change (0%)".to_string()
231-
};
232-
233-
report.push_str(&format!(
234-
"| **Total** | **{}** | **{}** | **{}** |\n\n",
235-
total_base, total_head, total_change_str
236-
));
237-
238-
// File-level annotation counts with percentage change
239-
if !analysis.changed_files.is_empty() {
240-
report.push_str("### Annotation Counts by File\n\n");
241-
report.push_str("| File | Base Branch | PR Branch | Change |\n");
242-
report.push_str("|------|------------|-----------|--------|\n");
243-
244-
// Count annotations by file in base branch
245-
let mut base_file_counts = HashMap::new();
246-
for anno in &analysis.base_annotations {
247-
*base_file_counts.entry(anno.file.clone()).or_insert(0) += 1;
248-
}
249-
250-
// Count annotations by file in head branch
251-
let mut head_file_counts = HashMap::new();
252-
for anno in &analysis.head_annotations {
253-
*head_file_counts.entry(anno.file.clone()).or_insert(0) += 1;
254-
}
255-
256-
// Get a sorted list of all files
257-
let mut all_files: Vec<String> = analysis.changed_files.iter().cloned().collect();
258-
all_files.sort();
259-
260-
// Generate table rows
261-
for file in all_files {
262-
let base_count = *base_file_counts.get(&file).unwrap_or(&0);
263-
let head_count = *head_file_counts.get(&file).unwrap_or(&0);
264-
let change = head_count as isize - base_count as isize;
265-
266-
// Skip files with no changes in annotation count
267-
if change == 0 && base_count == 0 && head_count == 0 {
268-
continue;
269-
}
270-
271-
// Calculate percentage change for file
272-
let percent_change = if base_count > 0 {
273-
(change as f64 / base_count as f64) * 100.0
274-
} else if change > 0 {
275-
f64::INFINITY
276-
} else {
277-
0.0
278-
};
279-
280-
// Format the change string with percentage for file
281-
let change_str = if change > 0 {
282-
if percent_change.is_infinite() {
283-
format!("⚠️ +{} (N/A)", change)
284-
} else {
285-
format!("⚠️ +{} (+{:.1}%)", change, percent_change)
286-
}
287-
} else if change < 0 {
288-
format!("✅ {} ({:.1}%)", change, percent_change)
289-
} else {
290-
"No change (0%)".to_string()
291-
};
292-
293-
report.push_str(&format!(
294-
"| `{}` | {} | {} | {} |\n",
295-
file, base_count, head_count, change_str
296-
));
297-
}
298-
299-
report.push_str("\n");
300-
}
301-
302-
// Add explanation
303-
report.push_str("### About This Report\n\n");
304-
report.push_str("This report tracks Clippy allow annotations for specific rules, ");
305-
report.push_str("showing how they've changed in this PR. ");
306-
report
307-
.push_str("Decreasing the number of these annotations generally improves code quality.\n");
308-
309-
report
310-
}
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
//! Report generator module for clippy-annotation-reporter
2+
//!
3+
//! This module handles the logic for generating formatted reports
4+
//! based on annotation analysis results.
5+
6+
use crate::analyzer::AnalysisResult;
7+
use std::collections::HashMap;
8+
9+
/// Generate a detailed report for PR comment
10+
pub fn generate_report(
11+
analysis: &AnalysisResult,
12+
rules: &[String],
13+
repository: &str,
14+
base_branch: &str,
15+
head_branch: &str,
16+
) -> String {
17+
let mut report = String::from("## Clippy Allow Annotation Report\n\n");
18+
19+
// Add branch information with link to base branch
20+
let base_branch_for_url = base_branch.strip_prefix("origin/").unwrap_or(base_branch);
21+
22+
report.push_str("Comparing clippy allow annotations between branches:\n");
23+
report.push_str(&format!(
24+
"- **Base Branch**: [{}](https://github.com/{}/tree/{})\n",
25+
base_branch, repository, base_branch_for_url
26+
));
27+
report.push_str(&format!("- **PR Branch**: {}\n\n", head_branch));
28+
29+
// Summary table by rule
30+
report.push_str("### Summary by Rule\n\n");
31+
report.push_str("| Rule | Base Branch | PR Branch | Change |\n");
32+
report.push_str("|------|------------|-----------|--------|\n");
33+
34+
let mut total_base = 0;
35+
let mut total_head = 0;
36+
37+
for rule in rules {
38+
let base_count = *analysis.base_counts.get(rule).unwrap_or(&0);
39+
let head_count = *analysis.head_counts.get(rule).unwrap_or(&0);
40+
let change = head_count as isize - base_count as isize;
41+
42+
total_base += base_count;
43+
total_head += head_count;
44+
45+
// Calculate percentage change
46+
let percent_change = if base_count > 0 {
47+
(change as f64 / base_count as f64) * 100.0
48+
} else if change > 0 {
49+
// If base count is 0 and there's an increase, it's an infinite increase
50+
// but we'll display it as N/A or a large number
51+
f64::INFINITY
52+
} else {
53+
// No change if both are 0
54+
0.0
55+
};
56+
57+
// Format the change string with percentage
58+
let change_str = if change > 0 {
59+
if percent_change.is_infinite() {
60+
format!("⚠️ +{} (N/A)", change)
61+
} else {
62+
format!("⚠️ +{} (+{:.1}%)", change, percent_change)
63+
}
64+
} else if change < 0 {
65+
format!("✅ {} ({:.1}%)", change, percent_change)
66+
} else {
67+
"No change (0%)".to_string()
68+
};
69+
70+
report.push_str(&format!(
71+
"| `{}` | {} | {} | {} |\n",
72+
rule, base_count, head_count, change_str
73+
));
74+
}
75+
76+
// Add total row with percentage
77+
let total_change = total_head as isize - total_base as isize;
78+
let total_percent_change = if total_base > 0 {
79+
(total_change as f64 / total_base as f64) * 100.0
80+
} else if total_change > 0 {
81+
f64::INFINITY
82+
} else {
83+
0.0
84+
};
85+
86+
let total_change_str = if total_change > 0 {
87+
if total_percent_change.is_infinite() {
88+
format!("⚠️ +{} (N/A)", total_change)
89+
} else {
90+
format!("⚠️ +{} (+{:.1}%)", total_change, total_percent_change)
91+
}
92+
} else if total_change < 0 {
93+
format!("✅ {} ({:.1}%)", total_change, total_percent_change)
94+
} else {
95+
"No change (0%)".to_string()
96+
};
97+
98+
report.push_str(&format!(
99+
"| **Total** | **{}** | **{}** | **{}** |\n\n",
100+
total_base, total_head, total_change_str
101+
));
102+
103+
// File-level annotation counts with percentage change
104+
if !analysis.changed_files.is_empty() {
105+
report.push_str("### Annotation Counts by File\n\n");
106+
report.push_str("| File | Base Branch | PR Branch | Change |\n");
107+
report.push_str("|------|------------|-----------|--------|\n");
108+
109+
// Count annotations by file in base branch
110+
let mut base_file_counts = HashMap::new();
111+
for anno in &analysis.base_annotations {
112+
*base_file_counts.entry(anno.file.clone()).or_insert(0) += 1;
113+
}
114+
115+
// Count annotations by file in head branch
116+
let mut head_file_counts = HashMap::new();
117+
for anno in &analysis.head_annotations {
118+
*head_file_counts.entry(anno.file.clone()).or_insert(0) += 1;
119+
}
120+
121+
// Get a sorted list of all files
122+
let mut all_files: Vec<String> = analysis.changed_files.iter().cloned().collect();
123+
all_files.sort();
124+
125+
// Generate table rows
126+
for file in all_files {
127+
let base_count = *base_file_counts.get(&file).unwrap_or(&0);
128+
let head_count = *head_file_counts.get(&file).unwrap_or(&0);
129+
let change = head_count as isize - base_count as isize;
130+
131+
// Skip files with no changes in annotation count
132+
if change == 0 && base_count == 0 && head_count == 0 {
133+
continue;
134+
}
135+
136+
// Calculate percentage change for file
137+
let percent_change = if base_count > 0 {
138+
(change as f64 / base_count as f64) * 100.0
139+
} else if change > 0 {
140+
f64::INFINITY
141+
} else {
142+
0.0
143+
};
144+
145+
// Format the change string with percentage for file
146+
let change_str = if change > 0 {
147+
if percent_change.is_infinite() {
148+
format!("⚠️ +{} (N/A)", change)
149+
} else {
150+
format!("⚠️ +{} (+{:.1}%)", change, percent_change)
151+
}
152+
} else if change < 0 {
153+
format!("✅ {} ({:.1}%)", change, percent_change)
154+
} else {
155+
"No change (0%)".to_string()
156+
};
157+
158+
report.push_str(&format!(
159+
"| `{}` | {} | {} | {} |\n",
160+
file, base_count, head_count, change_str
161+
));
162+
}
163+
164+
report.push_str("\n");
165+
}
166+
167+
// Add explanation
168+
report.push_str("### About This Report\n\n");
169+
report.push_str("This report tracks Clippy allow annotations for specific rules, ");
170+
report.push_str("showing how they've changed in this PR. ");
171+
report
172+
.push_str("Decreasing the number of these annotations generally improves code quality.\n");
173+
174+
report
175+
}

0 commit comments

Comments
 (0)