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 can be simplified to a while-loop.
18 *
19 * This rule is based on the PMD rule catalog. Detects for-loops that can be
20 * simplified as a while-loop.
21 *
22 * <code>
23 * class Foo
24 * {
25 *     public function bar($x)
26 *     {
27 *         for (;true;) true; // No Init or Update part, may as well be: while (true)
28 *     }
29 * }
30 * </code>
31 *
32 * @category  PHP
33 * @package   PHP_CodeSniffer
34 * @author    Manuel Pichler <mapi@manuel-pichler.de>
35 * @copyright 2007-2014 Manuel Pichler. All rights reserved.
36 * @license   http://www.opensource.org/licenses/bsd-license.php  BSD License
37 * @version   Release: @package_version@
38 * @link      http://pear.php.net/package/PHP_CodeSniffer
39 */
40class Generic_Sniffs_CodeAnalysis_ForLoopShouldBeWhileLoopSniff implements PHP_CodeSniffer_Sniff
41{
42
43
44    /**
45     * Registers the tokens that this sniff wants to listen for.
46     *
47     * @return int[]
48     */
49    public function register()
50    {
51        return array(T_FOR);
52
53    }//end register()
54
55
56    /**
57     * Processes this test, when one of its tokens is encountered.
58     *
59     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
60     * @param int                  $stackPtr  The position of the current token
61     *                                        in the stack passed in $tokens.
62     *
63     * @return void
64     */
65    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
66    {
67        $tokens = $phpcsFile->getTokens();
68        $token  = $tokens[$stackPtr];
69
70        // Skip invalid statement.
71        if (isset($token['parenthesis_opener']) === false) {
72            return;
73        }
74
75        $next = ++$token['parenthesis_opener'];
76        $end  = --$token['parenthesis_closer'];
77
78        $parts = array(
79                  0,
80                  0,
81                  0,
82                 );
83        $index = 0;
84
85        for (; $next <= $end; ++$next) {
86            $code = $tokens[$next]['code'];
87            if ($code === T_SEMICOLON) {
88                ++$index;
89            } else if (isset(PHP_CodeSniffer_Tokens::$emptyTokens[$code]) === false) {
90                ++$parts[$index];
91            }
92        }
93
94        if ($parts[0] === 0 && $parts[2] === 0 && $parts[1] > 0) {
95            $error = 'This FOR loop can be simplified to a WHILE loop';
96            $phpcsFile->addWarning($error, $stackPtr, 'CanSimplify');
97        }
98
99    }//end process()
100
101
102}//end class
103