big_code_analysis/spaces/space_kind.rs
1//! Inherent and `Display` impl blocks for [`super::SpaceKind`].
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::SpaceKind`'s methods
6//! and `Display` impl resolve unchanged.
7
8use super::*;
9
10impl SpaceKind {
11 /// Parse a [`SpaceKind`] from its lowercase serialized form — the
12 /// `#[serde(rename_all = "lowercase")]` representation that appears in
13 /// the JSON / wire `kind` field. An unrecognized string maps to
14 /// [`SpaceKind::Unknown`] so a JSON-walking front-end degrades
15 /// gracefully on a future kind rather than erroring.
16 ///
17 /// This is the single source of truth for the string-to-kind mapping a
18 /// consumer needs when it reads a serialized `kind` (the Python
19 /// `to_sarif` binding uses it to apply per-metric threshold scope via
20 /// [`crate::metric_catalog::MetricScope::admits`]). A round-trip test
21 /// pins it against the serde representation so the two cannot drift.
22 #[must_use]
23 pub fn from_serialized(serialized: &str) -> Self {
24 match serialized {
25 "function" => Self::Function,
26 "class" => Self::Class,
27 "struct" => Self::Struct,
28 "trait" => Self::Trait,
29 "impl" => Self::Impl,
30 "unit" => Self::Unit,
31 "namespace" => Self::Namespace,
32 "interface" => Self::Interface,
33 _ => Self::Unknown,
34 }
35 }
36
37 /// Whether the object-oriented member metrics — `wmc`, `npm`, `npa` —
38 /// are meaningful on a space of this kind.
39 ///
40 /// True for every container (which owns methods and attributes) and
41 /// for the file [`Unit`](SpaceKind::Unit) (which aggregates its
42 /// containers' counts into a whole-file roll-up). False for a
43 /// function space, which owns neither, and for
44 /// [`Unknown`](SpaceKind::Unknown).
45 ///
46 /// This is the single definition the three metrics share. `wmc`
47 /// carried it alone as an inline `matches!`; `npm` and `npa` enabled
48 /// themselves from `Checker::is_func_space` instead, which admits
49 /// function spaces and so gave a Kotlin `<get>` or a JavaScript method
50 /// an all-zero block its sibling method did not have (#1197).
51 ///
52 /// Phrased as an exclusion so that a future [`SpaceKind`] variant —
53 /// the enum is `#[non_exhaustive]` — defaults to *carrying* the
54 /// metrics. A new kind is far likelier to be another container than
55 /// another callable, and an extra roll-up is a milder wrong answer
56 /// than a silently missing one.
57 #[must_use]
58 pub(crate) fn is_member_scope(self) -> bool {
59 !matches!(self, Self::Function | Self::Unknown)
60 }
61}
62
63impl fmt::Display for SpaceKind {
64 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
65 let s = match self {
66 SpaceKind::Unknown => "unknown",
67 SpaceKind::Function => "function",
68 SpaceKind::Class => "class",
69 SpaceKind::Struct => "struct",
70 SpaceKind::Trait => "trait",
71 SpaceKind::Impl => "impl",
72 SpaceKind::Unit => "unit",
73 SpaceKind::Namespace => "namespace",
74 SpaceKind::Interface => "interface",
75 };
76 write!(f, "{s}")
77 }
78}