Skip to main content

big_code_analysis_ast/
error.rs

1//! Error type returned from the library's top-level entry points.
2//!
3//! `big_code_analysis::FromPathError`, the richer error of the
4//! file-backed `Ast::from_path`, lives in the root crate's
5//! `from_path_error` module; this one is the parse-layer error every
6//! dispatch entry point returns.
7//!
8//! Prior to this module, every entry point returned `Option<…>` and
9//! collapsed parse failure, empty input, and disabled-language builds
10//! into a single `None`. [`MetricsError`] distinguishes those cases so
11//! library consumers can react appropriately (e.g. report a disabled
12//! language distinctly from an empty parse).
13//!
14//! New variants may be added in future minor versions, so consumers
15//! must include a `_` arm when matching exhaustively — this is enforced
16//! by the [`#[non_exhaustive]`][non_exhaustive] attribute on the enum.
17//!
18//! [non_exhaustive]: https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute
19
20use crate::LANG;
21
22/// Error returned by the library's metric-computation entry points.
23///
24/// # Stability
25///
26/// The variant set is additive: new variants may be introduced in
27/// minor versions, so the enum is marked `#[non_exhaustive]`. Existing
28/// variants will not be removed without a major version bump. The
29/// [`std::error::Error`] and [`std::fmt::Display`] impls are part of
30/// the stable surface; the exact wording of the `Display` output is
31/// not.
32///
33/// # Examples
34///
35/// The [`MetricsError::EmptyRoot`] variant is reserved for a future
36/// walker change (see its documentation). The
37/// [`MetricsError::LanguageDisabled`] variant is the one actually
38/// produced today: every dispatch entry point emits it when the
39/// caller selects a
40/// [`LANG`] whose per-language Cargo feature is not enabled in the
41/// current build (see #252). The example demonstrates the
42/// exhaustive-with-`_` match shape that callers should adopt to stay
43/// forward-compatible with future variants.
44///
45/// [`AnyParser::parse`](crate::langs::AnyParser::parse) stands in for
46/// `big_code_analysis::analyze` here — it is the same dispatch, one
47/// layer down, and it is reachable from this crate alone. The match
48/// arms are the ones an `analyze` caller writes.
49///
50/// ```
51/// use big_code_analysis_ast::{AnyParser, MetricsError, LANG};
52///
53/// let result = AnyParser::parse(LANG::Cpp, b"int a = 42;".to_vec(), None, None);
54///
55/// match result {
56///     Ok(_parser) => {
57///         // The `cpp` feature is enabled in this build.
58///     }
59///     Err(MetricsError::EmptyRoot) => {
60///         // Reserved: walker produced no top-level FuncSpace.
61///     }
62///     Err(MetricsError::LanguageDisabled(_lang)) => {
63///         // The `LANG` variant the caller asked for has no grammar
64///         // crate compiled in for this build (per-language feature
65///         // disabled — see the `[features]` table in Cargo.toml).
66///     }
67///     // `MetricsError` is `#[non_exhaustive]`; new variants may be added.
68///     Err(_) => {}
69/// }
70/// ```
71#[non_exhaustive]
72#[derive(Clone, Copy, Debug, PartialEq, Eq)]
73pub enum MetricsError {
74    /// The walker produced no top-level `big_code_analysis::FuncSpace`.
75    ///
76    /// Reserved — not produced today. `metrics_with_options` always
77    /// pushes a synthetic top-level [`SpaceKind::Unit`][crate::SpaceKind]
78    /// `FuncSpace` onto its state stack before walking the AST, so
79    /// every parse — including empty input, whitespace-only input,
80    /// and comment-only input — currently returns
81    /// `Ok(FuncSpace { kind: Unit, .. })`. The variant is kept for a
82    /// future walker change that lets the state stack legitimately
83    /// drain to empty (e.g. an option that suppresses the synthetic
84    /// root for sources with no parseable structure).
85    ///
86    EmptyRoot,
87    /// The requested [`LANG`] is not enabled in this build.
88    ///
89    /// Produced by every dispatch entry point
90    /// (`big_code_analysis::analyze`, `big_code_analysis::Ast::parse`,
91    /// `big_code_analysis::Ast::from_tree_sitter`, and
92    /// [`crate::LANG::tree_sitter_language`])
93    /// when the caller selects a [`LANG`] variant whose per-language
94    /// Cargo feature is not enabled in the current build — see the
95    /// `[features]` table in the root `Cargo.toml` for the list.
96    /// The default feature set (`default = ["all-languages"]`) keeps
97    /// every grammar compiled in, matching the library's historical
98    /// behaviour; callers that opt into a narrower set with
99    /// `--no-default-features --features rust,…` are the only ones
100    /// that observe this variant.
101    LanguageDisabled(LANG),
102}
103
104impl std::fmt::Display for MetricsError {
105    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
106        match self {
107            Self::EmptyRoot => {
108                f.write_str("no top-level FuncSpace could be produced from the source AST")
109            }
110            Self::LanguageDisabled(lang) => {
111                write!(f, "language {} is not enabled in this build", lang.name())
112            }
113        }
114    }
115}
116
117impl std::error::Error for MetricsError {}