@@ -208,7 +208,7 @@ export function visit(root, visitor, keyMap) {
208
208
if ( ! isNode ( node ) ) {
209
209
throw new Error ( 'Invalid AST Node: ' + JSON . stringify ( node ) ) ;
210
210
}
211
- var visitFn = getVisitFn ( visitor , isLeaving , node . kind ) ;
211
+ var visitFn = getVisitFn ( visitor , node . kind , isLeaving ) ;
212
212
if ( visitFn ) {
213
213
result = visitFn . call ( visitor , node , key , parent , path , ancestors ) ;
214
214
@@ -263,7 +263,83 @@ function isNode(maybeNode) {
263
263
return maybeNode && typeof maybeNode . kind === 'string' ;
264
264
}
265
265
266
- export function getVisitFn ( visitor , isLeaving , kind ) {
266
+
267
+ /**
268
+ * Creates a new visitor instance which delegates to many visitors to run in
269
+ * parallel. Each visitor will be visited for each node before moving on.
270
+ *
271
+ * Visitors must not directly modify the AST nodes and only returning false to
272
+ * skip sub-branches is supported.
273
+ */
274
+ export function visitInParallel ( visitors ) {
275
+ const skipping = new Array ( visitors . length ) ;
276
+
277
+ return {
278
+ enter ( node ) {
279
+ for ( let i = 0 ; i < visitors . length ; i ++ ) {
280
+ if ( ! skipping [ i ] ) {
281
+ const fn = getVisitFn ( visitors [ i ] , node . kind , /* isLeaving */ false ) ;
282
+ if ( fn ) {
283
+ const result = fn . apply ( visitors [ i ] , arguments ) ;
284
+ if ( result === false ) {
285
+ skipping [ i ] = node ;
286
+ }
287
+ }
288
+ }
289
+ }
290
+ } ,
291
+ leave ( node ) {
292
+ for ( let i = 0 ; i < visitors . length ; i ++ ) {
293
+ if ( ! skipping [ i ] ) {
294
+ const fn = getVisitFn ( visitors [ i ] , node . kind , /* isLeaving */ true ) ;
295
+ if ( fn ) {
296
+ fn . apply ( visitors [ i ] , arguments ) ;
297
+ }
298
+ } else {
299
+ skipping [ i ] = null ;
300
+ }
301
+ }
302
+ }
303
+ } ;
304
+ }
305
+
306
+
307
+ /**
308
+ * Creates a new visitor instance which maintains a provided TypeInfo instance
309
+ * along with visiting visitor.
310
+ *
311
+ * Visitors must not directly modify the AST nodes and only returning false to
312
+ * skip sub-branches is supported.
313
+ */
314
+ export function visitWithTypeInfo ( typeInfo , visitor ) {
315
+ return {
316
+ enter ( node ) {
317
+ typeInfo . enter ( node ) ;
318
+ const fn = getVisitFn ( visitor , node . kind , /* isLeaving */ false ) ;
319
+ if ( fn ) {
320
+ const result = fn . apply ( visitor , arguments ) ;
321
+ if ( result === false ) {
322
+ typeInfo . leave ( node ) ;
323
+ return false ;
324
+ }
325
+ }
326
+ } ,
327
+ leave ( node ) {
328
+ const fn = getVisitFn ( visitor , node . kind , /* isLeaving */ true ) ;
329
+ if ( fn ) {
330
+ fn . apply ( visitor , arguments ) ;
331
+ }
332
+ typeInfo . leave ( node ) ;
333
+ }
334
+ } ;
335
+ }
336
+
337
+
338
+ /**
339
+ * Given a visitor instance, if it is leaving or not, and a node kind, return
340
+ * the function the visitor runtime should call.
341
+ */
342
+ function getVisitFn ( visitor , kind , isLeaving ) {
267
343
var kindVisitor = visitor [ kind ] ;
268
344
if ( kindVisitor ) {
269
345
if ( ! isLeaving && typeof kindVisitor === 'function' ) {
@@ -275,18 +351,18 @@ export function getVisitFn(visitor, isLeaving, kind) {
275
351
// { Kind: { enter() {}, leave() {} } }
276
352
return kindSpecificVisitor ;
277
353
}
278
- return ;
279
- }
280
- var specificVisitor = isLeaving ? visitor . leave : visitor . enter ;
281
- if ( specificVisitor ) {
282
- if ( typeof specificVisitor === 'function' ) {
283
- // { enter() {} , leave() {} }
284
- return specificVisitor ;
285
- }
286
- var specificKindVisitor = specificVisitor [ kind ] ;
287
- if ( typeof specificKindVisitor === 'function' ) {
288
- // { enter: { Kind() {} } , leave: { Kind() {} } }
289
- return specificKindVisitor ;
354
+ } else {
355
+ var specificVisitor = isLeaving ? visitor . leave : visitor . enter ;
356
+ if ( specificVisitor ) {
357
+ if ( typeof specificVisitor === 'function' ) {
358
+ // { enter( ) {} , leave() {} }
359
+ return specificVisitor ;
360
+ }
361
+ var specificKindVisitor = specificVisitor [ kind ] ;
362
+ if ( typeof specificKindVisitor === 'function' ) {
363
+ // { enter: { Kind() {} } , leave: { Kind( ) {} } }
364
+ return specificKindVisitor ;
365
+ }
290
366
}
291
367
}
292
368
}
0 commit comments