123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- "use strict";
- const vk = require("eslint-visitor-keys");
- const debug = require("debug")("eslint:traverser");
- function noop() {
-
- }
- function isNode(x) {
- return x !== null && typeof x === "object" && typeof x.type === "string";
- }
- function getVisitorKeys(visitorKeys, node) {
- let keys = visitorKeys[node.type];
- if (!keys) {
- keys = vk.getKeys(node);
- debug("Unknown node type \"%s\": Estimated visitor keys %j", node.type, keys);
- }
- return keys;
- }
- class Traverser {
- constructor() {
- this._current = null;
- this._parents = [];
- this._skipped = false;
- this._broken = false;
- this._visitorKeys = null;
- this._enter = null;
- this._leave = null;
- }
-
- current() {
- return this._current;
- }
-
- parents() {
- return this._parents.slice(0);
- }
-
- break() {
- this._broken = true;
- }
-
- skip() {
- this._skipped = true;
- }
-
- traverse(node, options) {
- this._current = null;
- this._parents = [];
- this._skipped = false;
- this._broken = false;
- this._visitorKeys = options.visitorKeys || vk.KEYS;
- this._enter = options.enter || noop;
- this._leave = options.leave || noop;
- this._traverse(node, null);
- }
-
- _traverse(node, parent) {
- if (!isNode(node)) {
- return;
- }
- this._current = node;
- this._skipped = false;
- this._enter(node, parent);
- if (!this._skipped && !this._broken) {
- const keys = getVisitorKeys(this._visitorKeys, node);
- if (keys.length >= 1) {
- this._parents.push(node);
- for (let i = 0; i < keys.length && !this._broken; ++i) {
- const child = node[keys[i]];
- if (Array.isArray(child)) {
- for (let j = 0; j < child.length && !this._broken; ++j) {
- this._traverse(child[j], node);
- }
- } else {
- this._traverse(child, node);
- }
- }
- this._parents.pop();
- }
- }
- if (!this._broken) {
- this._leave(node, parent);
- }
- this._current = parent;
- }
-
- static getKeys(node) {
- return vk.getKeys(node);
- }
-
- static traverse(node, options) {
- new Traverser().traverse(node, options);
- }
-
- static get DEFAULT_VISITOR_KEYS() {
- return vk.KEYS;
- }
- }
- module.exports = Traverser;
|