use itertools::Itertools;
use crate::lint;
use crate::lint::LintRun;
use crate::project::AbsolutePath;
use crate::tui::app::App;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum LintsProjectKind {
Rust,
#[default]
NonRust,
}
impl LintsProjectKind {
pub const fn is_rust(self) -> bool { matches!(self, Self::Rust) }
}
impl From<bool> for LintsProjectKind {
fn from(is_rust: bool) -> Self { if is_rust { Self::Rust } else { Self::NonRust } }
}
#[derive(Clone, Default)]
pub struct LintsData {
pub runs: Vec<LintRun>,
pub sizes: Vec<Option<u64>>,
pub owner_paths: Vec<AbsolutePath>,
pub owner_of: Vec<usize>,
pub project_kind: LintsProjectKind,
}
impl LintsData {
pub const fn has_runs(&self) -> bool { !self.runs.is_empty() }
pub fn owner_path_for_run(&self, index: usize) -> Option<&AbsolutePath> {
let owner = self.owner_of.get(index).copied().unwrap_or(0);
self.owner_paths.get(owner)
}
}
pub fn build_lints_data(app: &App) -> LintsData {
let is_rust = app
.project_list
.selected_project_path()
.is_some_and(|path| app.project_list.is_rust_at_path(path));
if let Some(paths) = app.project_list.selected_worktree_group_checkout_paths() {
return aggregate_group_lints(app, paths, is_rust);
}
let selected_path = app.project_list.selected_project_path();
let lint_runs = selected_path.and_then(|path| {
app.lint_at_path(path)
.or_else(|| app.project_list.vendored_owner_lint(path))
});
let (runs, sizes) = lint_runs.map_or_else(
|| (Vec::new(), Vec::new()),
|lr| {
let sizes: Vec<Option<u64>> = lr
.runs()
.iter()
.map(|run| lr.archive_bytes(&run.run_id))
.collect();
(lr.runs().to_vec(), sizes)
},
);
let owner_paths = selected_path.map(AbsolutePath::from).into_iter().collect();
let owner_of = vec![0; runs.len()];
LintsData {
runs,
sizes,
owner_paths,
owner_of,
project_kind: LintsProjectKind::from(is_rust),
}
}
fn aggregate_group_lints(app: &App, paths: Vec<AbsolutePath>, is_rust: bool) -> LintsData {
let mut merged: Vec<(LintRun, Option<u64>, usize)> = paths
.iter()
.enumerate()
.flat_map(|(owner, path)| {
app.lint_at_path(path.as_path())
.into_iter()
.flat_map(move |lr| {
lr.runs()
.iter()
.map(move |run| (run.clone(), lr.archive_bytes(&run.run_id), owner))
})
})
.collect();
merged.sort_by(|a, b| {
lint::parse_timestamp(&b.0.started_at).cmp(&lint::parse_timestamp(&a.0.started_at))
});
let (runs, sizes, owner_of): (Vec<LintRun>, Vec<Option<u64>>, Vec<usize>) =
merged.into_iter().multiunzip();
LintsData {
runs,
sizes,
owner_paths: paths,
owner_of,
project_kind: LintsProjectKind::from(is_rust),
}
}