<commit_before>import NodePath from "./index";
import * as t from "../../types";

/**
 * Description
 */

export function getStatementParent(): ?NodePath {
  var path = this;

  do {
    if (!path.parentPath || (Array.isArray(path.container) && path.isStatement())) {
      break;
    } else {
      path = path.parentPath;
    }
  } while (path);

  if (path && (path.isProgram() || path.isFile())) {
    throw new Error("File/Program node, we can't possibly find a statement parent to this");
  }

  return path;
}

/**
 * Description
 */

export function getOpposite() {
  if (this.key === "left") {
    return this.getSibling("right");
  } else if (this.key === "right") {
    return this.getSibling("left");
  }
}

/**
 * Description
 */

export function getCompletionRecords(): Array<NodePath> {
  var paths = [];

  var add = function (path) {
    if (path) paths = paths.concat(path.getCompletionRecords());
  };

  if (this.isIfStatement()) {
    add(this.get("consequent"));
    add(this.get("alternate"));
  } else if (this.isDoExpression() || this.isFor() || this.isWhile()) {
    add(this.get("body"));
  } else if (this.isProgram() || this.isBlockStatement()) {
    add(this.get("body").pop());
  } else if (this.isFunction()) {
    return this.get("body").getCompletionRecords();
  } else {
    paths.push(this);
  }

  return paths;
}

/**
 * Description
 */

export function getSibling(key) {
  return NodePath.get({
    parentPath: this.parentPath,
    parent: this.parent,
    container: this.container,
    listKey: this.listKey,
    key: key
  });
}

/**
 * Description
 */

export function get(key: string): NodePath {
  var parts = key.split(".");
  if (parts.length === 1) { // "foo"
    return this._getKey(key);
  } else { // "foo.bar"
    return this._getPattern(parts);
  }
}

/**
 * Description
 */

export function _getKey(key) {
  var node      = this.node;
  var container = node[key];

  if (Array.isArray(container)) {
    // requested a container so give them all the paths
    return container.map((_, i) => {
      return NodePath.get({
        listKey: key,
        parentPath: this,
        parent: node,
        container: container,
        key: i
      }).setContext();
    });
  } else {
    return NodePath.get({
      parentPath: this,
      parent: node,
      container: node,
      key: key
    }).setContext();
  }
}

/**
 * Description
 */

export function _getPattern(parts) {
  var path = this;
  for (var part of (parts: Array)) {
    if (part === ".") {
      path = path.parentPath;
    } else {
      if (Array.isArray(path)) {
        path = path[part];
      } else {
        path = path.get(part);
      }
    }
  }
  return path;
}

/**
 * Description
 */

export function getBindingIdentifiers(duplicates?) {
  return t.getBindingIdentifiers(this.node, duplicates);
}
<commit_msg>add optional context parameter to NodePath#get<commit_after>import NodePath from "./index";
import * as t from "../../types";

/**
 * Description
 */

export function getStatementParent(): ?NodePath {
  var path = this;

  do {
    if (!path.parentPath || (Array.isArray(path.container) && path.isStatement())) {
      break;
    } else {
      path = path.parentPath;
    }
  } while (path);

  if (path && (path.isProgram() || path.isFile())) {
    throw new Error("File/Program node, we can't possibly find a statement parent to this");
  }

  return path;
}

/**
 * Description
 */

export function getOpposite() {
  if (this.key === "left") {
    return this.getSibling("right");
  } else if (this.key === "right") {
    return this.getSibling("left");
  }
}

/**
 * Description
 */

export function getCompletionRecords(): Array {
  var paths = [];

  var add = function (path) {
    if (path) paths = paths.concat(path.getCompletionRecords());
  };

  if (this.isIfStatement()) {
    add(this.get("consequent"));
    add(this.get("alternate"));
  } else if (this.isDoExpression() || this.isFor() || this.isWhile()) {
    add(this.get("body"));
  } else if (this.isProgram() || this.isBlockStatement()) {
    add(this.get("body").pop());
  } else if (this.isFunction()) {
    return this.get("body").getCompletionRecords();
  } else {
    paths.push(this);
  }

  return paths;
}

/**
 * Description
 */

export function getSibling(key) {
  return NodePath.get({
    parentPath: this.parentPath,
    parent: this.parent,
    container: this.container,
    listKey: this.listKey,
    key: key
  });
}

/**
 * Description
 */

export function get(key: string, context?: boolean | TraversalContext): NodePath {
  if (context === true) context = this.context;
  var parts = key.split(".");
  if (parts.length === 1) { // "foo"
    return this._getKey(key, context);
  } else { // "foo.bar"
    return this._getPattern(parts, context);
  }
}

/**
 * Description
 */

export function _getKey(key, context?) {
  var node      = this.node;
  var container = node[key];

  if (Array.isArray(container)) {
    // requested a container so give them all the paths
    return container.map((_, i) => {
      return NodePath.get({
        listKey: key,
        parentPath: this,
        parent: node,
        container: container,
        key: i
      }).setContext(context);
    });
  } else {
    return NodePath.get({
      parentPath: this,
      parent: node,
      container: node,
      key: key
    }).setContext(context);
  }
}

/**
 * Description
 */

export function _getPattern(parts, context) {
  var path = this;
  for (var part of (parts: Array)) {
    if (part === ".") {
      path = path.parentPath;
    } else {
      if (Array.isArray(path)) {
        path = path[part];
      } else {
        path = path.get(part, context);
      }
    }
  }
  return path;
}

/**
 * Description
 */

export function getBindingIdentifiers(duplicates?) {
  return t.getBindingIdentifiers(this.node, duplicates);
}

{'fraction_non_alphanumeric': 0.1652708938642967, 'fraction_numerical': 0.0003418219107844813, 'mean_word_length': 2.734524569240587, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5696907', 'n_tokens_mistral': 1890, 'n_tokens_neox': 1878, 'n_words': 456}