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}