1<?php
2/**
3 * Generic_Sniffs_Formatting_DisallowMultipleStatementsSniff.
4 *
5 * PHP version 5
6 *
7 * @category  PHP
8 * @package   PHP_CodeSniffer
9 * @author    Greg Sherwood <gsherwood@squiz.net>
10 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
11 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
12 * @link      http://pear.php.net/package/PHP_CodeSniffer
13 */
14
15/**
16 * Generic_Sniffs_Formatting_DisallowMultipleStatementsSniff.
17 *
18 * Ensures each statement is on a line by itself.
19 *
20 * @category  PHP
21 * @package   PHP_CodeSniffer
22 * @author    Greg Sherwood <gsherwood@squiz.net>
23 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
24 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
25 * @version   Release: @package_version@
26 * @link      http://pear.php.net/package/PHP_CodeSniffer
27 */
28class Generic_Sniffs_Formatting_DisallowMultipleStatementsSniff implements PHP_CodeSniffer_Sniff
29{
30
31
32    /**
33     * Returns an array of tokens this test wants to listen for.
34     *
35     * @return array
36     */
37    public function register()
38    {
39        return array(T_SEMICOLON);
40
41    }//end register()
42
43
44    /**
45     * Processes this test, when one of its tokens is encountered.
46     *
47     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
48     * @param int                  $stackPtr  The position of the current token in
49     *                                        the stack passed in $tokens.
50     *
51     * @return void
52     */
53    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
54    {
55        $tokens = $phpcsFile->getTokens();
56
57        $prev = $phpcsFile->findPrevious(array(T_SEMICOLON, T_OPEN_TAG, T_OPEN_TAG_WITH_ECHO), ($stackPtr - 1));
58        if ($prev === false
59            || $tokens[$prev]['code'] === T_OPEN_TAG
60            || $tokens[$prev]['code'] === T_OPEN_TAG_WITH_ECHO
61        ) {
62            $phpcsFile->recordMetric($stackPtr, 'Multiple statements on same line', 'no');
63            return;
64        }
65
66        // Ignore multiple statements in a FOR condition.
67        if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
68            foreach ($tokens[$stackPtr]['nested_parenthesis'] as $bracket) {
69                if (isset($tokens[$bracket]['parenthesis_owner']) === false) {
70                    // Probably a closure sitting inside a function call.
71                    continue;
72                }
73
74                $owner = $tokens[$bracket]['parenthesis_owner'];
75                if ($tokens[$owner]['code'] === T_FOR) {
76                    return;
77                }
78            }
79        }
80
81        if ($tokens[$prev]['line'] === $tokens[$stackPtr]['line']) {
82            $phpcsFile->recordMetric($stackPtr, 'Multiple statements on same line', 'yes');
83
84            $error = 'Each PHP statement must be on a line by itself';
85            $fix   = $phpcsFile->addFixableError($error, $stackPtr, 'SameLine');
86            if ($fix === true) {
87                $phpcsFile->fixer->beginChangeset();
88                $phpcsFile->fixer->addNewline($prev);
89                if ($tokens[($prev + 1)]['code'] === T_WHITESPACE) {
90                    $phpcsFile->fixer->replaceToken(($prev + 1), '');
91                }
92
93                $phpcsFile->fixer->endChangeset();
94            }
95        } else {
96            $phpcsFile->recordMetric($stackPtr, 'Multiple statements on same line', 'no');
97        }
98
99    }//end process()
100
101
102}//end class
103