big_code_analysis_ast/getter/tsx.rs
1//! `Getter` implementation for TSX.
2#![allow(clippy::wildcard_imports, clippy::enum_glob_use)]
3
4use super::*;
5
6const GENERIC_ANGLES: GenericAngleKinds = GenericAngleKinds {
7 lists: &[Tsx::TypeArguments as u16, Tsx::TypeParameters as u16],
8 openers: &[Tsx::LT as u16],
9 closers: &[Tsx::GT as u16],
10 is_misparse: never_misparsed,
11};
12
13impl Getter for TsxCode {
14 fn get_space_kind(node: &Node) -> SpaceKind {
15 use Tsx::*;
16
17 match node.kind_id().into() {
18 // `ClassStaticBlock` is ES2022 `static { … }` (#1184).
19 FunctionExpression
20 | MethodDefinition
21 | GeneratorFunction
22 | FunctionDeclaration
23 | GeneratorFunctionDeclaration
24 | ArrowFunction
25 | ClassStaticBlock => SpaceKind::Function,
26 Class | ClassDeclaration | AbstractClassDeclaration => SpaceKind::Class,
27 InterfaceDeclaration => SpaceKind::Interface,
28 Program => SpaceKind::Unit,
29 _ => SpaceKind::Unknown,
30 }
31 }
32
33 fn get_func_space_name<'a, 'tree>(
34 node: &Node<'tree>,
35 code: &'a [u8],
36 ancestors: Ancestors<'tree, '_>,
37 ) -> Option<&'a str> {
38 // A class static block has no name token and no naming parent to
39 // fall back on, so it would otherwise land on `<anonymous>`
40 // alongside every arrow and function expression (#1184).
41 if node.kind_id() == Tsx::ClassStaticBlock as u16 {
42 return Some("<static-init>");
43 }
44 if let Some(name) = node.child_by_field_name("name") {
45 return node_text(code, &name);
46 }
47 // Otherwise the name comes from the binding site: a pair
48 // (`foo: function () {}`) or a variable declaration
49 // (`var aFun = function () {}`). The two differ only in which
50 // field carries the name, so they collapse to one lookup.
51 let bound_name = ancestors.parent(node).and_then(|parent| {
52 let field = match parent.kind_id().into() {
53 Tsx::Pair => "key",
54 Tsx::VariableDeclarator => "name",
55 _ => return None,
56 };
57 parent.child_by_field_name(field)
58 });
59 bound_name.map_or(Some("<anonymous>"), |name| node_text(code, &name))
60 }
61
62 // TSX exposes two anonymous `"string"` aliases: `String2` (kind_id
63 // 261, the string-literal alias — ordinary and JSX-attribute
64 // literals both parse as it), which is an operand like any other
65 // string literal, and `String3` (kind_id 141, the `: string` type
66 // keyword — the role TS's `String2` plays, emitted only as the
67 // child of a `predefined_type` wrapper). `String3` is deliberately
68 // NOT an operand: the wrapper already counts as the text-keyed
69 // `"string"` operator, so #313's listing of the child too counted
70 // one source token as operator AND operand while `: number` /
71 // `: boolean` counted once (#1261; see the TS invocation).
72 //
73 // TSX's TS-only member-expression productions `NestedIdentifier`
74 // and `MemberExpression4` were operand extras until #1263 and are
75 // now deliberately absent, matching the `MemberExpression*` drop in
76 // the macro body: a member access or a `namespace N.M` header
77 // contributes its identifier leaves plus the `.` operator, never
78 // the composite text as well.
79 //
80 // `LTSLASH` / `SLASHGT` are the JSX closing and self-closing tag
81 // delimiters. TSX is the only one of the two TypeScript grammars
82 // with JSX, so the `.ts` invocation has no such variants to pass
83 // (#1395), and the same holds for the `jsx:` text kinds (#1483).
84 //
85 // `Interface` / `Enum` are the TS-only type-declaration keyword
86 // leaves, billed as the shared `class` is (#1552) and as C# and
87 // Java bill theirs; their `*_declaration` wrappers stay unlisted.
88 //
89 // `Type` / `Namespace` / `Module2` / `Declare` / `Global` and the
90 // `TypeIdentifier` operand: see the TS invocation (#1557), as for
91 // `export_type_name`.
92 //
93 // `Satisfies` / `Keyof` / `Infer` / `Is` / `Asserts2`, the type-level
94 // operator keywords: see the TS invocation (#1561).
95 //
96 // `Public` through `Accessor`, the member modifiers: see the TS
97 // invocation (#1563).
98 //
99 // `generic_angles`: see the TS invocation (#1559). A JSX tag's `<` /
100 // `>` hang from the JSX element nodes, not from a generic list, so
101 // they stay `<` and `>`.
102 impl_js_family_get_op_type!(
103 Tsx,
104 op_extras: [
105 QMARKDOT, PredefinedType, Interface, Enum, Type, Namespace, Module2, Declare, Global,
106 Satisfies, Keyof, Infer, Is, Asserts2, Public, Private, Protected, Override, Readonly,
107 Abstract, Accessor, LTSLASH, SLASHGT,
108 ],
109 operand_extras: [Identifier2, String2, TypeIdentifier],
110 predefined_void: PredefinedType,
111 generic_angles: GENERIC_ANGLES,
112 export_type_name: [Type, ExportClause, ExportSpecifier],
113 jsx: [JsxText, HtmlCharacterReference],
114 );
115
116 get_operator!(Tsx);
117}