function VariableAnalysisSniff::processVariableAsAssignment
* Process a variable that is being assigned. * * This will record that the variable has been defined within a scope so that * later we can determine if it it unused and we can guarantee that any * future uses of the variable are not using an undefined variable. * * References (on either side of an assignment) behave differently and this * function handles those cases as well. * *
Parameters
File $phpcsFile: * @param int $stackPtr * @param string $varName * @param int $currScope * * @return void
1 call to VariableAnalysisSniff::processVariableAsAssignment()
- VariableAnalysisSniff::processVariable in vendor/
sirbrillig/ phpcs-variable-analysis/ VariableAnalysis/ Sniffs/ CodeAnalysis/ VariableAnalysisSniff.php - * Process a normal variable in the code. * * Most importantly, this function determines if the variable use is a "read" * (using the variable for something) or a "write" (an assignment) or, * sometimes, both at once. * …
File
-
vendor/
sirbrillig/ phpcs-variable-analysis/ VariableAnalysis/ Sniffs/ CodeAnalysis/ VariableAnalysisSniff.php, line 1115
Class
Namespace
VariableAnalysis\Sniffs\CodeAnalysisCode
protected function processVariableAsAssignment(File $phpcsFile, $stackPtr, $varName, $currScope) {
Helpers::debug("processVariableAsAssignment: starting for '{$varName}'");
$assignPtr = Helpers::getNextAssignPointer($phpcsFile, $stackPtr);
if (!is_int($assignPtr)) {
return;
}
// If the right-hand-side of the assignment to this variable is a reference
// variable, then this variable is a reference to that one, and as such any
// assignment to this variable (except another assignment by reference,
// which would change the binding) has a side effect of changing the
// referenced variable and therefore should count as both an assignment and
// a read.
$tokens = $phpcsFile->getTokens();
$referencePtr = $phpcsFile->findNext(Tokens::$emptyTokens, $assignPtr + 1, null, true, null, true);
if (is_int($referencePtr) && $tokens[$referencePtr]['code'] === T_BITWISE_AND) {
Helpers::debug("processVariableAsAssignment: found reference variable for '{$varName}'");
$varInfo = $this->getOrCreateVariableInfo($varName, $currScope);
// If the variable was already declared, but was not yet read, it is
// unused because we're about to change the binding; that is, unless we
// are inside a conditional block because in that case the condition may
// never activate.
$scopeInfo = $this->getOrCreateScopeInfo($currScope);
$conditionPointer = Helpers::getClosestConditionPositionIfBeforeOtherConditions($tokens[$referencePtr]['conditions']);
$lastAssignmentPtr = $varInfo->firstDeclared;
if (!$conditionPointer && $lastAssignmentPtr) {
Helpers::debug("processVariableAsAssignment: considering close of scope for '{$varName}' due to reference reassignment");
$this->processScopeCloseForVariable($phpcsFile, $varInfo, $scopeInfo);
}
if ($conditionPointer && $lastAssignmentPtr && $conditionPointer < $lastAssignmentPtr) {
// We may be inside a condition but the last assignment was also inside this condition.
Helpers::debug("processVariableAsAssignment: considering close of scope for '{$varName}' due to reference reassignment ignoring recent condition");
$this->processScopeCloseForVariable($phpcsFile, $varInfo, $scopeInfo);
}
if ($conditionPointer && $lastAssignmentPtr && $conditionPointer > $lastAssignmentPtr) {
Helpers::debug("processVariableAsAssignment: not considering close of scope for '{$varName}' due to reference reassignment because it is conditional");
}
// The referenced variable may have a different name, but we don't
// actually need to mark it as used in this case because the act of this
// assignment will mark it used on the next token.
$varInfo->referencedVariableScope = $currScope;
$this->markVariableDeclaration($varName, ScopeType::LOCAL, null, $stackPtr, $currScope, true);
// An assignment to a reference is a binding and should not count as
// initialization since it doesn't change any values.
$this->markVariableAssignmentWithoutInitialization($varName, $stackPtr, $currScope);
return;
}
Helpers::debug('processVariableAsAssignment: marking as assignment in scope', $currScope);
$this->markVariableAssignment($varName, $stackPtr, $currScope);
// If the left-hand-side of the assignment (the variable we are examining)
// is itself a reference, then that counts as a read as well as a write.
$varInfo = $this->getOrCreateVariableInfo($varName, $currScope);
if ($varInfo->isDynamicReference) {
Helpers::debug('processVariableAsAssignment: also marking as a use because variable is a reference');
$this->markVariableRead($varName, $stackPtr, $currScope);
}
}