Skip to main content

fallow_engine/health/
pipeline.rs

1//! Health pipeline carrier types shared by the engine health executor.
2
3use fallow_config::{ResolvedConfig, WorkspaceInfo};
4use fallow_output::DiffIndex;
5use fallow_types::workspace::WorkspaceDiagnostic;
6use rustc_hash::{FxHashMap, FxHashSet};
7use std::{path::PathBuf, sync::Arc};
8
9use crate::{
10    duplicates::DuplicationReport,
11    results::{AnalysisResults, DeadCodeAnalysisArtifacts},
12};
13
14use super::StylingAnalysisArtifacts;
15
16/// Discovery / parse inputs the CLI resolves before calling the engine.
17pub struct HealthPipelineInputs {
18    /// Resolved project config the run executes under.
19    pub config: ResolvedConfig,
20    /// Discovered files for the analysis scope.
21    pub files: Vec<fallow_types::discover::DiscoveredFile>,
22    /// Parsed modules for the discovered files.
23    pub modules: Vec<fallow_types::extract::ModuleInfo>,
24    /// Config resolution wall time in milliseconds.
25    pub config_ms: f64,
26    /// File discovery wall time in milliseconds.
27    pub discover_ms: f64,
28    /// Parse wall time in milliseconds.
29    pub parse_ms: f64,
30    /// Summed parse CPU time across rayon workers in milliseconds; `0.0` when
31    /// parse output was reused.
32    pub parse_cpu_ms: f64,
33    /// True when discover + parse were reused from the upstream check pass.
34    pub shared_parse: bool,
35    /// Dead-code analysis artifacts precomputed by the caller, so the health
36    /// pipeline skips its own graph build and dead-code pass.
37    pub pre_computed_analysis: Option<DeadCodeAnalysisArtifacts>,
38    /// Dead-code results reused by advisory sections that do not need the graph.
39    pub dead_code_results: Option<AnalysisResults>,
40    /// Styling analysis artifacts shared from an upstream pass.
41    pub styling_artifacts: Option<Arc<StylingAnalysisArtifacts>>,
42    /// Duplication report precomputed by the caller, so the health pipeline
43    /// skips its own duplication detection.
44    pub pre_computed_duplication: Option<DuplicationReport>,
45    /// Workspace metadata discovered during config resolution.
46    pub workspaces: Vec<WorkspaceInfo>,
47    /// Diagnostics from workspace discovery (undeclared or invalid members).
48    pub workspace_diagnostics: Vec<WorkspaceDiagnostic>,
49}
50
51pub(super) struct HealthPipelineRunInputs<M> {
52    pub(super) config: ResolvedConfig,
53    pub(super) files: Vec<fallow_types::discover::DiscoveredFile>,
54    pub(super) modules: M,
55    pub(super) config_ms: f64,
56    pub(super) discover_ms: f64,
57    pub(super) parse_ms: f64,
58    pub(super) parse_cpu_ms: f64,
59    pub(super) shared_parse: bool,
60    pub(super) pre_computed_analysis: Option<DeadCodeAnalysisArtifacts>,
61    pub(super) dead_code_results: Option<AnalysisResults>,
62    pub(super) styling_artifacts: Option<Arc<StylingAnalysisArtifacts>>,
63    pub(super) pre_computed_duplication: Option<DuplicationReport>,
64    pub(super) workspaces: Vec<WorkspaceInfo>,
65    pub(super) workspace_diagnostics: Vec<WorkspaceDiagnostic>,
66}
67
68impl From<HealthPipelineInputs>
69    for HealthPipelineRunInputs<Vec<fallow_types::extract::ModuleInfo>>
70{
71    fn from(input: HealthPipelineInputs) -> Self {
72        Self {
73            config: input.config,
74            files: input.files,
75            modules: input.modules,
76            config_ms: input.config_ms,
77            discover_ms: input.discover_ms,
78            parse_ms: input.parse_ms,
79            parse_cpu_ms: input.parse_cpu_ms,
80            shared_parse: input.shared_parse,
81            pre_computed_analysis: input.pre_computed_analysis,
82            dead_code_results: input.dead_code_results,
83            styling_artifacts: input.styling_artifacts,
84            pre_computed_duplication: input.pre_computed_duplication,
85            workspaces: input.workspaces,
86            workspace_diagnostics: input.workspace_diagnostics,
87        }
88    }
89}
90
91/// Scope inputs the CLI resolves before calling the engine.
92///
93/// The engine no longer fetches changed files, workspace roots, the shared diff
94/// index, or the CODEOWNERS-backed grouping resolver itself: those touch CLI
95/// state (the shared-diff `OnceLock`, CODEOWNERS parsing, workspace discovery
96/// error rendering), so the CLI resolves them and threads them in here.
97pub struct HealthScopeInputs<'a, R> {
98    /// Files changed since the requested git ref, when the run is diff-scoped.
99    pub changed_files: Option<FxHashSet<PathBuf>>,
100    /// Diff index scoping findings to changed lines.
101    pub diff_index: Option<&'a DiffIndex>,
102    /// Workspace roots limiting the analysis scope.
103    pub ws_roots: Option<Vec<PathBuf>>,
104    /// Grouping resolver for `--group-by` output; `None` disables grouping.
105    pub group_resolver: Option<R>,
106}
107
108pub(super) struct HealthPipelineTimings {
109    pub(super) config: f64,
110    pub(super) discover: f64,
111    pub(super) parse: f64,
112    /// Summed parse CPU time across rayon workers; `0.0` when parse was reused.
113    pub(super) parse_cpu: f64,
114    /// True when discover + parse were reused from the upstream check pass.
115    pub(super) shared_parse: bool,
116}
117
118impl HealthPipelineTimings {
119    pub(super) fn into_base_input(self, complexity_ms: f64) -> HealthTimingBaseInput {
120        HealthTimingBaseInput {
121            config_ms: self.config,
122            discover_ms: self.discover,
123            parse_ms: self.parse,
124            parse_cpu_ms: self.parse_cpu,
125            complexity_ms,
126            shared_parse: self.shared_parse,
127        }
128    }
129}
130
131pub(super) struct HealthScope<'a, R> {
132    pub(super) max_cyclomatic: u16,
133    pub(super) max_cognitive: u16,
134    pub(super) max_crap: f64,
135    pub(super) enforce_crap: bool,
136    pub(super) ignore_set: globset::GlobSet,
137    pub(super) changed_files: Option<FxHashSet<PathBuf>>,
138    pub(super) diff_index: Option<&'a DiffIndex>,
139    pub(super) ws_roots: Option<Vec<PathBuf>>,
140    pub(super) group_resolver: Option<R>,
141    pub(super) file_paths: FxHashMap<crate::discover::FileId, &'a PathBuf>,
142}
143
144pub(super) struct HealthTimingBaseInput {
145    pub(super) config_ms: f64,
146    pub(super) discover_ms: f64,
147    pub(super) parse_ms: f64,
148    pub(super) parse_cpu_ms: f64,
149    pub(super) complexity_ms: f64,
150    pub(super) shared_parse: bool,
151}