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,
26 pub cognitive: u16,
28 pub exceeds_cyclomatic: bool,
30 pub exceeds_cognitive: bool,
32}
33
34#[must_use]
48pub fn inline_complexity(
49 config: &ResolvedConfig,
50 modules: &[ModuleInfo],
51 files: &[DiscoveredFile],
52) -> Vec<InlineComplexity> {
53 let file_paths: rustc_hash::FxHashMap<_, _> =
54 files.iter().map(|file| (file.id, &file.path)).collect();
55 let ignore_set = super::ignore::build_ignore_set(&config.health.ignore);
56 let resolver = ThresholdOverrideResolver::new(
57 &config.health.threshold_overrides,
58 GlobalHealthThresholds {
59 cyclomatic: config.health.max_cyclomatic,
60 cognitive: config.health.max_cognitive,
61 crap: config.health.max_crap,
62 unit_size: config.health.max_unit_size,
63 },
64 )
65 .with_cyclomatic_policy(config.health.cyclomatic_policy);
66 let mut findings = Vec::new();
67
68 for module in modules {
69 let Some(path) = file_paths.get(&module.file_id) else {
70 continue;
71 };
72 let relative = path.strip_prefix(&config.root).unwrap_or(path);
73 if ignore_set.is_match(relative) {
74 continue;
75 }
76 let path_rules =
78 (!config.overrides.is_empty()).then(|| config.resolve_rules_for_path(path));
79 let rules = path_rules.as_ref().unwrap_or(&config.rules);
80 for function in &module.complexity {
81 if fallow_types::extract::is_synthetic_module_unit(&function.name)
82 || crate::suppress::is_suppressed(
83 &module.suppressions,
84 function.line,
85 crate::suppress::IssueKind::Complexity,
86 )
87 {
88 continue;
89 }
90 let (applied, _) = resolver.resolve(relative, &function.name);
91 let Some((exceeds_cyclomatic, exceeds_cognitive)) =
92 super::findings::complexity_exceeded(
93 function,
94 resolver.cyclomatic_policy(),
95 applied.effective,
96 )
97 else {
98 continue;
99 };
100 if rules.complexity_severity(exceeds_cyclomatic, exceeds_cognitive, false)
102 == Severity::Off
103 {
104 continue;
105 }
106 findings.push(InlineComplexity {
107 path: (*path).clone(),
108 name: function.name.clone(),
109 line: function.line,
110 col: function.col,
111 cyclomatic: resolver.gate_cyclomatic(function),
112 cognitive: function.cognitive,
113 exceeds_cyclomatic,
114 exceeds_cognitive,
115 });
116 }
117 }
118
119 findings
120}