oxc-parser 0.73.2 → 0.75.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.
@@ -0,0 +1,129 @@
1
+ 'use strict';
2
+
3
+ const {
4
+ NODE_TYPE_IDS_MAP,
5
+ NODE_TYPES_COUNT,
6
+ LEAF_NODE_TYPES_COUNT,
7
+ } = require('../generated/deserialize/lazy-types.js');
8
+
9
+ // Getter for private `#visitorsArr` property of `Visitor` class. Initialized in class body below.
10
+ let getVisitorsArr;
11
+
12
+ /**
13
+ * Visitor class, used to visit an AST.
14
+ */
15
+ class Visitor {
16
+ #visitorsArr;
17
+
18
+ /**
19
+ * Create `Visitor`.
20
+ *
21
+ * Provide an object where keys are names of AST nodes you want to visit,
22
+ * and values are visitor functions which receive AST node objects of that type.
23
+ *
24
+ * Keys can also be postfixed with `:exit` to visit when exiting the node, rather than entering.
25
+ *
26
+ * ```js
27
+ * const visitor = new Visitor({
28
+ * BinaryExpression(binExpr) {
29
+ * // Do stuff when entering a `BinaryExpression`
30
+ * },
31
+ * 'BinaryExpression:exit'(binExpr) {
32
+ * // Do stuff when exiting a `BinaryExpression`
33
+ * },
34
+ * });
35
+ * ```
36
+ *
37
+ * @constructor
38
+ * @param {Object} visitor - Object defining visit functions for AST nodes
39
+ * @returns {Visitor}
40
+ */
41
+ constructor(visitor) {
42
+ this.#visitorsArr = createVisitorsArr(visitor);
43
+ }
44
+
45
+ static {
46
+ getVisitorsArr = visitor => visitor.#visitorsArr;
47
+ }
48
+ }
49
+
50
+ module.exports = { Visitor, getVisitorsArr };
51
+
52
+ /**
53
+ * Create array of visitors, keyed by node type ID.
54
+ *
55
+ * Each element of array is one of:
56
+ *
57
+ * * No visitor for this type = `null`.
58
+ * * Visitor for leaf node = visit function.
59
+ * * Visitor for non-leaf node = object of form `{ enter, exit }`,
60
+ * where each property is either a visitor function or `null`.
61
+ *
62
+ * @param {Object} visitor - Visitors object from user
63
+ * @returns {Array<Object|function|null>} - Array of visitors
64
+ */
65
+ function createVisitorsArr(visitor) {
66
+ if (visitor === null || typeof visitor !== 'object') {
67
+ throw new Error('`visitors` must be an object');
68
+ }
69
+
70
+ // Create empty visitors array
71
+ const visitorsArr = [];
72
+ for (let i = NODE_TYPES_COUNT; i !== 0; i--) {
73
+ visitorsArr.push(null);
74
+ }
75
+
76
+ // Populate visitors array from provided object
77
+ for (let name of Object.keys(visitor)) {
78
+ const visitFn = visitor[name];
79
+ if (typeof visitFn !== 'function') {
80
+ throw new Error(`'${name}' property of \`visitors\` object is not a function`);
81
+ }
82
+
83
+ const isExit = name.endsWith(':exit');
84
+ if (isExit) name = name.slice(0, -5);
85
+
86
+ const typeId = NODE_TYPE_IDS_MAP.get(name);
87
+ if (typeId === void 0) throw new Error(`Unknown node type '${name}' in \`visitors\` object`);
88
+
89
+ if (typeId < LEAF_NODE_TYPES_COUNT) {
90
+ // Leaf node. Store just 1 function.
91
+ const existingVisitFn = visitorsArr[typeId];
92
+ if (existingVisitFn === null) {
93
+ visitorsArr[typeId] = visitFn;
94
+ } else if (isExit) {
95
+ visitorsArr[typeId] = combineVisitFunctions(existingVisitFn, visitFn);
96
+ } else {
97
+ visitorsArr[typeId] = combineVisitFunctions(visitFn, existingVisitFn);
98
+ }
99
+ continue;
100
+ }
101
+
102
+ let enterExit = visitorsArr[typeId];
103
+ if (enterExit === null) {
104
+ enterExit = visitorsArr[typeId] = { enter: null, exit: null };
105
+ }
106
+
107
+ if (isExit) {
108
+ enterExit.exit = visitFn;
109
+ } else {
110
+ enterExit.enter = visitFn;
111
+ }
112
+ }
113
+
114
+ return visitorsArr;
115
+ }
116
+
117
+ /**
118
+ * Combine 2 visitor functions into 1.
119
+ *
120
+ * @param {function} visit1 - 1st visitor function
121
+ * @param {function} visit2 - 2nd visitor function
122
+ * @returns {function} - Combined visitor function
123
+ */
124
+ function combineVisitFunctions(visit1, visit2) {
125
+ return function(node) {
126
+ visit1(node);
127
+ visit2(node);
128
+ };
129
+ }