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}