| 264 | } |
| 265 | |
| 266 | fn lint_inner<'skip>( |
| 267 | root: &Dir, |
| 268 | root_type: RootType, |
| 269 | config: &LintExecutionConfig, |
| 270 | skip: impl IntoIterator<Item = &'skip str>, |
| 271 | mut output: impl std::io::Write, |
| 272 | ) -> Result<LintExecutionResult> { |
| 273 | let mut fatal = 0usize; |
| 274 | let mut warnings = 0usize; |
| 275 | let mut passed = 0usize; |
| 276 | let skip: std::collections::HashSet<_> = skip.into_iter().collect(); |
| 277 | let (mut applicable_lints, skipped_lints): (Vec<_>, Vec<_>) = LINTS.iter().partition(|lint| { |
| 278 | if skip.contains(lint.name) { |
| 279 | return false; |
| 280 | } |
| 281 | if let Some(lint_root_type) = lint.root_type { |
| 282 | if lint_root_type != root_type { |
| 283 | return false; |
| 284 | } |
| 285 | } |
| 286 | true |
| 287 | }); |
| 288 | // SAFETY: Length must be smaller. |
| 289 | let skipped = skipped_lints.len(); |
| 290 | // Default to predictablility here |
| 291 | applicable_lints.sort_by(|a, b| a.name.cmp(b.name)); |
| 292 | // Split the lints by type |
| 293 | let (nonrec_lints, recursive_lints): (Vec<_>, Vec<_>) = applicable_lints |
| 294 | .into_iter() |
| 295 | .partition(|lint| matches!(lint.f, LintFnTy::Regular(_))); |
| 296 | let mut results = Vec::new(); |
| 297 | for lint in nonrec_lints { |
| 298 | let f = match lint.f { |
| 299 | LintFnTy::Regular(f) => f, |
| 300 | LintFnTy::Recursive(_) => unreachable!(), |
| 301 | }; |
| 302 | results.push((lint, f(&root, &config))); |
| 303 | } |
| 304 | |
| 305 | let mut recursive_lints = BTreeSet::from_iter(recursive_lints); |
| 306 | let mut recursive_errors = BTreeMap::new(); |
| 307 | root.walk( |
| 308 | &walk_configuration().path_base(Path::new("/")), |
| 309 | |e| -> std::io::Result<_> { |
| 310 | // If there's no recursive lints, we're done! |
| 311 | if recursive_lints.is_empty() { |
| 312 | return Ok(ControlFlow::Break(())); |
| 313 | } |
| 314 | // Keep track of any errors we caught while iterating over |
| 315 | // the recursive lints. |
| 316 | let mut this_iteration_errors = Vec::new(); |
| 317 | // Call each recursive lint on this directory entry. |
| 318 | for &lint in recursive_lints.iter() { |
| 319 | let f = match &lint.f { |
| 320 | // SAFETY: We know this set only holds recursive lints |
| 321 | LintFnTy::Regular(_) => unreachable!(), |
| 322 | LintFnTy::Recursive(f) => f, |
| 323 | }; |