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;
}