123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- /**
- * merge-estraverse-visitors
- * merge multiple estraverse visitors into one
- *
- * https://github.com/twada/merge-estraverse-visitors
- *
- * Copyright (c) 2016 Takuto Wada
- * Licensed under the MIT license.
- * https://twada.mit-license.org/
- */
- 'use strict';
- var estraverse = require('estraverse');
- function SubVisitor () {
- this.skipStartNode = null;
- this.broken = false;
- }
- SubVisitor.prototype.isBroken = function () {
- return !!this.broken;
- };
- SubVisitor.prototype.markBroken = function () {
- return this.broken = true;
- };
- SubVisitor.prototype.isSkipping = function (controller) {
- return this.skipStartNode && (this.skipStartNode !== controller.current());
- };
- SubVisitor.prototype.startSkipping = function (controller) {
- this.skipStartNode = controller.current();
- };
- SubVisitor.prototype.finishSkippingIfLeavingFrom = function (controller) {
- if (this.skipStartNode === controller.current()) {
- this.skipStartNode = null;
- }
- };
- function noop () {
- }
- function createSubVisitors (visitors) {
- var enters = [];
- var leaves = [];
- var subVisitor, i, v, len = visitors.length;
- for(i = 0; i < len; i += 1) {
- v = visitors[i];
- subVisitor = new SubVisitor();
- subVisitor.enter = (typeof v.enter === 'function') ? v.enter : noop;
- subVisitor.leave = (typeof v.leave === 'function') ? v.leave : noop;
- enters.push(subVisitor);
- leaves.unshift(subVisitor);
- }
- return {
- enters: enters,
- leaves: leaves
- };
- }
- module.exports = function mergeVisitors (visitors) {
- var subVisitors = createSubVisitors(visitors);
- return {
- enter: function (currentNode, parentNode) {
- var orig = this;
- subVisitors.enters.forEach(function (subVisitor) {
- var controller = Object.create(orig);
- if (subVisitor.isBroken()) {
- return;
- }
- if (subVisitor.isSkipping(controller)) {
- return;
- }
- controller.notify = function notify (flag) {
- switch (flag) {
- case estraverse.VisitorOption.Skip:
- subVisitor.startSkipping(controller);
- return;
- case estraverse.VisitorOption.Break:
- subVisitor.markBroken();
- return;
- default:
- orig.notify.call(orig, flag);
- }
- };
- var ret = subVisitor.enter.call(controller, currentNode, parentNode);
- switch (ret) {
- case estraverse.VisitorOption.Skip:
- subVisitor.startSkipping(controller);
- break;
- case estraverse.VisitorOption.Break:
- subVisitor.markBroken();
- break;
- }
- });
- },
- leave: function (currentNode, parentNode) {
- var orig = this;
- var replacements = [];
- subVisitors.leaves.forEach(function (subVisitor) {
- var controller = Object.create(orig);
- if (subVisitor.isBroken()) {
- return;
- }
- if (subVisitor.isSkipping(controller)) {
- return;
- }
- subVisitor.finishSkippingIfLeavingFrom(controller);
- controller.notify = function notify (flag) {
- switch (flag) {
- case estraverse.VisitorOption.Skip:
- // subVisitor.startSkipping(controller); // meaningless
- return;
- case estraverse.VisitorOption.Break:
- subVisitor.markBroken();
- return;
- default:
- orig.notify.call(orig, flag);
- }
- };
- var ret = subVisitor.leave.call(controller, currentNode, parentNode);
- switch (ret) {
- case estraverse.VisitorOption.Skip:
- // subVisitor.startSkipping(controller); // meaningless
- return;
- case estraverse.VisitorOption.Break:
- subVisitor.markBroken();
- return;
- }
- if (typeof ret === 'object' && ret !== null && typeof ret.type === 'string') {
- replacements.push(ret);
- }
- });
- if (replacements.length === 1) {
- return replacements[0];
- }
- return undefined;
- }
- };
- };
|