~ubuntu-branches/ubuntu/utopic/php-codesniffer/utopic

« back to all changes in this revision

Viewing changes to PHP_CodeSniffer-1.5.0RC2/CodeSniffer/Standards/Squiz/Sniffs/PHP/DisallowMultipleAssignmentsSniff.php

  • Committer: Package Import Robot
  • Author(s): Thomas Goirand
  • Date: 2013-07-12 15:16:25 UTC
  • mfrom: (1.1.3)
  • Revision ID: package-import@ubuntu.com-20130712151625-4autdc0twzbueha9
Tags: 1.5.0~rc2-1
* New upstream release.
* Refreshed patch.
* Standards-Version is now 3.9.4.
* Canonical VCS URLs.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * Squiz_Sniffs_PHP_DisallowMultipleAssignmentsSniff.
 
4
 *
 
5
 * PHP version 5
 
6
 *
 
7
 * @category  PHP
 
8
 * @package   PHP_CodeSniffer
 
9
 * @author    Greg Sherwood <gsherwood@squiz.net>
 
10
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 
11
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 
12
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 
13
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 
14
 */
 
15
 
 
16
/**
 
17
 * Squiz_Sniffs_PHP_DisallowMultipleAssignmentsSniff.
 
18
 *
 
19
 * Ensures that there is only one value assignment on a line, and that it is
 
20
 * the first thing on the line.
 
21
 *
 
22
 * @category  PHP
 
23
 * @package   PHP_CodeSniffer
 
24
 * @author    Greg Sherwood <gsherwood@squiz.net>
 
25
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 
26
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
 
27
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 
28
 * @version   Release: 1.5.0RC2
 
29
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 
30
 */
 
31
class Squiz_Sniffs_PHP_DisallowMultipleAssignmentsSniff implements PHP_CodeSniffer_Sniff
 
32
{
 
33
 
 
34
 
 
35
    /**
 
36
     * Returns an array of tokens this test wants to listen for.
 
37
     *
 
38
     * @return array
 
39
     */
 
40
    public function register()
 
41
    {
 
42
        return array(T_EQUAL);
 
43
 
 
44
    }//end register()
 
45
 
 
46
 
 
47
    /**
 
48
     * Processes this test, when one of its tokens is encountered.
 
49
     *
 
50
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
 
51
     * @param int                  $stackPtr  The position of the current token in the
 
52
     *                                        stack passed in $tokens.
 
53
     *
 
54
     * @return void
 
55
     */
 
56
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 
57
    {
 
58
        $tokens = $phpcsFile->getTokens();
 
59
 
 
60
        // Ignore default value assignments in function definitions.
 
61
        $function = $phpcsFile->findPrevious(array(T_FUNCTION, T_CLOSURE), ($stackPtr - 1));
 
62
        if ($function !== false) {
 
63
            $opener = $tokens[$function]['parenthesis_opener'];
 
64
            $closer = $tokens[$function]['parenthesis_closer'];
 
65
            if ($opener < $stackPtr && $closer > $stackPtr) {
 
66
                return;
 
67
            }
 
68
        }
 
69
 
 
70
        /*
 
71
            The general rule is:
 
72
            Find an equal sign and go backwards along the line. If you hit an
 
73
            end bracket, skip to the opening bracket. When you find a variable,
 
74
            stop. That variable must be the first non-empty token on the line
 
75
            or in the statement. If not, throw an error.
 
76
        */
 
77
 
 
78
        for ($varToken = ($stackPtr - 1); $varToken >= 0; $varToken--) {
 
79
            // Skip brackets.
 
80
            if (isset($tokens[$varToken]['parenthesis_opener']) === true && $tokens[$varToken]['parenthesis_opener'] < $varToken) {
 
81
                $varToken = $tokens[$varToken]['parenthesis_opener'];
 
82
                continue;
 
83
            }
 
84
 
 
85
            if (isset($tokens[$varToken]['bracket_opener']) === true) {
 
86
                $varToken = $tokens[$varToken]['bracket_opener'];
 
87
                continue;
 
88
            }
 
89
 
 
90
            if ($tokens[$varToken]['code'] === T_SEMICOLON) {
 
91
                // We've reached the next statement, so we
 
92
                // didn't find a variable.
 
93
                return;
 
94
            }
 
95
 
 
96
            if ($tokens[$varToken]['code'] === T_VARIABLE) {
 
97
                // We found our variable.
 
98
                break;
 
99
            }
 
100
        }
 
101
 
 
102
        if ($varToken <= 0) {
 
103
            // Didn't find a variable.
 
104
            return;
 
105
        }
 
106
 
 
107
        // Deal with this type of variable: self::$var by setting the var
 
108
        // token to be "self" rather than "$var".
 
109
        if ($tokens[($varToken - 1)]['code'] === T_DOUBLE_COLON) {
 
110
            $varToken = ($varToken - 2);
 
111
        }
 
112
 
 
113
        // Deal with this type of variable: $obj->$var by setting the var
 
114
        // token to be "$obj" rather than "$var".
 
115
        if ($tokens[($varToken - 1)]['code'] === T_OBJECT_OPERATOR) {
 
116
            $varToken = ($varToken - 2);
 
117
        }
 
118
 
 
119
        // Deal with this type of variable: $$var by setting the var
 
120
        // token to be "$" rather than "$var".
 
121
        if ($tokens[($varToken - 1)]['content'] === '$') {
 
122
            $varToken--;
 
123
        }
 
124
 
 
125
        // Ignore member var definitions.
 
126
        $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($varToken - 1), null, true);
 
127
        if (in_array($tokens[$prev]['code'], PHP_CodeSniffer_Tokens::$scopeModifiers) === true) {
 
128
            return;
 
129
        }
 
130
 
 
131
        if ($tokens[$prev]['code'] === T_STATIC) {
 
132
            return;
 
133
        }
 
134
 
 
135
        // Make sure this variable is the first thing in the statement.
 
136
        $varLine  = $tokens[$varToken]['line'];
 
137
        $prevLine = 0;
 
138
        for ($i = ($varToken - 1); $i >= 0; $i--) {
 
139
            if ($tokens[$i]['code'] === T_SEMICOLON) {
 
140
                // We reached the end of the statement.
 
141
                return;
 
142
            }
 
143
 
 
144
            if ($tokens[$i]['code'] === T_INLINE_THEN) {
 
145
                // We reached the end of the inline THEN statement.
 
146
                return;
 
147
            }
 
148
 
 
149
            if ($tokens[$i]['code'] === T_INLINE_ELSE) {
 
150
                // We reached the end of the inline ELSE statement.
 
151
                return;
 
152
            }
 
153
 
 
154
            if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
 
155
                $prevLine = $tokens[$i]['line'];
 
156
                break;
 
157
            }
 
158
        }
 
159
 
 
160
        // Ignore the first part of FOR loops as we are allowed to
 
161
        // assign variables there even though the variable is not the
 
162
        // first thing on the line. Also ignore WHILE loops.
 
163
        if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS && isset($tokens[$i]['parenthesis_owner']) === true) {
 
164
            $owner = $tokens[$i]['parenthesis_owner'];
 
165
            if ($tokens[$owner]['code'] === T_FOR || $tokens[$owner]['code'] === T_WHILE) {
 
166
                return;
 
167
            }
 
168
        }
 
169
 
 
170
        if ($prevLine === $varLine) {
 
171
            $error = 'Assignments must be the first block of code on a line';
 
172
            $phpcsFile->addError($error, $stackPtr, 'Found');
 
173
        }
 
174
 
 
175
    }//end process()
 
176
 
 
177
 
 
178
}//end class
 
179
 
 
180
?>