big_code_analysis_ast/getter/javascript.rs
1//! `Getter` implementation for JavaScript.
2#![allow(clippy::wildcard_imports, clippy::enum_glob_use)]
3
4use super::*;
5
6impl Getter for JavascriptCode {
7 fn get_space_kind(node: &Node) -> SpaceKind {
8 use Javascript::*;
9
10 match node.kind_id().into() {
11 // `ClassStaticBlock` is ES2022 `static { … }` (#1184).
12 FunctionExpression
13 | MethodDefinition
14 | GeneratorFunction
15 | FunctionDeclaration
16 | GeneratorFunctionDeclaration
17 | ArrowFunction
18 | ClassStaticBlock => SpaceKind::Function,
19 Class | ClassDeclaration => SpaceKind::Class,
20 Program => SpaceKind::Unit,
21 _ => SpaceKind::Unknown,
22 }
23 }
24
25 fn get_func_space_name<'a, 'tree>(
26 node: &Node<'tree>,
27 code: &'a [u8],
28 ancestors: Ancestors<'tree, '_>,
29 ) -> Option<&'a str> {
30 // A class static block has no name token and no naming parent to
31 // fall back on, so it would otherwise land on `<anonymous>`
32 // alongside every arrow and function expression (#1184).
33 if node.kind_id() == Javascript::ClassStaticBlock as u16 {
34 return Some("<static-init>");
35 }
36 if let Some(name) = node.child_by_field_name("name") {
37 return node_text(code, &name);
38 }
39 // Otherwise the name comes from the binding site: a pair
40 // (`foo: function () {}`) or a variable declaration
41 // (`var aFun = function () {}`). The two differ only in which
42 // field carries the name, so they collapse to one lookup.
43 let bound_name = ancestors.parent(node).and_then(|parent| {
44 let field = match parent.kind_id().into() {
45 Javascript::Pair => "key",
46 Javascript::VariableDeclarator => "name",
47 _ => return None,
48 };
49 parent.child_by_field_name(field)
50 });
51 bound_name.map_or(Some("<anonymous>"), |name| node_text(code, &name))
52 }
53
54 // JSX closing / self-closing tag delimiters. See the macro's
55 // `$op_extras` note: they are per-language extras because
56 // TypeScript, which shares this macro, has no JSX (#1395).
57 // `jsx:` bills element text and its entities as operands, for the
58 // same reason (#1483).
59 //
60 // `Staticget` is one token spelling `static get` followed by a
61 // newline, the static getter whose name starts the next line. It is
62 // billed beside the shared `static` (#1563) so that form bills a
63 // modifier rather than nothing; being one node it is one operator.
64 impl_js_family_get_op_type!(
65 Javascript,
66 op_extras: [OptionalChain, LTSLASH, SLASHGT, Staticget],
67 operand_extras: [Identifier2, String2],
68 jsx: [JsxText, HtmlCharacterReference],
69 );
70
71 get_operator!(Javascript);
72}