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

Source for file JumbledIncrementerSniff.php

Documentation is available at JumbledIncrementerSniff.php

  1. <?php
  2. /**
  3.  * Detects incrementer jumbling in for loops.
  4.  *
  5.  * This rule is based on the PMD rule catalog. The jumbling incrementer sniff
  6.  * detects the usage of one and the same incrementer into an outer and an inner
  7.  * loop. Even it is intended this is confusing code.
  8.  *
  9.  * <code>
  10.  * class Foo
  11.  * {
  12.  *     public function bar($x)
  13.  *     {
  14.  *         for ($i = 0; $i < 10; $i++)
  15.  *         {
  16.  *             for ($k = 0; $k < 20; $i++)
  17.  *             {
  18.  *                 echo 'Hello';
  19.  *             }
  20.  *         }
  21.  *     }
  22.  * }
  23.  * </code>
  24.  *
  25.  * @author    Manuel Pichler <mapi@manuel-pichler.de>
  26.  * @copyright 2007-2014 Manuel Pichler. All rights reserved.
  27.  * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
  28.  */
  29.  
  30. namespace PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis;
  31.  
  32. use PHP_CodeSniffer\Sniffs\Sniff;
  33. use PHP_CodeSniffer\Files\File;
  34.  
  35. class JumbledIncrementerSniff implements Sniff
  36. {
  37.  
  38.  
  39.     /**
  40.      * Registers the tokens that this sniff wants to listen for.
  41.      *
  42.      * @return int[] 
  43.      */
  44.     public function register()
  45.     {
  46.         return array(T_FOR);
  47.  
  48.     }//end register()
  49.  
  50.  
  51.     /**
  52.      * Processes this test, when one of its tokens is encountered.
  53.      *
  54.      * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
  55.      * @param int                         $stackPtr  The position of the current token
  56.      *                                                in the stack passed in $tokens.
  57.      *
  58.      * @return void 
  59.      */
  60.     public function process(File $phpcsFile$stackPtr)
  61.     {
  62.         $tokens $phpcsFile->getTokens();
  63.         $token  $tokens[$stackPtr];
  64.  
  65.         // Skip for-loop without body.
  66.         if (isset($token['scope_opener']=== false{
  67.             return;
  68.         }
  69.  
  70.         // Find incrementors for outer loop.
  71.         $outer $this->findIncrementers($tokens$token);
  72.  
  73.         // Skip if empty.
  74.         if (count($outer=== 0{
  75.             return;
  76.         }
  77.  
  78.         // Find nested for loops.
  79.         $start = ++$token['scope_opener'];
  80.         $end   = --$token['scope_closer'];
  81.  
  82.         for ($start <= $end; ++$start{
  83.             if ($tokens[$start]['code'!== T_FOR{
  84.                 continue;
  85.             }
  86.  
  87.             $inner $this->findIncrementers($tokens$tokens[$start]);
  88.             $diff  array_intersect($outer$inner);
  89.  
  90.             if (count($diff!== 0{
  91.                 $error 'Loop incrementor (%s) jumbling with inner loop';
  92.                 $data  = array(join(', '$diff));
  93.                 $phpcsFile->addWarning($error$stackPtr'Found'$data);
  94.             }
  95.         }
  96.  
  97.     }//end process()
  98.  
  99.  
  100.     /**
  101.      * Get all used variables in the incrementer part of a for statement.
  102.      *
  103.      * @param array(integer=>array) $tokens Array with all code sniffer tokens.
  104.      * @param array(string=>mixed)  $token  Current for loop token
  105.      *
  106.      * @return string[] List of all found incrementer variables.
  107.      */
  108.     protected function findIncrementers(array $tokensarray $token)
  109.     {
  110.         // Skip invalid statement.
  111.         if (isset($token['parenthesis_opener']=== false{
  112.             return array();
  113.         }
  114.  
  115.         $start = ++$token['parenthesis_opener'];
  116.         $end   = --$token['parenthesis_closer'];
  117.  
  118.         $incrementers = array();
  119.         $semicolons   = 0;
  120.         for ($next $start$next <= $end; ++$next{
  121.             $code $tokens[$next]['code'];
  122.             if ($code === T_SEMICOLON{
  123.                 ++$semicolons;
  124.             else if ($semicolons === 2 && $code === T_VARIABLE{
  125.                 $incrementers[$tokens[$next]['content'];
  126.             }
  127.         }
  128.  
  129.         return $incrementers;
  130.  
  131.     }//end findIncrementers()
  132.  
  133.  
  134. }//end class

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