Skip to content

Commit 4f54eb8

Browse files
authored
Simplify handling static variables (#32)
* Add getStackPtrIfVariableIsUnused to remove code duplication * Simplify checking for previous token in checkForStaticMember * Move Self/StaticOutsideClass to checkForStaticOutsideClass * Simplify checkForStaticOutsideClass * Remove unused processMemberVar
1 parent 208ce49 commit 4f54eb8

File tree

1 file changed

+77
-49
lines changed

1 file changed

+77
-49
lines changed

VariableAnalysis/Sniffs/CodeAnalysis/VariableAnalysisSniff.php

Lines changed: 77 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -511,48 +511,83 @@ protected function checkForStaticMember(File $phpcsFile, $stackPtr, $varName, $c
511511
$tokens = $phpcsFile->getTokens();
512512
$token = $tokens[$stackPtr];
513513

514-
// Are we a static member?
515514
$doubleColonPtr = $stackPtr - 1;
516515
if ($tokens[$doubleColonPtr]['code'] !== T_DOUBLE_COLON) {
517516
return false;
518517
}
519518
$classNamePtr = $stackPtr - 2;
520-
if (($tokens[$classNamePtr]['code'] !== T_STRING)
521-
&& ($tokens[$classNamePtr]['code'] !== T_SELF)
522-
&& ($tokens[$classNamePtr]['code'] !== T_STATIC)) {
519+
$staticReferences = [
520+
T_STRING,
521+
T_SELF,
522+
T_STATIC,
523+
];
524+
if (! in_array($tokens[$classNamePtr]['code'], $staticReferences, true)) {
523525
return false;
524526
}
527+
return true;
528+
}
525529

530+
protected function checkForStaticOutsideClass(File $phpcsFile, $stackPtr, $varName, $currScope) {
526531
// Are we refering to self:: outside a class?
527532
// TODO: not sure this is our business or should be some other sniff.
528-
if (($tokens[$classNamePtr]['code'] === T_SELF) || ($tokens[$classNamePtr]['code'] === T_STATIC)) {
529-
if ($tokens[$classNamePtr]['code'] === T_SELF) {
530-
$err_class = 'SelfOutsideClass';
531-
$err_desc = 'self::';
532-
} else {
533-
$err_class = 'StaticOutsideClass';
534-
$err_desc = 'static::';
533+
534+
$tokens = $phpcsFile->getTokens();
535+
$token = $tokens[$stackPtr];
536+
537+
$doubleColonPtr = $stackPtr - 1;
538+
if ($tokens[$doubleColonPtr]['code'] !== T_DOUBLE_COLON) {
539+
return false;
540+
}
541+
$classNamePtr = $stackPtr - 2;
542+
$code = $tokens[$classNamePtr]['code'];
543+
$staticReferences = [
544+
T_SELF,
545+
T_STATIC,
546+
];
547+
if (! in_array($code, $staticReferences, true)) {
548+
return false;
549+
}
550+
$errorClass = $code === T_SELF ? 'SelfOutsideClass' : 'StaticOutsideClass';
551+
$staticRefType = $code === T_SELF ? 'self::' : 'static::';
552+
if (!empty($token['conditions'])) {
553+
if ($this->areAnyConditionsAClosure($phpcsFile, $token['conditions'])) {
554+
$phpcsFile->addError("Use of {$staticRefType}%s inside closure.", $stackPtr, $errorClass, ["\${$varName}"]);
555+
return true;
535556
}
536-
if (!empty($token['conditions'])) {
537-
foreach (array_reverse($token['conditions'], true) as $scopePtr => $scopeCode) {
538-
// self within a closure is invalid
539-
// Note: have to fetch code from $tokens, T_CLOSURE isn't set for conditions codes.
540-
if ($tokens[$scopePtr]['code'] === T_CLOSURE) {
541-
$phpcsFile->addError("Use of {$err_desc}%s inside closure.", $stackPtr, $err_class, ["\${$varName}"]);
542-
return true;
543-
}
544-
if ($scopeCode === T_CLASS) {
545-
return true;
546-
}
547-
}
557+
if ($this->areAnyConditionsAClass($token['conditions'])) {
558+
return true;
548559
}
549-
$phpcsFile->addError("Use of {$err_desc}%s outside class definition.", $stackPtr, $err_class, ["\${$varName}"]);
550-
return true;
551560
}
552-
561+
$phpcsFile->addError(
562+
"Use of {$staticRefType}%s outside class definition.",
563+
$stackPtr,
564+
$errorClass,
565+
["\${$varName}"]
566+
);
553567
return true;
554568
}
555569

570+
protected function areAnyConditionsAClosure($phpcsFile, $conditions) {
571+
// self within a closure is invalid
572+
$tokens = $phpcsFile->getTokens();
573+
foreach (array_reverse($conditions, true) as $scopePtr => $scopeCode) {
574+
// Note: have to fetch code from $tokens, T_CLOSURE isn't set for conditions codes.
575+
if ($tokens[$scopePtr]['code'] === T_CLOSURE) {
576+
return true;
577+
}
578+
}
579+
return false;
580+
}
581+
582+
protected function areAnyConditionsAClass($conditions) {
583+
foreach (array_reverse($conditions, true) as $scopePtr => $scopeCode) {
584+
if ($scopeCode === T_CLASS) {
585+
return true;
586+
}
587+
}
588+
return false;
589+
}
590+
556591
protected function checkForAssignment(File $phpcsFile, $stackPtr, $varName, $currScope) {
557592
$tokens = $phpcsFile->getTokens();
558593
$token = $tokens[$stackPtr];
@@ -773,18 +808,6 @@ protected function checkForSymbolicObjectProperty(File $phpcsFile, $stackPtr, $v
773808
return true;
774809
}
775810

776-
/**
777-
* Called to process class member vars.
778-
*
779-
* @param File $phpcsFile The PHP_CodeSniffer file where this token was found.
780-
* @param int $stackPtr The position where the token was found.
781-
*/
782-
protected function processMemberVar(File $phpcsFile, $stackPtr) {
783-
$tokens = $phpcsFile->getTokens();
784-
$token = $tokens[$stackPtr];
785-
// TODO: don't care for now
786-
}
787-
788811
/**
789812
* Called to process normal member vars.
790813
*
@@ -846,6 +869,11 @@ protected function processVariable(File $phpcsFile, $stackPtr) {
846869
return;
847870
}
848871

872+
// Check for static members used outside a class
873+
if ($this->checkForStaticOutsideClass($phpcsFile, $stackPtr, $varName, $currScope)) {
874+
return;
875+
}
876+
849877
// $var part of class::$var static member
850878
if ($this->checkForStaticMember($phpcsFile, $stackPtr, $varName, $currScope)) {
851879
return;
@@ -1015,27 +1043,27 @@ protected function processScopeCloseForVariable($phpcsFile, $varInfo) {
10151043
// of "unused variable" warnings.
10161044
return;
10171045
}
1018-
if (isset($varInfo->firstDeclared)) {
1046+
$stackPtr = $this->getStackPtrIfVariableIsUnused($varInfo);
1047+
if ($stackPtr) {
10191048
$phpcsFile->addWarning(
10201049
"Unused %s %s.",
1021-
$varInfo->firstDeclared,
1050+
$stackPtr,
10221051
'UnusedVariable',
10231052
[
10241053
VariableInfo::$scopeTypeDescriptions[$varInfo->scopeType],
10251054
"\${$varInfo->name}",
10261055
]
10271056
);
10281057
}
1058+
}
1059+
1060+
protected function getStackPtrIfVariableIsUnused($varInfo) {
1061+
if (isset($varInfo->firstDeclared)) {
1062+
return $varInfo->firstDeclared;
1063+
}
10291064
if (isset($varInfo->firstInitialized)) {
1030-
$phpcsFile->addWarning(
1031-
"Unused %s %s.",
1032-
$varInfo->firstInitialized,
1033-
'UnusedVariable',
1034-
[
1035-
VariableInfo::$scopeTypeDescriptions[$varInfo->scopeType],
1036-
"\${$varInfo->name}",
1037-
]
1038-
);
1065+
return $varInfo->firstInitialized;
10391066
}
1067+
return null;
10401068
}
10411069
}

0 commit comments

Comments
 (0)