@ttsc/lint 0.18.3 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/README.md +95 -43
  2. package/go.mod +5 -4
  3. package/internal/rulecode/rulecode.go +88 -0
  4. package/lib/index.d.ts +10 -1
  5. package/lib/index.js +45 -17
  6. package/lib/index.js.map +1 -1
  7. package/lib/structures/ITtscLintConfig.d.ts +3 -0
  8. package/lib/structures/TtscLintRuleSetting.d.ts +3 -2
  9. package/lib/structures/format/ITtscLintFormat.d.ts +3 -2
  10. package/lib/structures/format/ITtscLintFormatSortImports.d.ts +20 -4
  11. package/lib/structures/rules/ITtscLintBoundariesRuleOptions.d.ts +80 -8
  12. package/lib/structures/rules/ITtscLintBoundariesRules.d.ts +6 -8
  13. package/lib/structures/rules/ITtscLintContributorRules.d.ts +18 -2
  14. package/lib/structures/rules/ITtscLintCoreRuleOptions.d.ts +347 -0
  15. package/lib/structures/rules/ITtscLintCoreRuleOptions.js +3 -0
  16. package/lib/structures/rules/ITtscLintCoreRuleOptions.js.map +1 -0
  17. package/lib/structures/rules/ITtscLintCoreRules.d.ts +101 -67
  18. package/lib/structures/rules/ITtscLintRegexpRules.d.ts +7 -2
  19. package/lib/structures/rules/ITtscLintRuleOptionsMap.d.ts +53 -7
  20. package/lib/structures/rules/ITtscLintRules.d.ts +6 -2
  21. package/lib/structures/rules/ITtscLintSolidRules.d.ts +0 -8
  22. package/lib/structures/rules/ITtscLintTypeScriptRuleOptions.d.ts +206 -0
  23. package/lib/structures/rules/ITtscLintTypeScriptRuleOptions.js +8 -0
  24. package/lib/structures/rules/ITtscLintTypeScriptRuleOptions.js.map +1 -0
  25. package/lib/structures/rules/ITtscLintTypeScriptRules.d.ts +55 -42
  26. package/lib/structures/rules/ITtscLintUnicornRuleOptions.d.ts +276 -0
  27. package/lib/structures/rules/ITtscLintUnicornRuleOptions.js +3 -0
  28. package/lib/structures/rules/ITtscLintUnicornRuleOptions.js.map +1 -0
  29. package/lib/structures/rules/ITtscLintUnicornRules.d.ts +44 -36
  30. package/lib/structures/rules/index.d.ts +3 -0
  31. package/lib/structures/rules/index.js +3 -0
  32. package/lib/structures/rules/index.js.map +1 -1
  33. package/linthost/ast_helpers.go +521 -23
  34. package/linthost/ast_selector_matcher.go +1628 -0
  35. package/linthost/ast_selector_parser.go +628 -0
  36. package/linthost/comment_scan.go +154 -0
  37. package/linthost/compile.go +129 -79
  38. package/linthost/config.go +352 -88
  39. package/linthost/config_format.go +15 -1
  40. package/linthost/contrib_adapter.go +129 -25
  41. package/linthost/declaration_rules.go +12 -11
  42. package/linthost/directives.go +9 -67
  43. package/linthost/dispatch.go +37 -3
  44. package/linthost/engine.go +368 -53
  45. package/linthost/escape_string.go +77 -0
  46. package/linthost/fix.go +133 -23
  47. package/linthost/flags_gen.go +18 -17
  48. package/linthost/format.go +73 -167
  49. package/linthost/format_editor_settings.go +134 -26
  50. package/linthost/grapheme_tables_gen.go +1920 -0
  51. package/linthost/host.go +160 -61
  52. package/linthost/literal_escape_scan.go +117 -0
  53. package/linthost/lsp.go +545 -98
  54. package/linthost/numeric_literal_precision.go +228 -0
  55. package/linthost/polyfill_browserslist.go +1439 -0
  56. package/linthost/polyfill_browserslist_config.go +603 -0
  57. package/linthost/polyfill_corejs.go +750 -0
  58. package/linthost/polyfill_data.go +113 -0
  59. package/linthost/polyfill_data_gen.json +39868 -0
  60. package/linthost/print_nodes_array.go +7 -1
  61. package/linthost/print_nodes_object.go +7 -1
  62. package/linthost/project_engine.go +151 -0
  63. package/linthost/project_rules.go +78 -0
  64. package/linthost/regex_clean.go +191 -0
  65. package/linthost/regex_tree.go +1544 -0
  66. package/linthost/regex_tree_optimizer.go +1685 -0
  67. package/linthost/regexp_cache.go +44 -0
  68. package/linthost/rule_codes.go +105 -0
  69. package/linthost/rule_codes.json +745 -0
  70. package/linthost/rules_ban_ts_comment.go +312 -0
  71. package/linthost/rules_boundaries.go +128 -43
  72. package/linthost/rules_boundaries_dependencies.go +1013 -0
  73. package/linthost/rules_core_extra.go +62 -92
  74. package/linthost/rules_cypress.go +1 -1
  75. package/linthost/rules_default_case.go +87 -11
  76. package/linthost/rules_dupes.go +38 -13
  77. package/linthost/rules_empty.go +188 -20
  78. package/linthost/rules_escape.go +62 -48
  79. package/linthost/rules_format_arrow_parens.go +19 -5
  80. package/linthost/rules_format_bracket_spacing.go +1 -1
  81. package/linthost/rules_format_clause_join.go +1 -1
  82. package/linthost/rules_format_declaration_header.go +31 -19
  83. package/linthost/rules_format_indent.go +1 -1
  84. package/linthost/rules_format_jsdoc.go +1 -1
  85. package/linthost/rules_format_orphan_semi.go +1 -1
  86. package/linthost/rules_format_parameter_properties.go +17 -7
  87. package/linthost/rules_format_print_width.go +1 -1
  88. package/linthost/rules_format_quote_props.go +1 -1
  89. package/linthost/rules_format_quotes.go +1 -1
  90. package/linthost/rules_format_semi.go +106 -79
  91. package/linthost/rules_format_sort_imports.go +79 -45
  92. package/linthost/rules_format_statement_split.go +1 -1
  93. package/linthost/rules_format_ternary_nullish_parens.go +1 -1
  94. package/linthost/rules_format_trailing_comma.go +64 -1
  95. package/linthost/rules_format_whitespace.go +1 -1
  96. package/linthost/rules_functional.go +21 -22
  97. package/linthost/rules_gap.go +80 -3
  98. package/linthost/rules_grouped_accessor_pairs.go +84 -25
  99. package/linthost/rules_guard_for_in.go +64 -147
  100. package/linthost/rules_jsx_a11y.go +232 -22
  101. package/linthost/rules_logic.go +84 -38
  102. package/linthost/rules_nextjs.go +105 -16
  103. package/linthost/rules_no_class_assign.go +70 -0
  104. package/linthost/rules_no_duplicate_imports.go +266 -0
  105. package/linthost/rules_no_else_return.go +156 -38
  106. package/linthost/rules_no_extend_native.go +113 -17
  107. package/linthost/rules_no_fallthrough.go +1013 -0
  108. package/linthost/rules_no_func_assign.go +70 -0
  109. package/linthost/rules_no_import_assign.go +278 -86
  110. package/linthost/rules_no_inner_declarations.go +186 -0
  111. package/linthost/rules_no_loop_func.go +438 -53
  112. package/linthost/rules_no_mixed_operators.go +208 -52
  113. package/linthost/rules_no_param_reassign.go +376 -61
  114. package/linthost/rules_no_promise_executor_return.go +156 -0
  115. package/linthost/rules_no_restricted_imports.go +1013 -57
  116. package/linthost/rules_no_restricted_syntax.go +190 -26
  117. package/linthost/rules_no_useless_constructor.go +6 -36
  118. package/linthost/rules_problems.go +154 -311
  119. package/linthost/rules_promise.go +2578 -109
  120. package/linthost/rules_react_extras.go +71 -45
  121. package/linthost/rules_react_hooks.go +18 -2
  122. package/linthost/rules_react_perf.go +1 -0
  123. package/linthost/rules_react_refresh.go +1 -1
  124. package/linthost/rules_regexp.go +230 -14
  125. package/linthost/rules_security.go +45 -19
  126. package/linthost/rules_self.go +21 -1
  127. package/linthost/rules_solid.go +13 -7
  128. package/linthost/rules_storybook.go +1 -1
  129. package/linthost/rules_suggestions.go +490 -84
  130. package/linthost/rules_testing_library.go +12 -1
  131. package/linthost/rules_ts.go +227 -54
  132. package/linthost/rules_ts_async.go +0 -131
  133. package/linthost/rules_ts_no_base_to_string.go +3 -4
  134. package/linthost/rules_ts_no_misused_promises.go +817 -0
  135. package/linthost/rules_ts_no_restricted_types.go +320 -34
  136. package/linthost/rules_ts_no_unnecessary_qualifier.go +132 -55
  137. package/linthost/rules_ts_no_unsafe_assignment.go +608 -60
  138. package/linthost/rules_ts_require_array_sort_compare.go +5 -5
  139. package/linthost/rules_ts_switch_exhaustiveness_check.go +556 -86
  140. package/linthost/rules_unicorn_better_regex.go +224 -16
  141. package/linthost/rules_unicorn_consistent_destructuring.go +1002 -7
  142. package/linthost/rules_unicorn_consistent_existence_index_check.go +208 -29
  143. package/linthost/rules_unicorn_consistent_function_scoping.go +1041 -8
  144. package/linthost/rules_unicorn_consistent_template_literal_escape.go +178 -7
  145. package/linthost/rules_unicorn_escape_case.go +30 -19
  146. package/linthost/rules_unicorn_filename_case.go +763 -16
  147. package/linthost/rules_unicorn_import_style.go +783 -17
  148. package/linthost/rules_unicorn_isolated_functions.go +934 -14
  149. package/linthost/rules_unicorn_no_hex_escape.go +26 -11
  150. package/linthost/rules_unicorn_no_typeof_undefined.go +234 -25
  151. package/linthost/rules_unicorn_no_unnecessary_polyfills.go +376 -21
  152. package/linthost/rules_unicorn_no_unused_properties.go +756 -19
  153. package/linthost/rules_unicorn_number_literal_case.go +58 -39
  154. package/linthost/rules_unicorn_prefer_at.go +7 -3
  155. package/linthost/rules_unicorn_prefer_number_properties.go +381 -48
  156. package/linthost/rules_unicorn_prefer_optional_catch_binding.go +24 -24
  157. package/linthost/rules_unicorn_prefer_simple_condition_first.go +597 -19
  158. package/linthost/rules_unicorn_prefer_string_raw.go +147 -16
  159. package/linthost/rules_unicorn_prevent_abbreviations.go +1963 -95
  160. package/linthost/rules_unicorn_string_content.go +611 -15
  161. package/linthost/rules_unicorn_switch_case_break_position.go +172 -15
  162. package/linthost/rules_unicorn_template_indent.go +923 -18
  163. package/linthost/rules_unicorn_text_encoding_identifier_case.go +202 -42
  164. package/linthost/rules_unicorn_throw_new_error.go +218 -26
  165. package/linthost/rules_var.go +829 -142
  166. package/linthost/string_length.go +222 -0
  167. package/package.json +4 -3
  168. package/rule/project.go +145 -0
  169. package/rule/rule.go +58 -1
  170. package/src/index.ts +58 -17
  171. package/src/structures/ITtscLintConfig.ts +3 -0
  172. package/src/structures/TtscLintRuleSetting.ts +3 -2
  173. package/src/structures/format/ITtscLintFormat.ts +3 -2
  174. package/src/structures/format/ITtscLintFormatSortImports.ts +21 -4
  175. package/src/structures/rules/ITtscLintBoundariesRuleOptions.ts +122 -8
  176. package/src/structures/rules/ITtscLintBoundariesRules.ts +6 -8
  177. package/src/structures/rules/ITtscLintContributorRules.ts +18 -2
  178. package/src/structures/rules/ITtscLintCoreRuleOptions.ts +465 -0
  179. package/src/structures/rules/ITtscLintCoreRules.ts +122 -67
  180. package/src/structures/rules/ITtscLintRegexpRules.ts +7 -2
  181. package/src/structures/rules/ITtscLintRuleOptionsMap.ts +88 -7
  182. package/src/structures/rules/ITtscLintRules.ts +7 -2
  183. package/src/structures/rules/ITtscLintSolidRules.ts +0 -9
  184. package/src/structures/rules/ITtscLintTypeScriptRuleOptions.ts +248 -0
  185. package/src/structures/rules/ITtscLintTypeScriptRules.ts +64 -42
  186. package/src/structures/rules/ITtscLintUnicornRuleOptions.ts +350 -0
  187. package/src/structures/rules/ITtscLintUnicornRules.ts +60 -36
  188. package/src/structures/rules/index.ts +3 -0
@@ -0,0 +1,1628 @@
1
+ package linthost
2
+
3
+ import (
4
+ "errors"
5
+ "math"
6
+ "math/big"
7
+ "strconv"
8
+ "strings"
9
+ "unicode/utf16"
10
+
11
+ shimast "github.com/microsoft/typescript-go/shim/ast"
12
+ shimscanner "github.com/microsoft/typescript-go/shim/scanner"
13
+ )
14
+
15
+ // matchASTSelector returns every node selected below root. A configured
16
+ // selector reports each node once even when multiple alternatives or subject
17
+ // paths reach it.
18
+ func matchASTSelector(root *shimast.Node, selector *astSelector) []*shimast.Node {
19
+ if root == nil || selector == nil {
20
+ return nil
21
+ }
22
+ subjects := astSelectorSubjects(selector, selector)
23
+ selected := make(map[*shimast.Node]struct{})
24
+ ordered := make([]*shimast.Node, 0)
25
+ walkDescendants(root, func(node *shimast.Node) {
26
+ if !astSelectorMatchesNode(node, selector, nil) {
27
+ return
28
+ }
29
+ if len(subjects) == 0 {
30
+ if _, duplicate := selected[node]; !duplicate {
31
+ selected[node] = struct{}{}
32
+ ordered = append(ordered, node)
33
+ }
34
+ return
35
+ }
36
+ for candidate := node; candidate != nil; candidate = selectorParent(candidate) {
37
+ for _, subject := range subjects {
38
+ if !astSelectorMatchesNode(candidate, subject, nil) {
39
+ continue
40
+ }
41
+ if _, duplicate := selected[candidate]; !duplicate {
42
+ selected[candidate] = struct{}{}
43
+ ordered = append(ordered, candidate)
44
+ }
45
+ break
46
+ }
47
+ }
48
+ })
49
+ return ordered
50
+ }
51
+
52
+ func astSelectorSubjects(selector, ancestor *astSelector) []*astSelector {
53
+ if selector == nil {
54
+ return nil
55
+ }
56
+ subjects := make([]*astSelector, 0)
57
+ if selector.subject {
58
+ subjects = append(subjects, ancestor)
59
+ }
60
+ if selector.left != nil {
61
+ subjects = append(subjects, astSelectorSubjects(selector.left, selector.left)...)
62
+ }
63
+ if selector.right != nil {
64
+ subjects = append(subjects, astSelectorSubjects(selector.right, ancestor)...)
65
+ }
66
+ for _, child := range selector.selectors {
67
+ subjects = append(subjects, astSelectorSubjects(child, ancestor)...)
68
+ }
69
+ return subjects
70
+ }
71
+
72
+ func astSelectorMatchesNode(node *shimast.Node, selector *astSelector, scopeRoot *shimast.Node) bool {
73
+ if node == nil || selector == nil {
74
+ return false
75
+ }
76
+ switch selector.kind {
77
+ case astSelectorWildcard:
78
+ return true
79
+ case astSelectorNodeType:
80
+ return astSelectorMatchesNodeType(node, selector.name)
81
+ case astSelectorExactNode:
82
+ return scopeRoot != nil && node == scopeRoot
83
+ case astSelectorAttribute:
84
+ return astSelectorMatchesAttribute(node, selector)
85
+ case astSelectorField:
86
+ return astSelectorMatchesField(node, selector.name)
87
+ case astSelectorMatches:
88
+ for _, alternative := range selector.selectors {
89
+ if astSelectorMatchesNode(node, alternative, scopeRoot) {
90
+ return true
91
+ }
92
+ }
93
+ return false
94
+ case astSelectorCompound:
95
+ for _, part := range selector.selectors {
96
+ if !astSelectorMatchesNode(node, part, scopeRoot) {
97
+ return false
98
+ }
99
+ }
100
+ return true
101
+ case astSelectorNot:
102
+ for _, excluded := range selector.selectors {
103
+ if astSelectorMatchesNode(node, excluded, scopeRoot) {
104
+ return false
105
+ }
106
+ }
107
+ return true
108
+ case astSelectorHas:
109
+ found := false
110
+ walkDescendants(node, func(candidate *shimast.Node) {
111
+ if found {
112
+ return
113
+ }
114
+ for _, nested := range selector.selectors {
115
+ if astSelectorMatchesNode(candidate, nested, node) {
116
+ found = true
117
+ return
118
+ }
119
+ }
120
+ })
121
+ return found
122
+ case astSelectorChild:
123
+ parent := selectorParent(node)
124
+ return parent != nil &&
125
+ astSelectorMatchesNode(node, selector.right, scopeRoot) &&
126
+ astSelectorMatchesNode(parent, selector.left, scopeRoot)
127
+ case astSelectorDescendant:
128
+ if !astSelectorMatchesNode(node, selector.right, scopeRoot) {
129
+ return false
130
+ }
131
+ for parent := selectorParent(node); parent != nil; parent = selectorParent(parent) {
132
+ if astSelectorMatchesNode(parent, selector.left, scopeRoot) {
133
+ return true
134
+ }
135
+ if scopeRoot != nil && parent == scopeRoot {
136
+ break
137
+ }
138
+ }
139
+ return false
140
+ case astSelectorSibling:
141
+ if astSelectorMatchesNode(node, selector.right, scopeRoot) {
142
+ for _, sibling := range selectorSiblings(node, false) {
143
+ if astSelectorMatchesNode(sibling, selector.left, scopeRoot) {
144
+ return true
145
+ }
146
+ }
147
+ }
148
+ if selector.left != nil && selector.left.subject && astSelectorMatchesNode(node, selector.left, scopeRoot) {
149
+ for _, sibling := range selectorSiblings(node, true) {
150
+ if astSelectorMatchesNode(sibling, selector.right, scopeRoot) {
151
+ return true
152
+ }
153
+ }
154
+ }
155
+ return false
156
+ case astSelectorAdjacent:
157
+ if astSelectorMatchesNode(node, selector.right, scopeRoot) {
158
+ if sibling := selectorAdjacent(node, false); sibling != nil {
159
+ return astSelectorMatchesNode(sibling, selector.left, scopeRoot)
160
+ }
161
+ }
162
+ if selector.left != nil && selector.left.subject && astSelectorMatchesNode(node, selector.left, scopeRoot) {
163
+ if sibling := selectorAdjacent(node, true); sibling != nil {
164
+ return astSelectorMatchesNode(sibling, selector.right, scopeRoot)
165
+ }
166
+ }
167
+ return false
168
+ case astSelectorNthChild:
169
+ return selectorChildIndex(node, false) == selector.index
170
+ case astSelectorNthLastChild:
171
+ return selectorChildIndex(node, true) == selector.index
172
+ case astSelectorClass:
173
+ return astSelectorMatchesClass(node, selector.name)
174
+ }
175
+ return false
176
+ }
177
+
178
+ func selectorParent(node *shimast.Node) *shimast.Node {
179
+ if node == nil {
180
+ return nil
181
+ }
182
+ return node.Parent
183
+ }
184
+
185
+ func selectorSiblings(node *shimast.Node, following bool) []*shimast.Node {
186
+ children, index := selectorNodeListPosition(node)
187
+ if index < 0 {
188
+ return nil
189
+ }
190
+ if following {
191
+ return children[index+1:]
192
+ }
193
+ return children[:index]
194
+ }
195
+
196
+ func selectorAdjacent(node *shimast.Node, following bool) *shimast.Node {
197
+ siblings := selectorSiblings(node, following)
198
+ if len(siblings) == 0 {
199
+ return nil
200
+ }
201
+ if following {
202
+ return siblings[0]
203
+ }
204
+ return siblings[len(siblings)-1]
205
+ }
206
+
207
+ func selectorChildIndex(node *shimast.Node, fromEnd bool) int {
208
+ children, index := selectorNodeListPosition(node)
209
+ if index < 0 {
210
+ return 0
211
+ }
212
+ if fromEnd {
213
+ return len(children) - index
214
+ }
215
+ return index + 1
216
+ }
217
+
218
+ // esquery defines sibling and child-position selectors only within array-valued
219
+ // visitor fields. Scalar children such as a call's callee are not siblings of
220
+ // entries in its arguments array. TypeScript-Go exposes traversal through
221
+ // ForEachChild, so recover the node-list boundaries from the structural fields
222
+ // supported by this selector adapter instead of flattening every child.
223
+ func selectorNodeListPosition(node *shimast.Node) ([]*shimast.Node, int) {
224
+ parent := selectorParent(node)
225
+ if parent == nil {
226
+ return nil, -1
227
+ }
228
+ fields := [...]string{
229
+ "body",
230
+ "params",
231
+ "arguments",
232
+ "consequent",
233
+ "declarations",
234
+ "elements",
235
+ "members",
236
+ "properties",
237
+ "statements",
238
+ }
239
+ for _, field := range fields {
240
+ value := astSelectorNodeProperty(parent, field)
241
+ if value.kind != astSelectorRuntimeNodes {
242
+ continue
243
+ }
244
+ for index, candidate := range value.nodes {
245
+ if candidate == node {
246
+ return value.nodes, index
247
+ }
248
+ }
249
+ }
250
+ return nil, -1
251
+ }
252
+
253
+ func astSelectorMatchesNodeType(node *shimast.Node, requested string) bool {
254
+ if node == nil {
255
+ return false
256
+ }
257
+ native := strings.TrimPrefix(node.Kind.String(), "Kind")
258
+ if strings.EqualFold(native, requested) {
259
+ return true
260
+ }
261
+ switch strings.ToLower(requested) {
262
+ case "program":
263
+ return node.Kind == shimast.KindSourceFile
264
+ case "arrowfunctionexpression":
265
+ return node.Kind == shimast.KindArrowFunction
266
+ case "objectexpression":
267
+ return node.Kind == shimast.KindObjectLiteralExpression && !isDestructuringAssignmentTarget(node)
268
+ case "arrayexpression":
269
+ return node.Kind == shimast.KindArrayLiteralExpression && !isDestructuringAssignmentTarget(node)
270
+ case "objectpattern":
271
+ return node.Kind == shimast.KindObjectBindingPattern ||
272
+ node.Kind == shimast.KindObjectLiteralExpression && isDestructuringAssignmentTarget(node)
273
+ case "arraypattern":
274
+ return node.Kind == shimast.KindArrayBindingPattern ||
275
+ node.Kind == shimast.KindArrayLiteralExpression && isDestructuringAssignmentTarget(node)
276
+ case "variabledeclarator":
277
+ return node.Kind == shimast.KindVariableDeclaration
278
+ case "memberexpression":
279
+ return node.Kind == shimast.KindPropertyAccessExpression || node.Kind == shimast.KindElementAccessExpression
280
+ case "assignmentexpression":
281
+ if node.Kind != shimast.KindBinaryExpression {
282
+ return false
283
+ }
284
+ expression := node.AsBinaryExpression()
285
+ return expression != nil && expression.OperatorToken != nil &&
286
+ isAssignmentOperator(expression.OperatorToken.Kind) &&
287
+ !isDestructuringAssignmentTarget(node)
288
+ case "logicalexpression":
289
+ if node.Kind != shimast.KindBinaryExpression {
290
+ return false
291
+ }
292
+ expression := node.AsBinaryExpression()
293
+ if expression == nil || expression.OperatorToken == nil {
294
+ return false
295
+ }
296
+ switch expression.OperatorToken.Kind {
297
+ case shimast.KindAmpersandAmpersandToken, shimast.KindBarBarToken, shimast.KindQuestionQuestionToken:
298
+ return true
299
+ }
300
+ return false
301
+ case "updateexpression":
302
+ if node.Kind == shimast.KindPrefixUnaryExpression {
303
+ expression := node.AsPrefixUnaryExpression()
304
+ return expression != nil && (expression.Operator == shimast.KindPlusPlusToken || expression.Operator == shimast.KindMinusMinusToken)
305
+ }
306
+ if node.Kind == shimast.KindPostfixUnaryExpression {
307
+ expression := node.AsPostfixUnaryExpression()
308
+ return expression != nil && (expression.Operator == shimast.KindPlusPlusToken || expression.Operator == shimast.KindMinusMinusToken)
309
+ }
310
+ return false
311
+ case "unaryexpression":
312
+ if node.Kind == shimast.KindPrefixUnaryExpression {
313
+ expression := node.AsPrefixUnaryExpression()
314
+ return expression != nil && expression.Operator != shimast.KindPlusPlusToken && expression.Operator != shimast.KindMinusMinusToken
315
+ }
316
+ return node.Kind == shimast.KindDeleteExpression ||
317
+ node.Kind == shimast.KindTypeOfExpression ||
318
+ node.Kind == shimast.KindVoidExpression
319
+ case "literal":
320
+ return astSelectorIsLiteral(node)
321
+ case "thisexpression":
322
+ return node.Kind == shimast.KindThisKeyword
323
+ case "super":
324
+ return node.Kind == shimast.KindSuperKeyword
325
+ case "templateliteral":
326
+ return node.Kind == shimast.KindTemplateExpression || node.Kind == shimast.KindNoSubstitutionTemplateLiteral
327
+ case "templateelement":
328
+ // ESTree models each quasi as a TemplateElement; TypeScript-Go spells
329
+ // them TemplateHead/Middle/Tail. A no-substitution template is its own
330
+ // single quasi (ESTree wraps it in a one-element TemplateLiteral).
331
+ return node.Kind == shimast.KindTemplateHead ||
332
+ node.Kind == shimast.KindTemplateMiddle ||
333
+ node.Kind == shimast.KindTemplateTail ||
334
+ node.Kind == shimast.KindNoSubstitutionTemplateLiteral
335
+ case "property":
336
+ switch node.Kind {
337
+ case shimast.KindPropertyAssignment,
338
+ shimast.KindShorthandPropertyAssignment:
339
+ return true
340
+ case shimast.KindBindingElement:
341
+ element := node.AsBindingElement()
342
+ return element != nil && element.DotDotDotToken == nil &&
343
+ node.Parent != nil && node.Parent.Kind == shimast.KindObjectBindingPattern
344
+ case shimast.KindMethodDeclaration,
345
+ shimast.KindGetAccessor,
346
+ shimast.KindSetAccessor:
347
+ return node.Parent != nil && node.Parent.Kind == shimast.KindObjectLiteralExpression
348
+ }
349
+ case "spreadelement":
350
+ return (node.Kind == shimast.KindSpreadElement || node.Kind == shimast.KindSpreadAssignment) &&
351
+ !isDestructuringAssignmentTarget(node)
352
+ case "restelement":
353
+ if (node.Kind == shimast.KindSpreadElement || node.Kind == shimast.KindSpreadAssignment) &&
354
+ isDestructuringAssignmentTarget(node) {
355
+ return true
356
+ }
357
+ if node.Kind == shimast.KindBindingElement {
358
+ element := node.AsBindingElement()
359
+ return element != nil && element.DotDotDotToken != nil
360
+ }
361
+ if node.Kind == shimast.KindParameter {
362
+ parameter := node.AsParameterDeclaration()
363
+ return parameter != nil && parameter.DotDotDotToken != nil
364
+ }
365
+ return false
366
+ case "tsasexpression":
367
+ return node.Kind == shimast.KindAsExpression
368
+ case "tstypeassertion":
369
+ return node.Kind == shimast.KindTypeAssertionExpression
370
+ case "tssatisfiesexpression":
371
+ return node.Kind == shimast.KindSatisfiesExpression
372
+ case "tsnonnullexpression":
373
+ return node.Kind == shimast.KindNonNullExpression
374
+ }
375
+ return false
376
+ }
377
+
378
+ func astSelectorIsLiteral(node *shimast.Node) bool {
379
+ if node == nil {
380
+ return false
381
+ }
382
+ switch node.Kind {
383
+ case shimast.KindNumericLiteral,
384
+ shimast.KindBigIntLiteral,
385
+ shimast.KindStringLiteral,
386
+ shimast.KindRegularExpressionLiteral,
387
+ shimast.KindTrueKeyword,
388
+ shimast.KindFalseKeyword,
389
+ shimast.KindNullKeyword:
390
+ return true
391
+ }
392
+ return false
393
+ }
394
+
395
+ func astSelectorMatchesClass(node *shimast.Node, class string) bool {
396
+ switch strings.ToLower(class) {
397
+ case "statement":
398
+ native := strings.TrimPrefix(node.Kind.String(), "Kind")
399
+ return strings.HasSuffix(native, "Statement") || strings.HasSuffix(native, "Declaration")
400
+ case "expression":
401
+ return astSelectorIsExpression(node)
402
+ case "declaration":
403
+ return astSelectorIsDeclaration(node)
404
+ case "function":
405
+ return isFunctionLikeKind(node)
406
+ case "pattern":
407
+ return astSelectorIsPattern(node) || astSelectorIsExpression(node)
408
+ default:
409
+ return false
410
+ }
411
+ }
412
+
413
+ func astSelectorIsExpression(node *shimast.Node) bool {
414
+ if node == nil {
415
+ return false
416
+ }
417
+ if astSelectorIsLiteral(node) {
418
+ return true
419
+ }
420
+ native := strings.TrimPrefix(node.Kind.String(), "Kind")
421
+ if strings.HasSuffix(native, "Expression") || strings.HasSuffix(native, "Literal") {
422
+ return true
423
+ }
424
+ switch node.Kind {
425
+ case shimast.KindIdentifier:
426
+ return node.Parent == nil || node.Parent.Kind != shimast.KindMetaProperty
427
+ case shimast.KindPrivateIdentifier,
428
+ shimast.KindMetaProperty,
429
+ shimast.KindThisKeyword,
430
+ shimast.KindSuperKeyword,
431
+ shimast.KindArrowFunction:
432
+ return true
433
+ }
434
+ return false
435
+ }
436
+
437
+ func astSelectorIsDeclaration(node *shimast.Node) bool {
438
+ if node == nil {
439
+ return false
440
+ }
441
+ return strings.HasSuffix(strings.TrimPrefix(node.Kind.String(), "Kind"), "Declaration")
442
+ }
443
+
444
+ func astSelectorIsPattern(node *shimast.Node) bool {
445
+ if node == nil {
446
+ return false
447
+ }
448
+ return strings.HasSuffix(strings.TrimPrefix(node.Kind.String(), "Kind"), "Pattern")
449
+ }
450
+
451
+ type astSelectorRuntimeValueKind uint8
452
+
453
+ const (
454
+ astSelectorRuntimeMissing astSelectorRuntimeValueKind = iota
455
+ astSelectorRuntimeNull
456
+ astSelectorRuntimeString
457
+ astSelectorRuntimeNumber
458
+ astSelectorRuntimeBigInt
459
+ astSelectorRuntimeBoolean
460
+ astSelectorRuntimeObject
461
+ astSelectorRuntimeNode
462
+ astSelectorRuntimeNodes
463
+ )
464
+
465
+ type astSelectorRuntimeValue struct {
466
+ kind astSelectorRuntimeValueKind
467
+ text string
468
+ number float64
469
+ boolean bool
470
+ node *shimast.Node
471
+ nodes []*shimast.Node
472
+ }
473
+
474
+ func astSelectorMatchesAttribute(node *shimast.Node, selector *astSelector) bool {
475
+ value := astSelectorPathValue(astSelectorRuntimeValue{kind: astSelectorRuntimeNode, node: node}, strings.Split(selector.name, "."))
476
+ if selector.operator == "" {
477
+ return value.kind != astSelectorRuntimeMissing && value.kind != astSelectorRuntimeNull
478
+ }
479
+ matched := false
480
+ switch selector.value.kind {
481
+ case astSelectorValueRegexp:
482
+ if selector.operator == "!=" {
483
+ return selector.value.regexp == nil || !selector.value.regexp.MatchString(astSelectorRuntimeStringValue(value))
484
+ }
485
+ matched = value.kind == astSelectorRuntimeString && selector.value.regexp != nil && selector.value.regexp.MatchString(value.text)
486
+ case astSelectorValueType:
487
+ matched = selector.value.literal == astSelectorRuntimeType(value)
488
+ case astSelectorValueLiteral:
489
+ if selector.operator == "=" || selector.operator == "!=" {
490
+ expected := selector.value.literal
491
+ if selector.value.number != nil {
492
+ expected = astSelectorNumberString(*selector.value.number)
493
+ }
494
+ matched = astSelectorRuntimeStringValue(value) == expected
495
+ } else {
496
+ return astSelectorCompare(value, selector.value, selector.operator)
497
+ }
498
+ default:
499
+ return false
500
+ }
501
+ if selector.operator == "!=" {
502
+ return !matched
503
+ }
504
+ return matched
505
+ }
506
+
507
+ func astSelectorCompare(value astSelectorRuntimeValue, expected astSelectorValue, operator string) bool {
508
+ if left, stringValue := astSelectorRuntimeRelationalString(value); stringValue && expected.number == nil {
509
+ comparison := astSelectorCompareUTF16(left, expected.literal)
510
+ switch operator {
511
+ case ">":
512
+ return comparison > 0
513
+ case ">=":
514
+ return comparison >= 0
515
+ case "<":
516
+ return comparison < 0
517
+ case "<=":
518
+ return comparison <= 0
519
+ }
520
+ return false
521
+ }
522
+ if value.kind == astSelectorRuntimeBigInt {
523
+ return astSelectorCompareBigInt(value.text, expected, operator)
524
+ }
525
+ left, leftNumber := astSelectorRuntimeNumberValue(value)
526
+ right := 0.0
527
+ rightNumber := false
528
+ if expected.number != nil {
529
+ right = *expected.number
530
+ rightNumber = true
531
+ } else if parsed, ok := astSelectorParseNumberString(expected.literal); ok {
532
+ right = parsed
533
+ rightNumber = true
534
+ }
535
+ if !leftNumber || !rightNumber || math.IsNaN(left) || math.IsNaN(right) {
536
+ return false
537
+ }
538
+ switch operator {
539
+ case ">":
540
+ return left > right
541
+ case ">=":
542
+ return left >= right
543
+ case "<":
544
+ return left < right
545
+ case "<=":
546
+ return left <= right
547
+ }
548
+ return false
549
+ }
550
+
551
+ func astSelectorCompareUTF16(left, right string) int {
552
+ leftUnits := utf16.Encode([]rune(left))
553
+ rightUnits := utf16.Encode([]rune(right))
554
+ length := len(leftUnits)
555
+ if len(rightUnits) < length {
556
+ length = len(rightUnits)
557
+ }
558
+ for index := 0; index < length; index++ {
559
+ if leftUnits[index] < rightUnits[index] {
560
+ return -1
561
+ }
562
+ if leftUnits[index] > rightUnits[index] {
563
+ return 1
564
+ }
565
+ }
566
+ switch {
567
+ case len(leftUnits) < len(rightUnits):
568
+ return -1
569
+ case len(leftUnits) > len(rightUnits):
570
+ return 1
571
+ default:
572
+ return 0
573
+ }
574
+ }
575
+
576
+ func astSelectorRuntimeRelationalString(value astSelectorRuntimeValue) (string, bool) {
577
+ switch value.kind {
578
+ case astSelectorRuntimeString,
579
+ astSelectorRuntimeObject,
580
+ astSelectorRuntimeNode,
581
+ astSelectorRuntimeNodes:
582
+ return astSelectorRuntimeStringValue(value), true
583
+ }
584
+ return "", false
585
+ }
586
+
587
+ func astSelectorCompareBigInt(value string, expected astSelectorValue, operator string) bool {
588
+ left, ok := new(big.Int).SetString(value, 10)
589
+ if !ok {
590
+ return false
591
+ }
592
+ right := new(big.Rat)
593
+ comparison := 0
594
+ if expected.number != nil {
595
+ if math.IsNaN(*expected.number) {
596
+ return false
597
+ }
598
+ if math.IsInf(*expected.number, 1) {
599
+ comparison = -1
600
+ } else if math.IsInf(*expected.number, -1) {
601
+ comparison = 1
602
+ } else {
603
+ if right.SetFloat64(*expected.number) == nil {
604
+ return false
605
+ }
606
+ comparison = new(big.Rat).SetInt(left).Cmp(right)
607
+ }
608
+ } else {
609
+ integer, ok := astSelectorParseBigIntString(expected.literal)
610
+ if !ok {
611
+ return false
612
+ }
613
+ right.SetInt(integer)
614
+ comparison = new(big.Rat).SetInt(left).Cmp(right)
615
+ }
616
+ switch operator {
617
+ case ">":
618
+ return comparison > 0
619
+ case ">=":
620
+ return comparison >= 0
621
+ case "<":
622
+ return comparison < 0
623
+ case "<=":
624
+ return comparison <= 0
625
+ }
626
+ return false
627
+ }
628
+
629
+ func astSelectorParseBigIntString(value string) (*big.Int, bool) {
630
+ value = strings.TrimSpace(value)
631
+ if value == "" {
632
+ return new(big.Int), true
633
+ }
634
+ negative := false
635
+ if value[0] == '+' || value[0] == '-' {
636
+ negative = value[0] == '-'
637
+ value = value[1:]
638
+ if value == "" {
639
+ return nil, false
640
+ }
641
+ lower := strings.ToLower(value)
642
+ if strings.HasPrefix(lower, "0x") || strings.HasPrefix(lower, "0o") || strings.HasPrefix(lower, "0b") {
643
+ return nil, false
644
+ }
645
+ }
646
+ base := 10
647
+ lower := strings.ToLower(value)
648
+ switch {
649
+ case strings.HasPrefix(lower, "0x"):
650
+ base, value = 16, value[2:]
651
+ case strings.HasPrefix(lower, "0o"):
652
+ base, value = 8, value[2:]
653
+ case strings.HasPrefix(lower, "0b"):
654
+ base, value = 2, value[2:]
655
+ }
656
+ integer, ok := new(big.Int).SetString(value, base)
657
+ if !ok {
658
+ return nil, false
659
+ }
660
+ if negative {
661
+ integer.Neg(integer)
662
+ }
663
+ return integer, true
664
+ }
665
+
666
+ func astSelectorRuntimeType(value astSelectorRuntimeValue) string {
667
+ switch value.kind {
668
+ case astSelectorRuntimeString:
669
+ return "string"
670
+ case astSelectorRuntimeNumber:
671
+ return "number"
672
+ case astSelectorRuntimeBigInt:
673
+ return "bigint"
674
+ case astSelectorRuntimeBoolean:
675
+ return "boolean"
676
+ case astSelectorRuntimeObject, astSelectorRuntimeNode, astSelectorRuntimeNodes, astSelectorRuntimeNull:
677
+ return "object"
678
+ default:
679
+ return "undefined"
680
+ }
681
+ }
682
+
683
+ func astSelectorRuntimeStringValue(value astSelectorRuntimeValue) string {
684
+ switch value.kind {
685
+ case astSelectorRuntimeString:
686
+ return value.text
687
+ case astSelectorRuntimeNumber:
688
+ return astSelectorNumberString(value.number)
689
+ case astSelectorRuntimeBigInt:
690
+ return value.text
691
+ case astSelectorRuntimeBoolean:
692
+ return strconv.FormatBool(value.boolean)
693
+ case astSelectorRuntimeNull:
694
+ return "null"
695
+ case astSelectorRuntimeMissing:
696
+ return "undefined"
697
+ case astSelectorRuntimeNodes:
698
+ if len(value.nodes) == 0 {
699
+ return ""
700
+ }
701
+ return strings.TrimSuffix(strings.Repeat("[object Object],", len(value.nodes)), ",")
702
+ case astSelectorRuntimeObject:
703
+ if value.text != "" {
704
+ return value.text
705
+ }
706
+ }
707
+ return "[object Object]"
708
+ }
709
+
710
+ func astSelectorRuntimeNumberValue(value astSelectorRuntimeValue) (float64, bool) {
711
+ switch value.kind {
712
+ case astSelectorRuntimeNumber:
713
+ return value.number, true
714
+ case astSelectorRuntimeString:
715
+ return astSelectorParseNumberString(value.text)
716
+ case astSelectorRuntimeBoolean:
717
+ if value.boolean {
718
+ return 1, true
719
+ }
720
+ return 0, true
721
+ case astSelectorRuntimeNull:
722
+ return 0, true
723
+ case astSelectorRuntimeObject,
724
+ astSelectorRuntimeNode,
725
+ astSelectorRuntimeNodes:
726
+ return astSelectorParseNumberString(astSelectorRuntimeStringValue(value))
727
+ }
728
+ return 0, false
729
+ }
730
+
731
+ func astSelectorNumberString(value float64) string {
732
+ if math.IsInf(value, 1) {
733
+ return "Infinity"
734
+ }
735
+ if math.IsInf(value, -1) {
736
+ return "-Infinity"
737
+ }
738
+ if math.IsNaN(value) {
739
+ return "NaN"
740
+ }
741
+ if value == 0 {
742
+ return "0"
743
+ }
744
+ formatted := strconv.FormatFloat(value, 'g', -1, 64)
745
+ exponentAt := strings.IndexByte(formatted, 'e')
746
+ if exponentAt < 0 {
747
+ return formatted
748
+ }
749
+ mantissa := formatted[:exponentAt]
750
+ exponent, err := strconv.Atoi(formatted[exponentAt+1:])
751
+ if err != nil {
752
+ return formatted
753
+ }
754
+ sign := ""
755
+ if strings.HasPrefix(mantissa, "-") {
756
+ sign = "-"
757
+ mantissa = mantissa[1:]
758
+ }
759
+ if exponent >= -6 && exponent < 21 {
760
+ digits := strings.ReplaceAll(mantissa, ".", "")
761
+ decimal := exponent + 1
762
+ switch {
763
+ case decimal <= 0:
764
+ return sign + "0." + strings.Repeat("0", -decimal) + digits
765
+ case decimal >= len(digits):
766
+ return sign + digits + strings.Repeat("0", decimal-len(digits))
767
+ default:
768
+ return sign + digits[:decimal] + "." + digits[decimal:]
769
+ }
770
+ }
771
+ exponentSign := "+"
772
+ if exponent < 0 {
773
+ exponentSign = ""
774
+ }
775
+ return sign + mantissa + "e" + exponentSign + strconv.Itoa(exponent)
776
+ }
777
+
778
+ func astSelectorParseNumberString(value string) (float64, bool) {
779
+ value = strings.TrimSpace(value)
780
+ if value == "" {
781
+ return 0, true
782
+ }
783
+ switch value {
784
+ case "Infinity", "+Infinity":
785
+ return math.Inf(1), true
786
+ case "-Infinity":
787
+ return math.Inf(-1), true
788
+ }
789
+ lower := strings.ToLower(value)
790
+ switch lower {
791
+ case "inf", "+inf", "-inf", "infinity", "+infinity", "-infinity":
792
+ return 0, false
793
+ }
794
+ if strings.ContainsRune(value, '_') {
795
+ return 0, false
796
+ }
797
+ if len(lower) > 1 && (lower[0] == '+' || lower[0] == '-') {
798
+ unsigned := lower[1:]
799
+ if strings.HasPrefix(unsigned, "0x") || strings.HasPrefix(unsigned, "0o") || strings.HasPrefix(unsigned, "0b") {
800
+ return 0, false
801
+ }
802
+ }
803
+ base := 0
804
+ switch {
805
+ case strings.HasPrefix(lower, "0x"):
806
+ base = 16
807
+ case strings.HasPrefix(lower, "0o"):
808
+ base = 8
809
+ case strings.HasPrefix(lower, "0b"):
810
+ base = 2
811
+ }
812
+ if base != 0 {
813
+ digits := value[2:]
814
+ if digits == "" || digits[0] == '+' || digits[0] == '-' || strings.ContainsRune(digits, '_') {
815
+ return 0, false
816
+ }
817
+ integer, ok := new(big.Int).SetString(digits, base)
818
+ if !ok {
819
+ return 0, false
820
+ }
821
+ number, _ := new(big.Float).SetInt(integer).Float64()
822
+ return number, true
823
+ }
824
+ number, err := strconv.ParseFloat(value, 64)
825
+ return number, err == nil || errors.Is(err, strconv.ErrRange)
826
+ }
827
+
828
+ func astSelectorPathValue(value astSelectorRuntimeValue, path []string) astSelectorRuntimeValue {
829
+ current := value
830
+ for _, field := range path {
831
+ switch current.kind {
832
+ case astSelectorRuntimeNode:
833
+ current = astSelectorNodeProperty(current.node, field)
834
+ case astSelectorRuntimeNodes:
835
+ if field == "length" {
836
+ current = astSelectorRuntimeValue{kind: astSelectorRuntimeNumber, number: float64(len(current.nodes))}
837
+ continue
838
+ }
839
+ index, err := strconv.Atoi(field)
840
+ if err != nil || index < 0 || strconv.Itoa(index) != field || index >= len(current.nodes) {
841
+ return astSelectorRuntimeValue{}
842
+ }
843
+ current = astSelectorNode(current.nodes[index])
844
+ case astSelectorRuntimeString:
845
+ if field != "length" {
846
+ return astSelectorRuntimeValue{}
847
+ }
848
+ current = astSelectorRuntimeValue{
849
+ kind: astSelectorRuntimeNumber,
850
+ number: float64(len(utf16.Encode([]rune(current.text)))),
851
+ }
852
+ case astSelectorRuntimeNull:
853
+ return current
854
+ default:
855
+ return astSelectorRuntimeValue{}
856
+ }
857
+ }
858
+ return current
859
+ }
860
+
861
+ func astSelectorMatchesField(node *shimast.Node, name string) bool {
862
+ path := strings.Split(name, ".")
863
+ ancestor := node
864
+ for range path {
865
+ ancestor = selectorParent(ancestor)
866
+ if ancestor == nil {
867
+ return false
868
+ }
869
+ }
870
+ return astSelectorNodeInPath(node, astSelectorRuntimeValue{kind: astSelectorRuntimeNode, node: ancestor}, path)
871
+ }
872
+
873
+ func astSelectorNodeInPath(node *shimast.Node, value astSelectorRuntimeValue, path []string) bool {
874
+ if len(path) == 0 {
875
+ return value.kind == astSelectorRuntimeNode && value.node == node
876
+ }
877
+ if value.kind != astSelectorRuntimeNode {
878
+ return false
879
+ }
880
+ next := astSelectorNodeProperty(value.node, path[0])
881
+ if next.kind == astSelectorRuntimeNodes {
882
+ for _, child := range next.nodes {
883
+ if astSelectorNodeInPath(node, astSelectorRuntimeValue{kind: astSelectorRuntimeNode, node: child}, path[1:]) {
884
+ return true
885
+ }
886
+ }
887
+ return false
888
+ }
889
+ return astSelectorNodeInPath(node, next, path[1:])
890
+ }
891
+
892
+ func astSelectorNodeProperty(node *shimast.Node, field string) astSelectorRuntimeValue {
893
+ if node == nil {
894
+ return astSelectorRuntimeValue{kind: astSelectorRuntimeNull}
895
+ }
896
+ switch field {
897
+ case "type":
898
+ return astSelectorString(strings.TrimPrefix(node.Kind.String(), "Kind"))
899
+ case "name":
900
+ if name := identifierText(node); name != "" {
901
+ return astSelectorString(name)
902
+ }
903
+ if node.Kind == shimast.KindPrivateIdentifier {
904
+ return astSelectorString(node.AsPrivateIdentifier().Text)
905
+ }
906
+ nameNode := node.Name()
907
+ if name := identifierText(nameNode); name != "" {
908
+ return astSelectorString(name)
909
+ }
910
+ if nameNode != nil && nameNode.Kind == shimast.KindPrivateIdentifier {
911
+ return astSelectorString(nameNode.AsPrivateIdentifier().Text)
912
+ }
913
+ if value := astSelectorLiteralValue(nameNode); value.kind != astSelectorRuntimeMissing {
914
+ return value
915
+ }
916
+ return astSelectorRuntimeValue{kind: astSelectorRuntimeNull}
917
+ case "value":
918
+ if node.Kind == shimast.KindPropertyAssignment {
919
+ return astSelectorNode(node.AsPropertyAssignment().Initializer)
920
+ }
921
+ if node.Kind == shimast.KindShorthandPropertyAssignment {
922
+ return astSelectorNode(node.AsShorthandPropertyAssignment().Name())
923
+ }
924
+ if node.Kind == shimast.KindBindingElement {
925
+ return astSelectorNode(node.Name())
926
+ }
927
+ return astSelectorLiteralValue(node)
928
+ case "raw":
929
+ if astSelectorIsLiteral(node) || node.Kind == shimast.KindNoSubstitutionTemplateLiteral {
930
+ if file := shimast.GetSourceFileOfNode(node); file != nil {
931
+ return astSelectorString(nodeText(file, node))
932
+ }
933
+ }
934
+ return astSelectorRuntimeValue{}
935
+ case "operator":
936
+ if operator := astSelectorNodeOperator(node); operator != "" {
937
+ return astSelectorString(operator)
938
+ }
939
+ return astSelectorRuntimeValue{}
940
+ case "kind":
941
+ if kind := astSelectorVariableKind(node); kind != "" {
942
+ return astSelectorString(kind)
943
+ }
944
+ return astSelectorRuntimeValue{}
945
+ case "async":
946
+ if node.FunctionLikeData() == nil {
947
+ return astSelectorRuntimeValue{}
948
+ }
949
+ return astSelectorBoolean(hasModifier(node, shimast.KindAsyncKeyword))
950
+ case "generator":
951
+ if node.FunctionLikeData() == nil {
952
+ return astSelectorRuntimeValue{}
953
+ }
954
+ return astSelectorBoolean(astSelectorIsGenerator(node))
955
+ case "static":
956
+ if !astSelectorSupportsStatic(node) {
957
+ return astSelectorRuntimeValue{}
958
+ }
959
+ if node.Kind == shimast.KindClassStaticBlockDeclaration {
960
+ return astSelectorBoolean(true)
961
+ }
962
+ return astSelectorBoolean(hasModifier(node, shimast.KindStaticKeyword))
963
+ case "readonly":
964
+ if !astSelectorSupportsReadonly(node) {
965
+ return astSelectorRuntimeValue{}
966
+ }
967
+ return astSelectorBoolean(hasModifier(node, shimast.KindReadonlyKeyword))
968
+ case "declare":
969
+ declared, applicable := astSelectorIsDeclared(node)
970
+ if !applicable {
971
+ return astSelectorRuntimeValue{}
972
+ }
973
+ return astSelectorBoolean(declared)
974
+ case "optional":
975
+ optional, applicable := astSelectorIsOptional(node)
976
+ if !applicable {
977
+ return astSelectorRuntimeValue{}
978
+ }
979
+ return astSelectorBoolean(optional)
980
+ case "computed":
981
+ computed, applicable := astSelectorIsComputed(node)
982
+ if !applicable {
983
+ return astSelectorRuntimeValue{}
984
+ }
985
+ return astSelectorBoolean(computed)
986
+ case "prefix":
987
+ switch node.Kind {
988
+ case shimast.KindPrefixUnaryExpression,
989
+ shimast.KindDeleteExpression,
990
+ shimast.KindTypeOfExpression,
991
+ shimast.KindVoidExpression:
992
+ return astSelectorBoolean(true)
993
+ case shimast.KindPostfixUnaryExpression:
994
+ return astSelectorBoolean(false)
995
+ }
996
+ return astSelectorRuntimeValue{}
997
+ case "id":
998
+ return astSelectorNode(node.Name())
999
+ case "params":
1000
+ if function := node.FunctionLikeData(); function != nil && function.Parameters != nil {
1001
+ return astSelectorNodes(function.Parameters.Nodes)
1002
+ }
1003
+ case "body":
1004
+ if body := node.Body(); body != nil {
1005
+ return astSelectorNode(body)
1006
+ }
1007
+ return astSelectorStatementBody(node)
1008
+ case "callee":
1009
+ if node.Kind == shimast.KindCallExpression {
1010
+ if call := node.AsCallExpression(); call != nil {
1011
+ return astSelectorNode(call.Expression)
1012
+ }
1013
+ }
1014
+ if node.Kind == shimast.KindNewExpression {
1015
+ if expression := node.AsNewExpression(); expression != nil {
1016
+ return astSelectorNode(expression.Expression)
1017
+ }
1018
+ }
1019
+ case "arguments":
1020
+ if node.Kind == shimast.KindCallExpression {
1021
+ if call := node.AsCallExpression(); call != nil && call.Arguments != nil {
1022
+ return astSelectorNodes(call.Arguments.Nodes)
1023
+ }
1024
+ }
1025
+ if node.Kind == shimast.KindNewExpression {
1026
+ if expression := node.AsNewExpression(); expression != nil && expression.Arguments != nil {
1027
+ return astSelectorNodes(expression.Arguments.Nodes)
1028
+ }
1029
+ }
1030
+ case "object":
1031
+ if node.Kind == shimast.KindPropertyAccessExpression {
1032
+ return astSelectorNode(node.AsPropertyAccessExpression().Expression)
1033
+ }
1034
+ if node.Kind == shimast.KindElementAccessExpression {
1035
+ return astSelectorNode(node.AsElementAccessExpression().Expression)
1036
+ }
1037
+ case "property":
1038
+ if node.Kind == shimast.KindPropertyAccessExpression {
1039
+ return astSelectorNode(node.AsPropertyAccessExpression().Name())
1040
+ }
1041
+ if node.Kind == shimast.KindElementAccessExpression {
1042
+ return astSelectorNode(node.AsElementAccessExpression().ArgumentExpression)
1043
+ }
1044
+ case "left":
1045
+ if node.Kind == shimast.KindBinaryExpression {
1046
+ return astSelectorNode(node.AsBinaryExpression().Left)
1047
+ }
1048
+ if node.Kind == shimast.KindQualifiedName {
1049
+ return astSelectorNode(node.AsQualifiedName().Left)
1050
+ }
1051
+ case "right":
1052
+ if node.Kind == shimast.KindBinaryExpression {
1053
+ return astSelectorNode(node.AsBinaryExpression().Right)
1054
+ }
1055
+ if node.Kind == shimast.KindQualifiedName {
1056
+ return astSelectorNode(node.AsQualifiedName().Right)
1057
+ }
1058
+ case "argument":
1059
+ return astSelectorUnaryArgument(node)
1060
+ case "expression":
1061
+ return astSelectorExpressionChild(node)
1062
+ case "test":
1063
+ return astSelectorTestChild(node)
1064
+ case "consequent":
1065
+ if node.Kind == shimast.KindIfStatement {
1066
+ return astSelectorNode(node.AsIfStatement().ThenStatement)
1067
+ }
1068
+ if node.Kind == shimast.KindConditionalExpression {
1069
+ return astSelectorNode(node.AsConditionalExpression().WhenTrue)
1070
+ }
1071
+ if node.Kind == shimast.KindCaseClause || node.Kind == shimast.KindDefaultClause {
1072
+ clause := node.AsCaseOrDefaultClause()
1073
+ if clause != nil && clause.Statements != nil {
1074
+ return astSelectorNodes(clause.Statements.Nodes)
1075
+ }
1076
+ }
1077
+ case "alternate":
1078
+ if node.Kind == shimast.KindIfStatement {
1079
+ return astSelectorNode(node.AsIfStatement().ElseStatement)
1080
+ }
1081
+ if node.Kind == shimast.KindConditionalExpression {
1082
+ return astSelectorNode(node.AsConditionalExpression().WhenFalse)
1083
+ }
1084
+ case "init":
1085
+ if node.Kind == shimast.KindVariableDeclaration {
1086
+ return astSelectorNode(node.AsVariableDeclaration().Initializer)
1087
+ }
1088
+ if node.Kind == shimast.KindForStatement {
1089
+ return astSelectorNode(node.AsForStatement().Initializer)
1090
+ }
1091
+ case "update":
1092
+ if node.Kind == shimast.KindForStatement {
1093
+ return astSelectorNode(node.AsForStatement().Incrementor)
1094
+ }
1095
+ case "declarations":
1096
+ if node.Kind == shimast.KindVariableDeclarationList {
1097
+ list := node.AsVariableDeclarationList()
1098
+ if list != nil && list.Declarations != nil {
1099
+ return astSelectorNodes(list.Declarations.Nodes)
1100
+ }
1101
+ }
1102
+ if node.Kind == shimast.KindVariableStatement {
1103
+ statement := node.AsVariableStatement()
1104
+ if statement != nil && statement.DeclarationList != nil {
1105
+ list := statement.DeclarationList.AsVariableDeclarationList()
1106
+ if list != nil && list.Declarations != nil {
1107
+ return astSelectorNodes(list.Declarations.Nodes)
1108
+ }
1109
+ }
1110
+ }
1111
+ case "elements":
1112
+ if node.Kind == shimast.KindArrayLiteralExpression {
1113
+ expression := node.AsArrayLiteralExpression()
1114
+ if expression != nil && expression.Elements != nil {
1115
+ return astSelectorNodes(expression.Elements.Nodes)
1116
+ }
1117
+ }
1118
+ if node.Kind == shimast.KindObjectBindingPattern || node.Kind == shimast.KindArrayBindingPattern {
1119
+ pattern := node.AsBindingPattern()
1120
+ if pattern != nil && pattern.Elements != nil {
1121
+ return astSelectorNodes(pattern.Elements.Nodes)
1122
+ }
1123
+ }
1124
+ case "properties":
1125
+ if node.Kind == shimast.KindObjectLiteralExpression {
1126
+ expression := node.AsObjectLiteralExpression()
1127
+ if expression != nil && expression.Properties != nil {
1128
+ return astSelectorNodes(expression.Properties.Nodes)
1129
+ }
1130
+ }
1131
+ if node.Kind == shimast.KindObjectBindingPattern {
1132
+ pattern := node.AsBindingPattern()
1133
+ if pattern != nil && pattern.Elements != nil {
1134
+ return astSelectorNodes(pattern.Elements.Nodes)
1135
+ }
1136
+ }
1137
+ case "members":
1138
+ switch node.Kind {
1139
+ case shimast.KindClassDeclaration,
1140
+ shimast.KindClassExpression,
1141
+ shimast.KindInterfaceDeclaration,
1142
+ shimast.KindEnumDeclaration,
1143
+ shimast.KindTypeLiteral,
1144
+ shimast.KindMappedType:
1145
+ return astSelectorNodes(node.Members())
1146
+ }
1147
+ case "key":
1148
+ return astSelectorPropertyKey(node)
1149
+ case "source":
1150
+ if node.Kind == shimast.KindImportDeclaration {
1151
+ return astSelectorNode(node.AsImportDeclaration().ModuleSpecifier)
1152
+ }
1153
+ if node.Kind == shimast.KindExportDeclaration {
1154
+ return astSelectorNode(node.AsExportDeclaration().ModuleSpecifier)
1155
+ }
1156
+ case "statements":
1157
+ return astSelectorStatements(node)
1158
+ }
1159
+ return astSelectorRuntimeValue{}
1160
+ }
1161
+
1162
+ func astSelectorString(value string) astSelectorRuntimeValue {
1163
+ return astSelectorRuntimeValue{kind: astSelectorRuntimeString, text: value}
1164
+ }
1165
+
1166
+ func astSelectorBoolean(value bool) astSelectorRuntimeValue {
1167
+ return astSelectorRuntimeValue{kind: astSelectorRuntimeBoolean, boolean: value}
1168
+ }
1169
+
1170
+ func astSelectorLiteralValue(node *shimast.Node) astSelectorRuntimeValue {
1171
+ if node == nil {
1172
+ return astSelectorRuntimeValue{kind: astSelectorRuntimeNull}
1173
+ }
1174
+ switch node.Kind {
1175
+ case shimast.KindStringLiteral, shimast.KindNoSubstitutionTemplateLiteral:
1176
+ if data := node.LiteralLikeData(); data != nil {
1177
+ return astSelectorString(data.Text)
1178
+ }
1179
+ case shimast.KindRegularExpressionLiteral:
1180
+ if file := shimast.GetSourceFileOfNode(node); file != nil {
1181
+ return astSelectorRuntimeValue{kind: astSelectorRuntimeObject, text: astSelectorRegexpString(nodeText(file, node))}
1182
+ }
1183
+ return astSelectorRuntimeValue{kind: astSelectorRuntimeObject}
1184
+ case shimast.KindNumericLiteral:
1185
+ if data := node.LiteralLikeData(); data != nil {
1186
+ text := strings.ReplaceAll(data.Text, "_", "")
1187
+ if number, err := strconv.ParseFloat(text, 64); err == nil || errors.Is(err, strconv.ErrRange) {
1188
+ return astSelectorRuntimeValue{kind: astSelectorRuntimeNumber, number: number}
1189
+ }
1190
+ if integer, ok := new(big.Int).SetString(text, 0); ok {
1191
+ number, _ := new(big.Float).SetInt(integer).Float64()
1192
+ return astSelectorRuntimeValue{kind: astSelectorRuntimeNumber, number: number}
1193
+ }
1194
+ }
1195
+ case shimast.KindBigIntLiteral:
1196
+ if data := node.LiteralLikeData(); data != nil {
1197
+ text := strings.TrimSuffix(strings.ReplaceAll(data.Text, "_", ""), "n")
1198
+ if integer, ok := new(big.Int).SetString(text, 0); ok {
1199
+ text = integer.String()
1200
+ }
1201
+ return astSelectorRuntimeValue{
1202
+ kind: astSelectorRuntimeBigInt,
1203
+ text: text,
1204
+ }
1205
+ }
1206
+ case shimast.KindTrueKeyword:
1207
+ return astSelectorBoolean(true)
1208
+ case shimast.KindFalseKeyword:
1209
+ return astSelectorBoolean(false)
1210
+ case shimast.KindNullKeyword:
1211
+ return astSelectorRuntimeValue{kind: astSelectorRuntimeNull}
1212
+ }
1213
+ return astSelectorRuntimeValue{}
1214
+ }
1215
+
1216
+ func astSelectorRegexpString(raw string) string {
1217
+ delimiter := strings.LastIndexByte(raw, '/')
1218
+ if delimiter <= 0 || delimiter == len(raw)-1 {
1219
+ return raw
1220
+ }
1221
+ flags := raw[delimiter+1:]
1222
+ var canonical strings.Builder
1223
+ for _, flag := range "dgimsuvy" {
1224
+ if strings.ContainsRune(flags, flag) {
1225
+ canonical.WriteRune(flag)
1226
+ }
1227
+ }
1228
+ if canonical.Len() != len(flags) {
1229
+ return raw
1230
+ }
1231
+ return raw[:delimiter+1] + canonical.String()
1232
+ }
1233
+
1234
+ func astSelectorNode(node *shimast.Node) astSelectorRuntimeValue {
1235
+ if node == nil {
1236
+ return astSelectorRuntimeValue{kind: astSelectorRuntimeNull}
1237
+ }
1238
+ return astSelectorRuntimeValue{kind: astSelectorRuntimeNode, node: node}
1239
+ }
1240
+
1241
+ func astSelectorNodes(nodes []*shimast.Node) astSelectorRuntimeValue {
1242
+ if nodes == nil {
1243
+ return astSelectorRuntimeValue{kind: astSelectorRuntimeNull}
1244
+ }
1245
+ return astSelectorRuntimeValue{kind: astSelectorRuntimeNodes, nodes: nodes}
1246
+ }
1247
+
1248
+ func astSelectorNodeOperator(node *shimast.Node) string {
1249
+ if node == nil {
1250
+ return ""
1251
+ }
1252
+ kind := shimast.KindUnknown
1253
+ switch node.Kind {
1254
+ case shimast.KindBinaryExpression:
1255
+ if expression := node.AsBinaryExpression(); expression != nil && expression.OperatorToken != nil {
1256
+ kind = expression.OperatorToken.Kind
1257
+ }
1258
+ case shimast.KindPrefixUnaryExpression:
1259
+ kind = node.AsPrefixUnaryExpression().Operator
1260
+ case shimast.KindPostfixUnaryExpression:
1261
+ kind = node.AsPostfixUnaryExpression().Operator
1262
+ case shimast.KindDeleteExpression:
1263
+ return "delete"
1264
+ case shimast.KindTypeOfExpression:
1265
+ return "typeof"
1266
+ case shimast.KindVoidExpression:
1267
+ return "void"
1268
+ }
1269
+ return astSelectorOperatorText(kind)
1270
+ }
1271
+
1272
+ func astSelectorOperatorText(kind shimast.Kind) string {
1273
+ return shimscanner.TokenToString(kind)
1274
+ }
1275
+
1276
+ func astSelectorVariableKind(node *shimast.Node) string {
1277
+ if node == nil {
1278
+ return ""
1279
+ }
1280
+ list := node
1281
+ if node.Kind == shimast.KindVariableStatement {
1282
+ statement := node.AsVariableStatement()
1283
+ if statement == nil {
1284
+ return ""
1285
+ }
1286
+ list = statement.DeclarationList
1287
+ } else if node.Kind == shimast.KindVariableDeclaration {
1288
+ list = node.Parent
1289
+ }
1290
+ if list == nil || list.Kind != shimast.KindVariableDeclarationList {
1291
+ return ""
1292
+ }
1293
+ flags := list.Flags & shimast.NodeFlagsBlockScoped
1294
+ switch flags {
1295
+ case shimast.NodeFlagsLet:
1296
+ return "let"
1297
+ case shimast.NodeFlagsConst:
1298
+ return "const"
1299
+ case shimast.NodeFlagsUsing:
1300
+ return "using"
1301
+ case shimast.NodeFlagsAwaitUsing:
1302
+ return "await using"
1303
+ default:
1304
+ return "var"
1305
+ }
1306
+ }
1307
+
1308
+ func astSelectorIsGenerator(node *shimast.Node) bool {
1309
+ if node == nil || !isFunctionLikeKind(node) {
1310
+ return false
1311
+ }
1312
+ body := node.BodyData()
1313
+ return body != nil && body.AsteriskToken != nil
1314
+ }
1315
+
1316
+ func astSelectorIsOptional(node *shimast.Node) (bool, bool) {
1317
+ if node == nil {
1318
+ return false, false
1319
+ }
1320
+ switch node.Kind {
1321
+ case shimast.KindPropertyAccessExpression:
1322
+ return node.AsPropertyAccessExpression().QuestionDotToken != nil, true
1323
+ case shimast.KindElementAccessExpression:
1324
+ return node.AsElementAccessExpression().QuestionDotToken != nil, true
1325
+ case shimast.KindCallExpression:
1326
+ return node.AsCallExpression().QuestionDotToken != nil, true
1327
+ case shimast.KindTaggedTemplateExpression:
1328
+ return node.AsTaggedTemplateExpression().QuestionDotToken != nil, true
1329
+ case shimast.KindParameter,
1330
+ shimast.KindNamedTupleMember,
1331
+ shimast.KindMethodDeclaration,
1332
+ shimast.KindShorthandPropertyAssignment,
1333
+ shimast.KindMethodSignature,
1334
+ shimast.KindPropertySignature,
1335
+ shimast.KindPropertyAssignment,
1336
+ shimast.KindPropertyDeclaration,
1337
+ shimast.KindEnumMember,
1338
+ shimast.KindGetAccessor,
1339
+ shimast.KindSetAccessor:
1340
+ return node.QuestionToken() != nil, true
1341
+ }
1342
+ return false, false
1343
+ }
1344
+
1345
+ func astSelectorSupportsStatic(node *shimast.Node) bool {
1346
+ if node == nil {
1347
+ return false
1348
+ }
1349
+ switch node.Kind {
1350
+ case shimast.KindClassStaticBlockDeclaration:
1351
+ return true
1352
+ case shimast.KindPropertyDeclaration,
1353
+ shimast.KindMethodDeclaration,
1354
+ shimast.KindGetAccessor,
1355
+ shimast.KindSetAccessor:
1356
+ return node.Parent != nil &&
1357
+ (node.Parent.Kind == shimast.KindClassDeclaration || node.Parent.Kind == shimast.KindClassExpression)
1358
+ }
1359
+ return false
1360
+ }
1361
+
1362
+ func astSelectorSupportsReadonly(node *shimast.Node) bool {
1363
+ if node == nil {
1364
+ return false
1365
+ }
1366
+ switch node.Kind {
1367
+ case shimast.KindParameter,
1368
+ shimast.KindPropertyDeclaration,
1369
+ shimast.KindPropertySignature,
1370
+ shimast.KindIndexSignature:
1371
+ return true
1372
+ }
1373
+ return false
1374
+ }
1375
+
1376
+ func astSelectorIsDeclared(node *shimast.Node) (bool, bool) {
1377
+ if node == nil {
1378
+ return false, false
1379
+ }
1380
+ declaration := node
1381
+ if node.Kind == shimast.KindVariableDeclaration {
1382
+ declaration = node.Parent
1383
+ }
1384
+ if declaration != nil && declaration.Kind == shimast.KindVariableDeclarationList {
1385
+ declaration = declaration.Parent
1386
+ }
1387
+ if declaration != nil && declaration.Kind == shimast.KindVariableStatement {
1388
+ return hasModifier(declaration, shimast.KindDeclareKeyword), true
1389
+ }
1390
+ if !astSelectorIsDeclaration(node) {
1391
+ return false, false
1392
+ }
1393
+ return hasModifier(node, shimast.KindDeclareKeyword), true
1394
+ }
1395
+
1396
+ func astSelectorIsComputed(node *shimast.Node) (bool, bool) {
1397
+ if node == nil {
1398
+ return false, false
1399
+ }
1400
+ switch node.Kind {
1401
+ case shimast.KindElementAccessExpression, shimast.KindComputedPropertyName:
1402
+ return true, true
1403
+ case shimast.KindPropertyAccessExpression:
1404
+ return false, true
1405
+ case shimast.KindBindingElement:
1406
+ element := node.AsBindingElement()
1407
+ return element != nil && element.PropertyName != nil && element.PropertyName.Kind == shimast.KindComputedPropertyName, true
1408
+ case shimast.KindPropertyAssignment,
1409
+ shimast.KindShorthandPropertyAssignment,
1410
+ shimast.KindMethodDeclaration,
1411
+ shimast.KindMethodSignature,
1412
+ shimast.KindGetAccessor,
1413
+ shimast.KindSetAccessor,
1414
+ shimast.KindPropertyDeclaration,
1415
+ shimast.KindPropertySignature,
1416
+ shimast.KindEnumMember:
1417
+ name := node.Name()
1418
+ return name != nil && name.Kind == shimast.KindComputedPropertyName, true
1419
+ }
1420
+ return false, false
1421
+ }
1422
+
1423
+ func astSelectorStatementBody(node *shimast.Node) astSelectorRuntimeValue {
1424
+ if node == nil {
1425
+ return astSelectorRuntimeValue{}
1426
+ }
1427
+ switch node.Kind {
1428
+ case shimast.KindSourceFile:
1429
+ file := node.AsSourceFile()
1430
+ if file != nil && file.Statements != nil {
1431
+ return astSelectorNodes(file.Statements.Nodes)
1432
+ }
1433
+ case shimast.KindBlock:
1434
+ block := node.AsBlock()
1435
+ if block != nil && block.Statements != nil {
1436
+ return astSelectorNodes(block.Statements.Nodes)
1437
+ }
1438
+ case shimast.KindModuleBlock:
1439
+ block := node.AsModuleBlock()
1440
+ if block != nil && block.Statements != nil {
1441
+ return astSelectorNodes(block.Statements.Nodes)
1442
+ }
1443
+ case shimast.KindCatchClause:
1444
+ if clause := node.AsCatchClause(); clause != nil {
1445
+ return astSelectorNode(clause.Block)
1446
+ }
1447
+ case shimast.KindLabeledStatement:
1448
+ if statement := node.AsLabeledStatement(); statement != nil {
1449
+ return astSelectorNode(statement.Statement)
1450
+ }
1451
+ case shimast.KindClassStaticBlockDeclaration:
1452
+ if block := node.AsClassStaticBlockDeclaration(); block != nil {
1453
+ return astSelectorNode(block.Body)
1454
+ }
1455
+ case shimast.KindIfStatement:
1456
+ return astSelectorNode(node.AsIfStatement().ThenStatement)
1457
+ case shimast.KindWhileStatement:
1458
+ return astSelectorNode(node.AsWhileStatement().Statement)
1459
+ case shimast.KindDoStatement:
1460
+ return astSelectorNode(node.AsDoStatement().Statement)
1461
+ case shimast.KindForStatement:
1462
+ return astSelectorNode(node.AsForStatement().Statement)
1463
+ case shimast.KindForInStatement, shimast.KindForOfStatement:
1464
+ return astSelectorNode(node.AsForInOrOfStatement().Statement)
1465
+ case shimast.KindWithStatement:
1466
+ return astSelectorNode(node.AsWithStatement().Statement)
1467
+ }
1468
+ return astSelectorRuntimeValue{}
1469
+ }
1470
+
1471
+ func astSelectorUnaryArgument(node *shimast.Node) astSelectorRuntimeValue {
1472
+ if node == nil {
1473
+ return astSelectorRuntimeValue{}
1474
+ }
1475
+ switch node.Kind {
1476
+ case shimast.KindPrefixUnaryExpression:
1477
+ return astSelectorNode(node.AsPrefixUnaryExpression().Operand)
1478
+ case shimast.KindPostfixUnaryExpression:
1479
+ return astSelectorNode(node.AsPostfixUnaryExpression().Operand)
1480
+ case shimast.KindDeleteExpression:
1481
+ return astSelectorNode(node.AsDeleteExpression().Expression)
1482
+ case shimast.KindTypeOfExpression:
1483
+ return astSelectorNode(node.AsTypeOfExpression().Expression)
1484
+ case shimast.KindVoidExpression:
1485
+ return astSelectorNode(node.AsVoidExpression().Expression)
1486
+ case shimast.KindAwaitExpression:
1487
+ return astSelectorNode(node.AsAwaitExpression().Expression)
1488
+ case shimast.KindYieldExpression:
1489
+ return astSelectorNode(node.AsYieldExpression().Expression)
1490
+ case shimast.KindReturnStatement:
1491
+ return astSelectorNode(node.AsReturnStatement().Expression)
1492
+ case shimast.KindThrowStatement:
1493
+ return astSelectorNode(node.AsThrowStatement().Expression)
1494
+ case shimast.KindSpreadElement:
1495
+ return astSelectorNode(node.AsSpreadElement().Expression)
1496
+ case shimast.KindSpreadAssignment:
1497
+ return astSelectorNode(node.AsSpreadAssignment().Expression)
1498
+ case shimast.KindBindingElement:
1499
+ element := node.AsBindingElement()
1500
+ if element != nil && element.DotDotDotToken != nil {
1501
+ return astSelectorNode(element.Name())
1502
+ }
1503
+ case shimast.KindParameter:
1504
+ parameter := node.AsParameterDeclaration()
1505
+ if parameter != nil && parameter.DotDotDotToken != nil {
1506
+ return astSelectorNode(parameter.Name())
1507
+ }
1508
+ }
1509
+ return astSelectorRuntimeValue{}
1510
+ }
1511
+
1512
+ func astSelectorExpressionChild(node *shimast.Node) astSelectorRuntimeValue {
1513
+ if node == nil {
1514
+ return astSelectorRuntimeValue{}
1515
+ }
1516
+ switch node.Kind {
1517
+ case shimast.KindPropertyAccessExpression,
1518
+ shimast.KindElementAccessExpression,
1519
+ shimast.KindParenthesizedExpression,
1520
+ shimast.KindCallExpression,
1521
+ shimast.KindNewExpression,
1522
+ shimast.KindExpressionWithTypeArguments,
1523
+ shimast.KindComputedPropertyName,
1524
+ shimast.KindNonNullExpression,
1525
+ shimast.KindTypeAssertionExpression,
1526
+ shimast.KindAsExpression,
1527
+ shimast.KindSatisfiesExpression,
1528
+ shimast.KindTypeOfExpression,
1529
+ shimast.KindSpreadAssignment,
1530
+ shimast.KindSpreadElement,
1531
+ shimast.KindTemplateSpan,
1532
+ shimast.KindDeleteExpression,
1533
+ shimast.KindVoidExpression,
1534
+ shimast.KindAwaitExpression,
1535
+ shimast.KindYieldExpression,
1536
+ shimast.KindPartiallyEmittedExpression,
1537
+ shimast.KindIfStatement,
1538
+ shimast.KindDoStatement,
1539
+ shimast.KindWhileStatement,
1540
+ shimast.KindWithStatement,
1541
+ shimast.KindForInStatement,
1542
+ shimast.KindForOfStatement,
1543
+ shimast.KindSwitchStatement,
1544
+ shimast.KindCaseClause,
1545
+ shimast.KindExpressionStatement,
1546
+ shimast.KindReturnStatement,
1547
+ shimast.KindThrowStatement,
1548
+ shimast.KindExternalModuleReference,
1549
+ shimast.KindExportAssignment,
1550
+ shimast.KindDecorator,
1551
+ shimast.KindJsxExpression,
1552
+ shimast.KindJsxSpreadAttribute:
1553
+ return astSelectorNode(node.Expression())
1554
+ }
1555
+ return astSelectorRuntimeValue{}
1556
+ }
1557
+
1558
+ func astSelectorTestChild(node *shimast.Node) astSelectorRuntimeValue {
1559
+ if node == nil {
1560
+ return astSelectorRuntimeValue{}
1561
+ }
1562
+ switch node.Kind {
1563
+ case shimast.KindIfStatement:
1564
+ return astSelectorNode(node.AsIfStatement().Expression)
1565
+ case shimast.KindWhileStatement:
1566
+ return astSelectorNode(node.AsWhileStatement().Expression)
1567
+ case shimast.KindDoStatement:
1568
+ return astSelectorNode(node.AsDoStatement().Expression)
1569
+ case shimast.KindForStatement:
1570
+ return astSelectorNode(node.AsForStatement().Condition)
1571
+ case shimast.KindConditionalExpression:
1572
+ return astSelectorNode(node.AsConditionalExpression().Condition)
1573
+ case shimast.KindCaseClause:
1574
+ clause := node.AsCaseOrDefaultClause()
1575
+ if clause != nil {
1576
+ return astSelectorNode(clause.Expression)
1577
+ }
1578
+ }
1579
+ return astSelectorRuntimeValue{}
1580
+ }
1581
+
1582
+ func astSelectorPropertyKey(node *shimast.Node) astSelectorRuntimeValue {
1583
+ if node == nil {
1584
+ return astSelectorRuntimeValue{}
1585
+ }
1586
+ switch node.Kind {
1587
+ case shimast.KindPropertyAssignment:
1588
+ return astSelectorNode(node.AsPropertyAssignment().Name())
1589
+ case shimast.KindShorthandPropertyAssignment:
1590
+ return astSelectorNode(node.AsShorthandPropertyAssignment().Name())
1591
+ case shimast.KindBindingElement:
1592
+ element := node.AsBindingElement()
1593
+ if element.PropertyName != nil {
1594
+ return astSelectorNode(element.PropertyName)
1595
+ }
1596
+ return astSelectorNode(element.Name())
1597
+ }
1598
+ return astSelectorNode(node.Name())
1599
+ }
1600
+
1601
+ func astSelectorStatements(node *shimast.Node) astSelectorRuntimeValue {
1602
+ if node == nil {
1603
+ return astSelectorRuntimeValue{}
1604
+ }
1605
+ switch node.Kind {
1606
+ case shimast.KindSourceFile:
1607
+ file := node.AsSourceFile()
1608
+ if file != nil && file.Statements != nil {
1609
+ return astSelectorNodes(file.Statements.Nodes)
1610
+ }
1611
+ case shimast.KindBlock:
1612
+ block := node.AsBlock()
1613
+ if block != nil && block.Statements != nil {
1614
+ return astSelectorNodes(block.Statements.Nodes)
1615
+ }
1616
+ case shimast.KindModuleBlock:
1617
+ block := node.AsModuleBlock()
1618
+ if block != nil && block.Statements != nil {
1619
+ return astSelectorNodes(block.Statements.Nodes)
1620
+ }
1621
+ case shimast.KindCaseClause, shimast.KindDefaultClause:
1622
+ clause := node.AsCaseOrDefaultClause()
1623
+ if clause != nil && clause.Statements != nil {
1624
+ return astSelectorNodes(clause.Statements.Nodes)
1625
+ }
1626
+ }
1627
+ return astSelectorRuntimeValue{}
1628
+ }