Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * A Sniff to enforce the use of IDENTICAL type operators rather than EQUAL operators.
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 Squiz Pty Ltd (ABN 77 084 670 600)
12
 * @license   http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
13
 * @version   CVS: $Id: ComparisonOperatorUsageSniff.php 267855 2008-10-27 04:29:28Z squiz $
14
 * @link      http://pear.php.net/package/PHP_CodeSniffer
15
 */
16
 
17
/**
18
 * A Sniff to enforce the use of IDENTICAL type operators rather than EQUAL operators.
19
 *
20
 * The use of === true is enforced over implicit true statements,
21
 * for example:
22
 *
23
 * <code>
24
 * if ($a)
25
 * {
26
 *     ...
27
 * }
28
 * </code>
29
 *
30
 * should be:
31
 *
32
 * <code>
33
 * if ($a === true)
34
 * {
35
 *     ...
36
 * }
37
 * </code>
38
 *
39
 * It also enforces the use of === false over ! operators.
40
 *
41
 * @category  PHP
42
 * @package   PHP_CodeSniffer
43
 * @author    Greg Sherwood <gsherwood@squiz.net>
44
 * @author    Marc McIntyre <mmcintyre@squiz.net>
45
 * @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
46
 * @license   http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
47
 * @version   Release: 1.2.1
48
 * @link      http://pear.php.net/package/PHP_CodeSniffer
49
 */
50
class Squiz_Sniffs_Operators_ComparisonOperatorUsageSniff implements PHP_CodeSniffer_Sniff
51
{
52
 
53
    /**
54
     * A list of tokenizers this sniff supports.
55
     *
56
     * @var array
57
     */
58
    public $supportedTokenizers = array(
59
                                   'PHP',
60
                                   'JS',
61
                                  );
62
 
63
    /**
64
     * A list of valid comparison operators.
65
     *
66
     * @var array
67
     */
68
    private static $_validOps = array(
69
                                 T_IS_IDENTICAL,
70
                                 T_IS_NOT_IDENTICAL,
71
                                 T_LESS_THAN,
72
                                 T_GREATER_THAN,
73
                                 T_IS_GREATER_OR_EQUAL,
74
                                 T_IS_SMALLER_OR_EQUAL,
75
                                 T_INSTANCEOF,
76
                                );
77
 
78
    /**
79
     * A list of invalid operators with their alternatives.
80
     *
81
     * @var array(int => string)
82
     */
83
    private static $_invalidOps = array(
84
                                   'PHP' => array(
85
                                             T_IS_EQUAL     => '===',
86
                                             T_IS_NOT_EQUAL => '!==',
87
                                             T_BOOLEAN_NOT  => '=== FALSE',
88
                                            ),
89
                                   'JS'  => array(
90
                                             T_IS_EQUAL     => '===',
91
                                             T_IS_NOT_EQUAL => '!==',
92
                                            ),
93
                                  );
94
 
95
 
96
    /**
97
     * Registers the token types that this sniff wishes to listen to.
98
     *
99
     * @return array
100
     */
101
    public function register()
102
    {
103
        return array(
104
                T_IF,
105
                T_INLINE_THEN,
106
               );
107
 
108
    }//end register()
109
 
110
 
111
    /**
112
     * Process the tokens that this sniff is listening for.
113
     *
114
     * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
115
     * @param int                  $stackPtr  The position in the stack where the token
116
     *                                        was found.
117
     *
118
     * @return void
119
     */
120
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
121
    {
122
        $tokens    = $phpcsFile->getTokens();
123
        $tokenizer = $phpcsFile->tokenizerType;
124
 
125
        if ($tokens[$stackPtr]['code'] === T_INLINE_THEN) {
126
            $end = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr - 1), null, true);
127
            if ($tokens[$end]['code'] !== T_CLOSE_PARENTHESIS) {
128
                // This inline IF statement does not have its condition
129
                // bracketed, so we need to guess where it starts.
130
                for ($i = ($end - 1); $i >= 0; $i--) {
131
                    if ($tokens[$i]['code'] === T_SEMICOLON) {
132
                        // Stop here as we assume it is the end
133
                        // of the previous statement.
134
                        break;
135
                    } else if ($tokens[$i]['code'] === T_OPEN_TAG) {
136
                        // Stop here as this is the start of the file.
137
                        break;
138
                    } else if ($tokens[$i]['code'] === T_CLOSE_CURLY_BRACKET) {
139
                        // Stop if this is the closing brace of
140
                        // a code block.
141
                        if (isset($tokens[$i]['scope_opener']) === true) {
142
                            break;
143
                        }
144
                    } else if ($tokens[$i]['code'] === T_OPEN_CURLY_BRACKET) {
145
                        // Stop if this is the opening brace of
146
                        // a code block.
147
                        if (isset($tokens[$i]['scope_closer']) === true) {
148
                            break;
149
                        }
150
                    }
151
                }//end for
152
 
153
                $start = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($i + 1), null, true);
154
            } else {
155
                $start = $tokens[$end]['parenthesis_opener'];
156
            }
157
        } else {
158
            $start = $tokens[$stackPtr]['parenthesis_opener'];
159
            $end   = $tokens[$stackPtr]['parenthesis_closer'];
160
        }
161
 
162
        $requiredOps = 0;
163
        $foundOps    = 0;
164
 
165
        for ($i = $start; $i <= $end; $i++) {
166
            $type = $tokens[$i]['code'];
167
            if (in_array($type, array_keys(self::$_invalidOps[$tokenizer])) === true) {
168
                $error  = 'Operator '.$tokens[$i]['content'].' prohibited;';
169
                $error .= ' use '.self::$_invalidOps[$tokenizer][$type].' instead';
170
                $phpcsFile->addError($error, $i);
171
                $foundOps++;
172
            } else if (in_array($type, self::$_validOps) === true) {
173
                $foundOps++;
174
            }
175
 
176
            if ($phpcsFile->tokenizerType !== 'JS') {
177
                if ($tokens[$i]['code'] === T_BOOLEAN_AND || $tokens[$i]['code'] === T_BOOLEAN_OR) {
178
                    $requiredOps++;
179
 
180
                    // If we get to here and we have not found the right number of
181
                    // comparison operators, then we must have had an implicit
182
                    // true operation ie. if ($a) instead of the required
183
                    // if ($a === true), so let's add an error.
184
                    if ($requiredOps !== $foundOps) {
185
                        $error = 'Implicit true comparisons prohibited; use === TRUE instead';
186
                        $phpcsFile->addError($error, $stackPtr);
187
                        $foundOps++;
188
                    }
189
                }
190
            }//end if
191
        }//end for
192
 
193
        $requiredOps++;
194
 
195
        if ($phpcsFile->tokenizerType !== 'JS') {
196
            if ($foundOps < $requiredOps) {
197
                $error = 'Implicit true comparisons prohibited; use === TRUE instead';
198
                $phpcsFile->addError($error, $stackPtr);
199
            }
200
        }
201
 
202
    }//end process()
203
 
204
 
205
}//end class
206
 
207
?>