Skip to content

Commit 3b26bf3

Browse files
committed
refactor(linter/plugins): split adding visit function to compiler visitor into multiple functions (#14433)
Pure refactor. Split code for adding a visitor function to compiled visitor into multiple functions. This PR does not alter the code in any way, just splits it up. This is a preparatory step for implementing selectors DSL.
1 parent af3a75e commit 3b26bf3

File tree

1 file changed

+88
-57
lines changed

1 file changed

+88
-57
lines changed

apps/oxlint/src-js/plugins/visitor.ts

Lines changed: 88 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@
7373
// it will avoid full GC runs, which should greatly improve performance.
7474

7575
import { LEAF_NODE_TYPES_COUNT, NODE_TYPE_IDS_MAP, NODE_TYPES_COUNT } from '../generated/type_ids.js';
76-
import { assertIs } from './utils.js';
7776

7877
import type { CompiledVisitorEntry, EnterExit, Node, VisitFn, Visitor } from './types.ts';
7978

@@ -223,64 +222,96 @@ export function addVisitorToCompiled(visitor: Visitor): void {
223222

224223
const typeId = NODE_TYPE_IDS_MAP.get(name);
225224
if (typeId === void 0) throw new Error(`Unknown node type '${name}' in visitor object`);
225+
addVisitFn(typeId, isExit, visitFn);
226+
}
227+
}
228+
229+
/**
230+
* Add visit function to compiled visitor.
231+
* @param typeId - Node type ID
232+
* @param isExit - `true` if is an exit visitor
233+
* @param visitFn - Visit function
234+
*/
235+
function addVisitFn(typeId: number, isExit: boolean, visitFn: VisitFn): void {
236+
if (typeId < LEAF_NODE_TYPES_COUNT) {
237+
addLeafVisitFn(typeId, isExit, visitFn);
238+
} else {
239+
addNonLeafVisitFn(typeId, isExit, visitFn);
240+
}
241+
}
242+
243+
/**
244+
* Add visit function for a leaf node to compiled visitor.
245+
*
246+
* Stored as just 1 function, not enter+exit pair.
247+
*
248+
* @param typeId - Node type ID
249+
* @param isExit - `true` if is an exit visitor
250+
* @param visitFn - Visit function
251+
*/
252+
function addLeafVisitFn(typeId: number, isExit: boolean, visitFn: VisitFn): void {
253+
const existing = compiledVisitor[typeId] as CompilingLeafVisitorEntry;
254+
255+
if (existing === null) {
256+
compiledVisitor[typeId] = visitFn;
257+
} else if (isArray(existing)) {
258+
if (isExit) {
259+
existing.push(visitFn);
260+
} else {
261+
// Insert before last in array in case last was enter visit function from the current rule,
262+
// to ensure enter is called before exit.
263+
// It could also be either an enter or exit visitor function for another rule, but the order
264+
// rules are called in doesn't matter. We only need to make sure that a rule's exit visitor
265+
// isn't called before enter visitor *for that same rule*.
266+
existing.splice(existing.length - 1, 0, visitFn);
267+
}
268+
} else {
269+
// Same as above, enter visitor is put to front of list to make sure enter is called before exit
270+
(compiledVisitor as CompilingVisitor)[typeId] = isExit
271+
? createVisitFnArray(existing, visitFn)
272+
: createVisitFnArray(visitFn, existing);
273+
mergedLeafVisitorTypeIds.push(typeId);
274+
}
275+
}
276+
277+
/**
278+
* Add visit function for a non-leaf node to compiled visitor.
279+
*
280+
* Stored as enter+exit pair.
281+
*
282+
* @param typeId - Node type ID
283+
* @param isExit - `true` if is an exit visitor
284+
* @param visitFn - Visit function
285+
*/
286+
function addNonLeafVisitFn(typeId: number, isExit: boolean, visitFn: VisitFn): void {
287+
const existing = compiledVisitor[typeId] as CompilingNonLeafVisitorEntry;
226288

227-
const existing = (compiledVisitor as CompilingVisitor)[typeId];
228-
if (typeId < LEAF_NODE_TYPES_COUNT) {
229-
// Leaf node - store just 1 function, not enter+exit pair
230-
assertIs<CompilingLeafVisitorEntry>(existing);
231-
232-
if (existing === null) {
233-
compiledVisitor[typeId] = visitFn;
234-
} else if (isArray(existing)) {
235-
if (isExit) {
236-
existing.push(visitFn);
237-
} else {
238-
// Insert before last in array in case last was enter visit function from the current rule,
239-
// to ensure enter is called before exit.
240-
// It could also be either an enter or exit visitor function for another rule, but the order
241-
// rules are called in doesn't matter. We only need to make sure that a rule's exit visitor
242-
// isn't called before enter visitor *for that same rule*.
243-
existing.splice(existing.length - 1, 0, visitFn);
244-
}
245-
} else {
246-
// Same as above, enter visitor is put to front of list to make sure enter is called before exit
247-
(compiledVisitor as CompilingVisitor)[typeId] = isExit
248-
? createVisitFnArray(existing, visitFn)
249-
: createVisitFnArray(visitFn, existing);
250-
mergedLeafVisitorTypeIds.push(typeId);
251-
}
289+
if (existing === null) {
290+
const enterExit = compiledVisitor[typeId] = getEnterExitObject();
291+
if (isExit) {
292+
enterExit.exit = visitFn;
293+
} else {
294+
enterExit.enter = visitFn;
295+
}
296+
} else if (isExit) {
297+
const { exit } = existing;
298+
if (exit === null) {
299+
existing.exit = visitFn;
300+
} else if (isArray(exit)) {
301+
exit.push(visitFn);
302+
} else {
303+
existing.exit = createVisitFnArray(exit, visitFn);
304+
mergedExitVisitorTypeIds.push(typeId);
305+
}
306+
} else {
307+
const { enter } = existing;
308+
if (enter === null) {
309+
existing.enter = visitFn;
310+
} else if (isArray(enter)) {
311+
enter.push(visitFn);
252312
} else {
253-
// Not leaf node - store enter+exit pair
254-
assertIs<CompilingNonLeafVisitorEntry>(existing);
255-
256-
if (existing === null) {
257-
const enterExit = compiledVisitor[typeId] = getEnterExitObject();
258-
if (isExit) {
259-
enterExit.exit = visitFn;
260-
} else {
261-
enterExit.enter = visitFn;
262-
}
263-
} else if (isExit) {
264-
const { exit } = existing;
265-
if (exit === null) {
266-
existing.exit = visitFn;
267-
} else if (isArray(exit)) {
268-
exit.push(visitFn);
269-
} else {
270-
existing.exit = createVisitFnArray(exit, visitFn);
271-
mergedExitVisitorTypeIds.push(typeId);
272-
}
273-
} else {
274-
const { enter } = existing;
275-
if (enter === null) {
276-
existing.enter = visitFn;
277-
} else if (isArray(enter)) {
278-
enter.push(visitFn);
279-
} else {
280-
existing.enter = createVisitFnArray(enter, visitFn);
281-
mergedEnterVisitorTypeIds.push(typeId);
282-
}
283-
}
313+
existing.enter = createVisitFnArray(enter, visitFn);
314+
mergedEnterVisitorTypeIds.push(typeId);
284315
}
285316
}
286317
}

0 commit comments

Comments
 (0)