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 {}