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

function toStatements(node) {
  if (t.isBlockStatement(node)) {
    var hasBlockScoped = false;

    for (var i = 0; i < node.body.length; i++) {
      var bodyNode = node.body[i];
      if (t.isBlockScoped(bodyNode)) hasBlockScoped = true;
    }

    if (!hasBlockScoped) {
      return node.body;
    }
  }

  return node;
}

export var metadata = {
  optional: true,
  group: "builtin-setup"
};

export function ReferencedIdentifier(node, parent, scope) {
  var binding = scope.getBinding(node.name);
  if (!binding || binding.references > 1 || !binding.constant) return;
  if (binding.kind === "param" || binding.kind === "module") return;

  var replacement = binding.path.node;
  if (t.isVariableDeclarator(replacement)) {
    replacement = replacement.init;
  }
  if (!replacement) return;

  // ensure it's a "pure" type
  if (!scope.isPure(replacement, true)) return;

  if (t.isClass(replacement) || t.isFunction(replacement)) {
    // don't change this if it's in a different scope, this can be bad
    // for performance since it may be inside a loop or deeply nested in
    // hot code
    if (binding.path.scope.parent !== scope) return;
  }

  if (this.findParent((node) => node === replacement)) {
    return;
  }

  t.toExpression(replacement);
  scope.removeBinding(node.name);
  binding.path.dangerouslyRemove();
  return replacement;
}

export function FunctionDeclaration(node, parent, scope) {
  var bindingInfo = scope.getBinding(node.id.name);
  if (bindingInfo && !bindingInfo.referenced) {
    this.dangerouslyRemove();
  }
}

export { FunctionDeclaration as ClassDeclaration };

export function VariableDeclarator(node, parent, scope) {
  if (!t.isIdentifier(node.id) || !scope.isPure(node.init, true)) return;
  FunctionDeclaration.apply(this, arguments);
}

export function ConditionalExpression(node, parent, scope) {
  var evaluateTest = this.get("test").evaluateTruthy();
  if (evaluateTest === true) {
    return node.consequent;
  } else if (evaluateTest === false) {
    return node.alternate;
  }
}

export var IfStatement = {
  exit(node) {
    var consequent = node.consequent;
    var alternate  = node.alternate;
    var test = node.test;

    var evaluateTest = this.get("test").evaluateTruthy();

    // we can check if a test will be truthy 100% and if so then we can inline
    // the consequent and completely ignore the alternate
    //
    //   if (true) { foo; } -> { foo; }
    //   if ("foo") { foo; } -> { foo; }
    //

    if (evaluateTest === true) {
      return toStatements(consequent);
    }

    // we can check if a test will be falsy 100% and if so we can inline the<commit_msg>remove all non-function statements after completion statements in blocks<commit_after>import * as t from "../../../types";

function toStatements(node) {
  if (t.isBlockStatement(node)) {
    var hasBlockScoped = false;

    for (var i = 0; i < node.body.length; i++) {
      var bodyNode = node.body[i];
      if (t.isBlockScoped(bodyNode)) hasBlockScoped = true;
    }

    if (!hasBlockScoped) {
      return node.body;
    }
  }

  return node;
}

export var metadata = {
  optional: true,
  group: "builtin-basic"
};

export function ReferencedIdentifier(node, parent, scope) {
  var binding = scope.getBinding(node.name);
  if (!binding || binding.references > 1 || !binding.constant) return;
  if (binding.kind === "param" || binding.kind === "module") return;

  var replacement = binding.path.node;
  if (t.isVariableDeclarator(replacement)) {
    replacement = replacement.init;
  }
  if (!replacement) return;

  // ensure it's a "pure" type
  if (!scope.isPure(replacement, true)) return;

  if (t.isClass(replacement) || t.isFunction(replacement)) {
    // don't change this if it's in a different scope, this can be bad
    // for performance since it may be inside a loop or deeply nested in
    // hot code
    if (binding.path.scope.parent !== scope) return;
  }

  if (this.findParent((node) => node === replacement)) {
    return;
  }

  t.toExpression(replacement);
  scope.removeBinding(node.name);
  binding.path.dangerouslyRemove();
  return replacement;
}

export function FunctionDeclaration(node, parent, scope) {
  var bindingInfo = scope.getBinding(node.id.name);
  if (bindingInfo && !bindingInfo.referenced) {
    this.dangerouslyRemove();
  }
}

export { FunctionDeclaration as ClassDeclaration };

export function VariableDeclarator(node, parent, scope) {
  if (!t.isIdentifier(node.id) || !scope.isPure(node.init, true)) return;
  FunctionDeclaration.apply(this, arguments);
}

export function ConditionalExpression(node, parent, scope) {
  var evaluateTest = this.get("test").evaluateTruthy();
  if (evaluateTest === true) {
    return node.consequent;
  } else if (evaluateTest === false) {
    return node.alternate;
  }
}

export function BlockStatement(node) {
  var paths = this.get("body");

  var purge = false;

  for (var i = 0; i < paths.length; i++) {
    let path = paths[i];

    if (!purge && path.isCompletionStatement()) {
      purge = true;
      continue;
    }

    if (purge && !path.isFunctionDeclaration()) {
      path.dangerouslyRemove();
    }
  }
}

export var IfStatement = {
  exit(node) {
    var consequent = node.consequent;
    var alternate  = node.alternate;
    var test = node.test;

    var evaluateTest = this.get("test").evaluateTruthy();

    // we can check if a test will be truthy 100% and if so then we can inline
    // the consequent and completely ignore the alternate
    //
    //   if (true) { foo; } -> { foo; }
    //   if ("foo") { foo; } -> { foo; }
    //

    if (evaluateTest === true) {
      return toStatements(consequent);
    }

    // we can check if a test will be falsy 100% and if so we can inline the
{'fraction_non_alphanumeric': 0.13531239212978943, 'fraction_numerical': 0.0029340697273041077, 'mean_word_length': 3.2268417213712617, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 11, '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': '7394137', 'n_tokens_mistral': 1860, 'n_tokens_neox': 1790, 'n_words': 516}