Skip to main content

big_code_analysis/spaces/
options.rs

1//! `Default` and inherent impl blocks for [`super::MetricsOptions`].
2//!
3//! Split out of `spaces.rs` to keep that module focused on the public
4//! API type definitions. The blocks are moved verbatim; method and
5//! trait resolution is by type, so `crate::spaces::MetricsOptions`'s
6//! methods and `Default` impl resolve unchanged.
7
8use super::*;
9
10impl Default for MetricsOptions {
11    /// Defaults preserve every metric value emitted by the pre-#182
12    /// [`analyze`] entry point: every metric selected, tests
13    /// included, and Rust `?` counted toward cyclomatic (#409).
14    fn default() -> Self {
15        Self {
16            exclude_tests: false,
17            metrics: MetricSet::default(),
18            count_cyclomatic_try: true,
19        }
20    }
21}
22
23impl MetricsOptions {
24    /// Builder-style setter for `MetricsOptions::exclude_tests`.
25    ///
26    /// Provided because `MetricsOptions` is `#[non_exhaustive]` — the
27    /// struct-literal form is unavailable to downstream crates, so
28    /// external callers chain `MetricsOptions::default()
29    /// .with_exclude_tests(true)` instead.
30    #[inline]
31    #[must_use]
32    pub fn with_exclude_tests(mut self, exclude_tests: bool) -> Self {
33        self.exclude_tests = exclude_tests;
34        self
35    }
36
37    /// Builder-style setter for `MetricsOptions::count_cyclomatic_try`.
38    ///
39    /// Pass `false` to stop Rust's `?` operator from contributing to
40    /// cyclomatic complexity (standard and modified). The default is
41    /// `true`, which keeps every published metric value unchanged
42    /// (#409). Inert for non-Rust languages, none of which emit the
43    /// `try_expression` grammar node.
44    #[inline]
45    #[must_use]
46    pub fn with_count_cyclomatic_try(mut self, count: bool) -> Self {
47        self.count_cyclomatic_try = count;
48        self
49    }
50
51    /// Restrict computation to the given metrics. Metrics outside
52    /// this set are skipped during the walk; their `Stats` fields on
53    /// [`CodeMetrics`] remain at their `Default` value and are
54    /// elided from the [`Serialize`] output. Pass an empty slice to
55    /// disable every metric (the walker still runs and produces the
56    /// space tree, but no metric values are populated).
57    ///
58    /// # Dependencies
59    ///
60    /// Derived metrics implicitly pull in the inputs they require:
61    ///
62    /// - [`Metric::Mi`] adds [`Metric::Loc`], [`Metric::Cyclomatic`],
63    ///   [`Metric::Halstead`].
64    /// - [`Metric::Wmc`] adds [`Metric::Cyclomatic`] and
65    ///   [`Metric::Nom`].
66    ///
67    /// This auto-resolution is silent: a caller asking for `Mi`
68    /// alone gets a populated `Mi` value, not a zero. See
69    /// [`Metric::dependencies`] for the source of truth.
70    ///
71    /// # Examples
72    ///
73    /// ```
74    /// use big_code_analysis::{Metric, MetricsOptions};
75    ///
76    /// // Compute LoC only.
77    /// let _opts = MetricsOptions::default().with_only(&[Metric::Loc]);
78    ///
79    /// // Compute Mi: Loc + Cyclomatic + Halstead are auto-added.
80    /// let _opts = MetricsOptions::default().with_only(&[Metric::Mi]);
81    /// ```
82    #[inline]
83    #[must_use]
84    pub fn with_only(mut self, metrics: &[Metric]) -> Self {
85        self.metrics = MetricSet::from_slice_with_deps(metrics);
86        self
87    }
88
89    /// Restrict computation to the metrics in `metrics`, closing the
90    /// set under [`Metric::dependencies`] before storing it.
91    ///
92    /// Like [`MetricsOptions::with_only`], a derived metric pulls in
93    /// the inputs it needs: passing `MetricSet::empty().with(Metric::Mi)`
94    /// also selects [`Metric::Loc`], [`Metric::Cyclomatic`], and
95    /// [`Metric::Halstead`], so the maintainability index is computed
96    /// from real inputs rather than zero-valued defaults (#743). The
97    /// resolution is idempotent: an already-closed set is stored
98    /// unchanged.
99    ///
100    /// Use this builder when you already hold a [`MetricSet`]; reach
101    /// for [`MetricsOptions::with_only`] when you have a `&[Metric]`.
102    ///
103    /// # Examples
104    ///
105    /// ```
106    /// use big_code_analysis::{Metric, MetricSet, MetricsOptions};
107    ///
108    /// // `Mi` alone — Loc + Cyclomatic + Halstead are auto-added so the
109    /// // resulting MI value is meaningful.
110    /// let set = MetricSet::empty().with(Metric::Mi);
111    /// let _opts = MetricsOptions::default().with_metric_set(set);
112    /// ```
113    #[inline]
114    #[must_use]
115    pub fn with_metric_set(mut self, metrics: MetricSet) -> Self {
116        self.metrics = metrics.resolved();
117        self
118    }
119}