text: "use strict";
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.traverseNodes = exports.getNodes = exports.getKeys = exports.getFallbackKeys = void 0;
  const visitor_keys_1 = require("./visitor-keys");
  /**
   * Check that the given key should be traversed or not.
   * @this {Traversable}
   * @param key The key to check.
   * @returns `true` if the key should be traversed.
   */
  function fallbackKeysFilter(key) {
      let value = null;
      return (key !== "comments" &&
          key !== "leadingComments" &&
          key !== "loc" &&
          key !== "parent" &&
          key !== "range" &&
          key !== "tokens" &&
          key !== "trailingComments" &&
          (value = this[key]) !== null &&
          typeof value === "object" &&
          (typeof value.type === "string" || Array.isArray(value)));
  }
  /**
   * Get the keys of the given node to traverse it.
   * @param node The node to get.
   * @returns The keys to traverse.
   */
  function getFallbackKeys(node) {
      return Object.keys(node).filter(fallbackKeysFilter, node);
  }
  exports.getFallbackKeys = getFallbackKeys;
  /**
   * Get the keys of the given node to traverse it.
   * @param node The node to get.
   * @returns The keys to traverse.
   */
  function getKeys(node, visitorKeys) {
      const keys = (visitorKeys || visitor_keys_1.KEYS)[node.type] || getFallbackKeys(node);
      return keys.filter((key) => !getNodes(node, key).next().done);
  }
  exports.getKeys = getKeys;
  /**
   * Get the nodes of the given node.
   * @param node The node to get.
   */
  function* getNodes(node, key) {
      const child = node[key];
      if (Array.isArray(child)) {
          for (const c of child) {
              if (isNode(c)) {
                  yield c;
              }
          }
      }
      else if (isNode(child)) {
          yield child;
      }
  }
  exports.getNodes = getNodes;
  /**
   * Check whether a given value is a node.
   * @param x The value to check.
   * @returns `true` if the value is a node.
   */
  function isNode(x) {
      return x !== null && typeof x === "object" && typeof x.type === "string";
  }
  /**
   * Traverse the given node.
   * @param node The node to traverse.
   * @param parent The parent node.
   * @param visitor The node visitor.
   */
  function traverse(node, parent, visitor) {
      visitor.enterNode(node, parent);
      const keys = getKeys(node, visitor.visitorKeys);
      for (const key of keys) {
          for (const child of getNodes(node, key)) {
              traverse(child, node, visitor);
          }
      }
      visitor.leaveNode(node, parent);
  }
  /**
   * Traverse the given AST tree.
   * @param node Root node to traverse.
   * @param visitor Visitor.
   */
  function traverseNodes(node, visitor) {
      traverse(node, null, visitor);
  }
  exports.traverseNodes = traverseNodes;
  