PHP_CodeSniffer
[ class tree: PHP_CodeSniffer ] [ index: PHP_CodeSniffer ] [ all elements ]

Source for file SelfMemberReferenceSniff.php

Documentation is available at SelfMemberReferenceSniff.php

  1. <?php
  2. /**
  3.  * Tests self member references.
  4.  *
  5.  * Verifies that :
  6.  * - self:: is used instead of Self::
  7.  * - self:: is used for local static member reference
  8.  * - self:: is used instead of self ::
  9.  *
  10.  * @author    Greg Sherwood <gsherwood@squiz.net>
  11.  * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
  12.  * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
  13.  */
  14.  
  15. namespace PHP_CodeSniffer\Standards\Squiz\Sniffs\Classes;
  16.  
  17. use PHP_CodeSniffer\Sniffs\AbstractScopeSniff;
  18. use PHP_CodeSniffer\Files\File;
  19.  
  20. class SelfMemberReferenceSniff extends AbstractScopeSniff
  21. {
  22.  
  23.  
  24.     /**
  25.      * Constructs a Squiz_Sniffs_Classes_SelfMemberReferenceSniff.
  26.      */
  27.     public function __construct()
  28.     {
  29.         parent::__construct(array(T_CLASS), array(T_DOUBLE_COLON));
  30.  
  31.     }//end __construct()
  32.  
  33.  
  34.     /**
  35.      * Processes the function tokens within the class.
  36.      *
  37.      * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found.
  38.      * @param int                         $stackPtr  The position where the token was found.
  39.      * @param int                         $currScope The current scope opener token.
  40.      *
  41.      * @return void 
  42.      */
  43.     protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope)
  44.     {
  45.         $tokens = $phpcsFile->getTokens();
  46.  
  47.         $calledClassName = ($stackPtr - 1);
  48.         if ($tokens[$calledClassName]['code'] === T_SELF) {
  49.             if ($tokens[$calledClassName]['content'] !== 'self') {
  50.                 $error = 'Must use "self::" for local static member reference; found "%s::"';
  51.                 $data  = array($tokens[$calledClassName]['content']);
  52.                 $fix   = $phpcsFile->addFixableError($error, $calledClassName, 'IncorrectCase', $data);
  53.                 if ($fix === true) {
  54.                     $phpcsFile->fixer->replaceToken($calledClassName, 'self');
  55.                 }
  56.  
  57.                 return;
  58.             }
  59.         } else if ($tokens[$calledClassName]['code'] === T_STRING) {
  60.             // If the class is called with a namespace prefix, build fully qualified
  61.             // namespace calls for both current scope class and requested class.
  62.             if ($tokens[($calledClassName - 1)]['code'] === T_NS_SEPARATOR) {
  63.                 $declarationName        = $this->getDeclarationNameWithNamespace($tokens, $calledClassName);
  64.                 $declarationName        = substr($declarationName, 1);
  65.                 $fullQualifiedClassName = $this->getNamespaceOfScope($phpcsFile, $currScope);
  66.                 if ($fullQualifiedClassName === '\\') {
  67.                     $fullQualifiedClassName = '';
  68.                 } else {
  69.                     $fullQualifiedClassName .= '\\';
  70.                 }
  71.  
  72.                 $fullQualifiedClassName .= $phpcsFile->getDeclarationName($currScope);
  73.             } else {
  74.                 $declarationName        = $phpcsFile->getDeclarationName($currScope);
  75.                 $fullQualifiedClassName = $tokens[$calledClassName]['content'];
  76.             }
  77.  
  78.             if ($declarationName === $fullQualifiedClassName) {
  79.                 // Class name is the same as the current class, which is not allowed
  80.                 // except if being used inside a closure.
  81.                 if ($phpcsFile->hasCondition($stackPtr, T_CLOSURE) === false) {
  82.                     $error = 'Must use "self::" for local static member reference';
  83.                     $fix   = $phpcsFile->addFixableError($error, $calledClassName, 'NotUsed');
  84.  
  85.                     if ($fix === true) {
  86.                         $prev = $phpcsFile->findPrevious(array(T_NS_SEPARATOR, T_STRING), ($stackPtr - 1), null, true);
  87.                         $phpcsFile->fixer->beginChangeset();
  88.                         for ($i = ($prev + 1); $i < $stackPtr; $i++) {
  89.                             $phpcsFile->fixer->replaceToken($i, '');
  90.                         }
  91.  
  92.                         $phpcsFile->fixer->replaceToken($stackPtr, 'self::');
  93.                         $phpcsFile->fixer->endChangeset();
  94.                     }
  95.  
  96.                     return;
  97.                 }
  98.             }//end if
  99.         }//end if
  100.  
  101.         if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) {
  102.             $found = strlen($tokens[($stackPtr - 1)]['content']);
  103.             $error = 'Expected 0 spaces before double colon; %s found';
  104.             $data  = array($found);
  105.             $fix   = $phpcsFile->addFixableError($error, $calledClassName, 'SpaceBefore', $data);
  106.  
  107.             if ($fix === true) {
  108.                 $phpcsFile->fixer->replaceToken(($stackPtr - 1), '');
  109.             }
  110.         }
  111.  
  112.         if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) {
  113.             $found = strlen($tokens[($stackPtr + 1)]['content']);
  114.             $error = 'Expected 0 spaces after double colon; %s found';
  115.             $data  = array($found);
  116.             $fix   = $phpcsFile->addFixableError($error, $calledClassName, 'SpaceAfter', $data);
  117.  
  118.             if ($fix === true) {
  119.                 $phpcsFile->fixer->replaceToken(($stackPtr + 1), '');
  120.             }
  121.         }
  122.  
  123.     }//end processTokenWithinScope()
  124.  
  125.  
  126.     /**
  127.      * Processes a token that is found within the scope that this test is
  128.      * listening to.
  129.      *
  130.      * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found.
  131.      * @param int                         $stackPtr  The position in the stack where this
  132.      *                                                token was found.
  133.      *
  134.      * @return void 
  135.      */
  136.     protected function processTokenOutsideScope(File $phpcsFile, $stackPtr)
  137.     {
  138.  
  139.     }//end processTokenOutsideScope()
  140.  
  141.  
  142.     /**
  143.      * Returns the declaration names for classes/interfaces/functions with a namespace.
  144.      *
  145.      * @param array $tokens   Token stack for this file
  146.      * @param int   $stackPtr The position where the namespace building will start.
  147.      *
  148.      * @return string 
  149.      */
  150.     protected function getDeclarationNameWithNamespace(array $tokens, $stackPtr)
  151.     {
  152.         $nameParts      = array();
  153.         $currentPointer = $stackPtr;
  154.         while ($tokens[$currentPointer]['code'] === T_NS_SEPARATOR
  155.             || $tokens[$currentPointer]['code'] === T_STRING
  156.         ) {
  157.             $nameParts[] = $tokens[$currentPointer]['content'];
  158.             $currentPointer--;
  159.         }
  160.  
  161.         $nameParts = array_reverse($nameParts);
  162.         return implode('', $nameParts);
  163.  
  164.     }//end getDeclarationNameWithNamespace()
  165.  
  166.  
  167.     /**
  168.      * Returns the namespace declaration of a file.
  169.      *
  170.      * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found.
  171.      * @param int                         $stackPtr  The position where the search for the
  172.      *                                                namespace declaration will start.
  173.      *
  174.      * @return string 
  175.      */
  176.     protected function getNamespaceOfScope(File $phpcsFile, $stackPtr)
  177.     {
  178.         $namespace            = '\\';
  179.         $namespaceDeclaration = $phpcsFile->findPrevious(T_NAMESPACE, $stackPtr);
  180.  
  181.         if ($namespaceDeclaration !== false) {
  182.             $endOfNamespaceDeclaration = $phpcsFile->findNext(T_SEMICOLON, $namespaceDeclaration);
  183.             $namespace = $this->getDeclarationNameWithNamespace(
  184.                 $phpcsFile->getTokens(),
  185.                 ($endOfNamespaceDeclaration - 1)
  186.             );
  187.         }
  188.  
  189.         return $namespace;
  190.  
  191.     }//end getNamespaceOfScope()
  192.  
  193.  
  194. }//end class

Documentation generated on Mon, 11 Mar 2019 15:27:46 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.