Skip to main content

big_code_analysis_ast/
traits.rs

1// Per-language metric and AST modules deliberately consume the macro-
2// generated tree-sitter token enums via `use crate::*` and `use Foo::*`
3// inside match expressions — explicit imports would list dozens of
4// variants per arm and obscure the per-language token sets that are the
5// point of these files. Allowed at the module level rather than per
6// function so the per-language impl blocks stay readable.
7#![allow(clippy::wildcard_imports, clippy::enum_glob_use)]
8
9//! [`ParserTrait`], [`LanguageInfo`], and [`Search`].
10
11use std::path::Path;
12use std::sync::Arc;
13
14use crate::alterator::Alterator;
15use crate::checker::Checker;
16use crate::getter::Getter;
17use crate::langs::*;
18use crate::node::Ancestors;
19use crate::node::Node;
20use crate::parser::Filter;
21use crate::preproc::PreprocResults;
22
23/// Static identification of a language code tag.
24///
25/// Implemented by every `XxxCode` type generated by the internal
26/// `mk_code!` macro. Crate-internal: reached only through the
27/// `pub` `Parser<T>` plumbing behind the `big_code_analysis::Ast` seam.
28pub trait LanguageInfo {
29    /// Tree-sitter base language enum carried by this code tag.
30    type BaseLang;
31
32    /// Returns the workspace-level [`LANG`] variant for this code tag.
33    fn lang() -> LANG;
34}
35
36/// A parsed source in one language: the tree, its bytes, and the
37/// `Checker` / `Getter` classifiers that read it.
38///
39/// Implemented once, generically, by [`Parser<T>`](crate::parser::Parser)
40/// for every `*Code` tag; the per-language `*Parser` aliases in
41/// [`langs`](crate::langs) are its concrete forms. This is the *parse*
42/// half of a language: `big-code-analysis` layers the per-metric
43/// implementations on top through its own supertrait, so nothing here
44/// depends on a metric (#1376). Not an extension contract — implement
45/// nothing; match on [`AnyParser`] to reach one.
46pub trait ParserTrait {
47    /// The language's classification predicates.
48    type Checker: Alterator + Checker;
49    /// The language's naming / space-kind / Halstead-class accessors.
50    type Getter: Getter;
51
52    /// Parses `code` read from `path`. `pr` carries the C-family
53    /// preprocessor results whose `#define`s are expanded before parsing;
54    /// every other language ignores it.
55    ///
56    /// # Panics
57    ///
58    /// When the language's Cargo feature is disabled in this build —
59    /// there is no grammar to parse with and the signature is
60    /// infallible. Check [`LANG::is_enabled`](crate::LANG::is_enabled)
61    /// first, or reach a parser through
62    /// [`AnyParser::parse`](crate::langs::AnyParser::parse), which
63    /// returns `Err(MetricsError::LanguageDisabled)` instead.
64    fn new(code: Vec<u8>, path: &Path, pr: Option<Arc<PreprocResults>>) -> Self;
65    /// The root node of the parsed tree.
66    fn root(&self) -> Node<'_>;
67    /// The bytes the tree was parsed from (after macro expansion, for
68    /// the C family).
69    fn code(&self) -> &[u8];
70    /// The returned [`Filter`] borrows `self` — the `"function"` and
71    /// `"string"` predicates read the source bytes (#1162, #1381).
72    fn filters(&self, requested: &[String]) -> Filter<'_>;
73}
74
75/// Subtree traversal helpers implemented by [`Node`].
76pub trait Search<'a> {
77    /// Visits every node of the subtree in source order, handing the
78    /// action each node's ancestor chain alongside it so a predicate it
79    /// applies stays off `Node::parent` (#1088).
80    fn act_on_node(&self, action: &mut dyn FnMut(&Node<'a>, Ancestors<'a, '_>));
81    /// The first direct child whose `kind_id` satisfies `pred`.
82    fn first_child(&self, pred: fn(u16) -> bool) -> Option<Node<'a>>;
83    /// Visits each direct child in source order.
84    fn act_on_child(&self, action: &mut dyn FnMut(&Node<'a>));
85}