private function isVariableAssignment()

in src/Linters/UnusedVariableLinter.hack [262:322]


  private function isVariableAssignment(
    VariableExpression $var,
    vec<Node> $parents,
  ): bool {
    foreach (Vec\reverse($parents) as $parent) {
      if ($parent === $var) {
        continue;
      }

      // Too early to tell
      if ($parent is ListItem<_> || $parent is NodeList<_>) {
        continue;
      }

      // SubscriptExpression
      // $a[$b]
      // ^^ ^^
      // |  +-- index
      // +-- receiver
      //
      // A variable in the index of a subscript expression is never an assignment
      // A variable that is the receiver of a subscript expression may be an assignment or use; continue until a BinaryExpression is found.
      //
      // $a[$b] = '123'; // assignment of $a, use of $b
      // f($a[$b]);      // use of $a
      if ($parent is SubscriptExpression) {
        $index = $parent->getIndex();
        if ($index !== null && $index->isAncestorOf($var)) {
          return false;
        } else {
          continue;
        }
      }

      if (
        $parent is BinaryExpression &&
        $this->isAssignmentExpression($parent) &&
        $parent->getLeftOperand()->isAncestorOf($var)
      ) {
        return true;
      }

      if (
        $parent is ForeachStatement &&
        (($parent->getValue() === $var) || ($parent->getKey() === $var))
      ) {
        return true;
      }

      if (
        $parent is ListExpression &&
        (bool)$parent->getMembers()?->isAncestorOf($var)
      ) {
        return true;
      }

      break;
    }

    return false;
  }