@@ -208,7 +208,7 @@ export function visit(root, visitor, keyMap) {
208208 if ( ! isNode ( node ) ) {
209209 throw new Error ( 'Invalid AST Node: ' + JSON . stringify ( node ) ) ;
210210 }
211- var visitFn = getVisitFn ( visitor , isLeaving , node . kind ) ;
211+ var visitFn = getVisitFn ( visitor , node . kind , isLeaving ) ;
212212 if ( visitFn ) {
213213 result = visitFn . call ( visitor , node , key , parent , path , ancestors ) ;
214214
@@ -263,7 +263,83 @@ function isNode(maybeNode) {
263263 return maybeNode && typeof maybeNode . kind === 'string' ;
264264}
265265
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 ) {
267343 var kindVisitor = visitor [ kind ] ;
268344 if ( kindVisitor ) {
269345 if ( ! isLeaving && typeof kindVisitor === 'function' ) {
@@ -275,18 +351,18 @@ export function getVisitFn(visitor, isLeaving, kind) {
275351 // { Kind: { enter() {}, leave() {} } }
276352 return kindSpecificVisitor ;
277353 }
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+ }
290366 }
291367 }
292368}
0 commit comments