big_code_analysis_ast/getter/rust.rs
1//! `Getter` implementation for Rust.
2#![allow(clippy::wildcard_imports, clippy::enum_glob_use)]
3
4use super::*;
5
6impl Getter for RustCode {
7 fn get_func_space_name<'a, 'tree>(
8 node: &Node<'tree>,
9 code: &'a [u8],
10 _ancestors: Ancestors<'tree, '_>,
11 ) -> Option<&'a str> {
12 // we're in a function or in a class or an impl
13 // for an impl: we've 'impl ... type {...'
14 if let Some(name) = node
15 .child_by_field_name("name")
16 .or_else(|| node.child_by_field_name("type"))
17 {
18 node_text(code, &name)
19 } else {
20 Some("<anonymous>")
21 }
22 }
23
24 fn get_space_kind(node: &Node) -> SpaceKind {
25 use Rust::*;
26
27 match node.kind_id().into() {
28 FunctionItem | ClosureExpression => SpaceKind::Function,
29 TraitItem => SpaceKind::Trait,
30 ImplItem => SpaceKind::Impl,
31 SourceFile => SpaceKind::Unit,
32 _ => SpaceKind::Unknown,
33 }
34 }
35
36 fn get_op_type<'a>(node: &Node<'a>, ancestors: Ancestors<'a, '_>) -> TokenRole {
37 use Rust::*;
38
39 match node.kind_id().into() {
40 // `||` is treated as an operator only if it's part of a binary expression.
41 // This prevents misclassification inside macros where closures without arguments (e.g., `let closure = || { /* ... */ };`)
42 // are not recognized as `ClosureExpression` and their `||` node is identified as `PIPEPIPE` instead of `ClosureParameters`.
43 //
44 // Similarly, exclude `/` when it corresponds to the third slash in `///` (`OuterDocCommentMarker`)
45 PIPEPIPE | SLASH => match ancestors.parent(node) {
46 Some(parent) if matches!(parent.kind_id().into(), BinaryExpression) => {
47 TokenRole::Operator
48 }
49 _ => TokenRole::Unknown,
50 },
51 // Ensure `!` is counted as an operator unless it belongs to an `InnerDocCommentMarker` `//!`
52 BANG => match ancestors.parent(node) {
53 Some(parent) if !matches!(parent.kind_id().into(), InnerDocCommentMarker) => {
54 TokenRole::Operator
55 }
56 _ => TokenRole::Unknown,
57 },
58 // COLONCOLON (`::`) is the path-segment separator. C++, Java,
59 // C#, and Kotlin all classify it as an operator; omitting it
60 // here (issue #394) silently dropped every path expression
61 // (`std::collections::HashMap`, `Vec::new`, `T::method`) into
62 // TokenRole::Unknown, deflating n1/N1 for path-heavy code.
63 //
64 // The 14 declaration/visibility keywords (Const, Static, Enum,
65 // Struct, Trait, Impl, Use, Mod, Pub, Type, Union, Where,
66 // Extern, Dyn) were inconsistently absent — the impl already
67 // accepted 17 other keywords (As, Async, Await, Break, …, Fn).
68 // Including them brings declaration-heavy code in line with
69 // statement-heavy code.
70 LPAREN | LBRACE | LBRACK | As | EQGT | PLUS | STAR | Async | Await | Break
71 | Continue | Else | For | If | In | Let | Loop | Match | Return | Unsafe | While
72 | EQ | COMMA | DASHGT | QMARK | LT | GT | AMP | MutableSpecifier | DOTDOT
73 | DOTDOTEQ | DASH | AMPAMP | PIPE | CARET | EQEQ | BANGEQ | LTEQ | GTEQ | LTLT
74 | GTGT | PERCENT | PLUSEQ | DASHEQ | STAREQ | SLASHEQ | PERCENTEQ | AMPEQ | PIPEEQ
75 | CARETEQ | LTLTEQ | GTGTEQ | Move | DOT | PrimitiveType | PrimitiveType2
76 | PrimitiveType3 | PrimitiveType4 | PrimitiveType5 | PrimitiveType6
77 | PrimitiveType7 | PrimitiveType8 | PrimitiveType9 | PrimitiveType10
78 | PrimitiveType11 | PrimitiveType12 | PrimitiveType13 | PrimitiveType14
79 | PrimitiveType15 | PrimitiveType16 | PrimitiveType17 | Fn | SEMI | COLONCOLON
80 | Const | Static | Enum | Struct | Trait | Impl | Use | Mod | Pub | Type | Union
81 | Where | Extern | Dyn => TokenRole::Operator,
82 // FieldIdentifier (e.g. `p.x`) and TypeIdentifier (e.g. `Vec`,
83 // `HashMap`) are operand-class names — C++ and Go classify them
84 // the same way (see arms ~588 and ~862 below). Omitting them
85 // here silently dropped both into TokenRole::Unknown,
86 // deflating n2/N2 and the derived vocabulary/volume/effort
87 // estimates (issue #390).
88 Identifier | TypeIdentifier | FieldIdentifier | StringLiteral | RawStringLiteral
89 | IntegerLiteral | FloatLiteral | BooleanLiteral | Zelf | CharLiteral | UNDERSCORE => {
90 TokenRole::Operand
91 }
92 _ => TokenRole::Unknown,
93 }
94 }
95
96 get_operator!(Rust);
97}