fallow_engine/health/
inline.rs1use std::path::PathBuf;
5
6use fallow_config::{ResolvedConfig, Severity};
7use fallow_types::discover::DiscoveredFile;
8
9use super::threshold_overrides::{GlobalHealthThresholds, ThresholdOverrideResolver};
10use crate::source::ModuleInfo;
11
12#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct InlineComplexity {
15 pub path: PathBuf,
17 pub name: String,
19 pub line: u32,
21 pub col: u32,
23 pub cyclomatic: u16,
25 pub cognitive: u16,
27 pub exceeds_cyclomatic: bool,
29 pub exceeds_cognitive: bool,
31}
32
33#[must_use]
47pub fn inline_complexity(
48 config: &ResolvedConfig,
49 modules: &[ModuleInfo],
50 files: &[DiscoveredFile],
51) -> Vec<InlineComplexity> {
52 let file_paths: rustc_hash::FxHashMap<_, _> =
53 files.iter().map(|file| (file.id, &file.path)).collect();
54 let ignore_set = super::ignore::build_ignore_set(&config.health.ignore);
55 let resolver = ThresholdOverrideResolver::new(
56 &config.health.threshold_overrides,
57 GlobalHealthThresholds {
58 cyclomatic: config.health.max_cyclomatic,
59 cognitive: config.health.max_cognitive,
60 crap: config.health.max_crap,
61 unit_size: config.health.max_unit_size,
62 },
63 );
64 let mut findings = Vec::new();
65
66 for module in modules {
67 let Some(path) = file_paths.get(&module.file_id) else {
68 continue;
69 };
70 let relative = path.strip_prefix(&config.root).unwrap_or(path);
71 if ignore_set.is_match(relative) {
72 continue;
73 }
74 let path_rules =
76 (!config.overrides.is_empty()).then(|| config.resolve_rules_for_path(path));
77 let rules = path_rules.as_ref().unwrap_or(&config.rules);
78 for function in &module.complexity {
79 if fallow_types::extract::is_synthetic_module_unit(&function.name)
80 || crate::suppress::is_suppressed(
81 &module.suppressions,
82 function.line,
83 crate::suppress::IssueKind::Complexity,
84 )
85 {
86 continue;
87 }
88 let (applied, _) = resolver.resolve(relative, &function.name);
89 let Some((exceeds_cyclomatic, exceeds_cognitive)) =
90 super::findings::complexity_exceeded(function, applied.effective)
91 else {
92 continue;
93 };
94 if rules.complexity_severity(exceeds_cyclomatic, exceeds_cognitive, false)
96 == Severity::Off
97 {
98 continue;
99 }
100 findings.push(InlineComplexity {
101 path: (*path).clone(),
102 name: function.name.clone(),
103 line: function.line,
104 col: function.col,
105 cyclomatic: function.cyclomatic,
106 cognitive: function.cognitive,
107 exceeds_cyclomatic,
108 exceeds_cognitive,
109 });
110 }
111 }
112
113 findings
114}