1<?php 2/** 3 * This file is part of the CodeAnalysis add-on for PHP_CodeSniffer. 4 * 5 * PHP version 5 6 * 7 * @category PHP 8 * @package PHP_CodeSniffer 9 * @author Greg Sherwood <gsherwood@squiz.net> 10 * @author Manuel Pichler <mapi@manuel-pichler.de> 11 * @copyright 2007-2014 Manuel Pichler. All rights reserved. 12 * @license http://www.opensource.org/licenses/bsd-license.php BSD License 13 * @link http://pear.php.net/package/PHP_CodeSniffer 14 */ 15 16/** 17 * Detects for-loops that use a function call in the test expression. 18 * 19 * This rule is based on the PMD rule catalog. Detects for-loops that use a 20 * function call in the test expression. 21 * 22 * <code> 23 * class Foo 24 * { 25 * public function bar($x) 26 * { 27 * $a = array(1, 2, 3, 4); 28 * for ($i = 0; $i < count($a); $i++) { 29 * $a[$i] *= $i; 30 * } 31 * } 32 * } 33 * </code> 34 * 35 * @category PHP 36 * @package PHP_CodeSniffer 37 * @author Manuel Pichler <mapi@manuel-pichler.de> 38 * @copyright 2007-2014 Manuel Pichler. All rights reserved. 39 * @license http://www.opensource.org/licenses/bsd-license.php BSD License 40 * @version Release: @package_version@ 41 * @link http://pear.php.net/package/PHP_CodeSniffer 42 */ 43class Generic_Sniffs_CodeAnalysis_ForLoopWithTestFunctionCallSniff implements PHP_CodeSniffer_Sniff 44{ 45 46 47 /** 48 * Registers the tokens that this sniff wants to listen for. 49 * 50 * @return int[] 51 */ 52 public function register() 53 { 54 return array(T_FOR); 55 56 }//end register() 57 58 59 /** 60 * Processes this test, when one of its tokens is encountered. 61 * 62 * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. 63 * @param int $stackPtr The position of the current token 64 * in the stack passed in $tokens. 65 * 66 * @return void 67 */ 68 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) 69 { 70 $tokens = $phpcsFile->getTokens(); 71 $token = $tokens[$stackPtr]; 72 73 // Skip invalid statement. 74 if (isset($token['parenthesis_opener']) === false) { 75 return; 76 } 77 78 $next = ++$token['parenthesis_opener']; 79 $end = --$token['parenthesis_closer']; 80 81 $position = 0; 82 83 for (; $next <= $end; ++$next) { 84 $code = $tokens[$next]['code']; 85 if ($code === T_SEMICOLON) { 86 ++$position; 87 } 88 89 if ($position < 1) { 90 continue; 91 } else if ($position > 1) { 92 break; 93 } else if ($code !== T_VARIABLE && $code !== T_STRING) { 94 continue; 95 } 96 97 // Find next non empty token, if it is a open curly brace we have a 98 // function call. 99 $index = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($next + 1), null, true); 100 101 if ($tokens[$index]['code'] === T_OPEN_PARENTHESIS) { 102 $error = 'Avoid function calls in a FOR loop test part'; 103 $phpcsFile->addWarning($error, $stackPtr, 'NotAllowed'); 104 break; 105 } 106 }//end for 107 108 }//end process() 109 110 111}//end class 112