Skip to content

Commit

Permalink
Support for static member vars. Report on use of self::$var outside c…
Browse files Browse the repository at this point in the history
…lass scope. Consolidate unit test list of warnings and errors.
  • Loading branch information
illusori committed Jul 20, 2011
1 parent a73bde8 commit 372456c
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 56 deletions.
1 change: 1 addition & 0 deletions README
Expand Up @@ -7,6 +7,7 @@ variable use.
* Warns on use of undefined variables.
* Warns if variables are set or declared but never used within that scope.
* Warns if variables are redeclared within same scope.
* Warns if self::$static_member is used outside class scope.

INSTALLATION

Expand Down
56 changes: 56 additions & 0 deletions Sniffs/CodeAnalysis/VariableAnalysisSniff.php
Expand Up @@ -566,6 +566,56 @@ protected function checkForThisWithinClass(
return false;
}

protected function checkForStaticMember(
PHP_CodeSniffer_File $phpcsFile,
$stackPtr,
$varName,
$currScope
) {
$tokens = $phpcsFile->getTokens();
$token = $tokens[$stackPtr];

// Are we a static member?
$doubleColonPtr = $stackPtr - 1;
if ($tokens[$doubleColonPtr]['code'] !== T_DOUBLE_COLON) {
return false;
}
$classNamePtr = $stackPtr - 2;
if (($tokens[$classNamePtr]['code'] !== T_STRING) &&
($tokens[$classNamePtr]['code'] !== T_SELF)) {
return false;
}

//echo "found className " . $tokens[$classNamePtr]['content'] . "\n";

// Are we refering to self:: outside a class?
// TODO: not sure this is our business or should be some other sniff.
if ($tokens[$classNamePtr]['code'] === T_SELF) {
//echo "found self, like totally trippin'\n";
if (!empty($token['conditions'])) {
foreach (array_reverse($token['conditions'], true) as $scopePtr => $scopeCode) {
// self within a closure is invalid
// Note: have to fetch code from $tokens, T_CLOSURE isn't set for conditions codes.
if ($tokens[$scopePtr]['code'] === T_CLOSURE) {
$phpcsFile->addError("Use of self::%s inside closure.", $stackPtr,
'SelfOutsideClass',
array("\${$varName}"));
return true;
}
if ($scopeCode === T_CLASS) {
return true;
}
}
}
$phpcsFile->addError("Use of self::%s outside class definition.", $stackPtr,
'SelfOutsideClass',
array("\${$varName}"));
return true;
}

return true;
}

protected function checkForAssignment(
PHP_CodeSniffer_File $phpcsFile,
$stackPtr,
Expand Down Expand Up @@ -827,6 +877,7 @@ protected function processVariable(
// Is closure use declaration of a variable defined within containing scope
// catch (...) block start
// $this within a class (but not within a closure).
// $var part of class::$var static member
// Assignment via =
// Assignment via list (...) =
// Declares as a global
Expand All @@ -849,6 +900,11 @@ protected function processVariable(
return;
}

// $var part of class::$var static member
if ($this->checkForStaticMember($phpcsFile, $stackPtr, $varName, $currScope)) {
return;
}

// Is the next non-whitespace an assignment?
if ($this->checkForAssignment($phpcsFile, $stackPtr, $varName, $currScope)) {
return;
Expand Down
22 changes: 22 additions & 0 deletions Tests/CodeAnalysis/VariableAnalysisUnitTest.inc
Expand Up @@ -158,22 +158,32 @@ class ClassWithoutMembers {

function method_with_member_var() {
echo $this->member_var;
echo self::$static_member_var;
}
}

class ClassWithMembers {
public $member_var;
static $static_member_var;

function method_with_member_var() {
echo $this->member_var;
echo $this->no_such_member_var;
echo self::$static_member_var;
echo self::$no_such_static_member_var;
echo SomeOtherClass::$external_static_member_var;
}
}

function function_with_this_outside_class() {
return $this->whatever();
}

function function_with_static_members_outside_class() {
echo SomeOtherClass::$external_static_member_var;
return self::$whatever;
}

function function_with_closure($outer_param) {
$outer_var = 1;
$outer_var2 = 2;
Expand Down Expand Up @@ -260,6 +270,18 @@ class ClassWithThisInsideClosure {
}
}

class ClassWithSelfInsideClosure {
static $static_member;

function method_with_self_inside_closure() {
echo self::$static_member;
array_map(function () {
echo self::$static_member;
}, array());
echo self::$static_member;
}
}

function function_with_inline_assigns() {
echo $var;
($var = 12) && $var;
Expand Down

0 comments on commit 372456c

Please sign in to comment.