3
* A Sniff to enforce the use of IDENTICAL type operators rather than EQUAL operators.
8
* @package PHP_CodeSniffer
9
* @author Greg Sherwood <gsherwood@squiz.net>
10
* @author Marc McIntyre <mmcintyre@squiz.net>
11
* @copyright 2006-2014 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
17
* A Sniff to enforce the use of IDENTICAL type operators rather than EQUAL operators.
19
* The use of === true is enforced over implicit true statements,
38
* It also enforces the use of === false over ! operators.
41
* @package PHP_CodeSniffer
42
* @author Greg Sherwood <gsherwood@squiz.net>
43
* @author Marc McIntyre <mmcintyre@squiz.net>
44
* @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
45
* @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
46
* @version Release: 1.5.4
47
* @link http://pear.php.net/package/PHP_CodeSniffer
49
class Squiz_Sniffs_Operators_ComparisonOperatorUsageSniff implements PHP_CodeSniffer_Sniff
53
* A list of tokenizers this sniff supports.
57
public $supportedTokenizers = array(
63
* A list of valid comparison operators.
67
private static $_validOps = array(
72
T_IS_GREATER_OR_EQUAL,
73
T_IS_SMALLER_OR_EQUAL,
78
* A list of invalid operators with their alternatives.
80
* @var array(int => string)
82
private static $_invalidOps = array(
85
T_IS_NOT_EQUAL => '!==',
86
T_BOOLEAN_NOT => '=== FALSE',
90
T_IS_NOT_EQUAL => '!==',
96
* Registers the token types that this sniff wishes to listen to.
100
public function register()
112
* Process the tokens that this sniff is listening for.
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
120
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
122
$tokens = $phpcsFile->getTokens();
123
$tokenizer = $phpcsFile->tokenizerType;
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.
135
} else if ($tokens[$i]['code'] === T_OPEN_TAG) {
136
// Stop here as this is the start of the file.
138
} else if ($tokens[$i]['code'] === T_CLOSE_CURLY_BRACKET) {
139
// Stop if this is the closing brace of
141
if (isset($tokens[$i]['scope_opener']) === true) {
144
} else if ($tokens[$i]['code'] === T_OPEN_CURLY_BRACKET) {
145
// Stop if this is the opening brace of
147
if (isset($tokens[$i]['scope_closer']) === true) {
153
$start = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($i + 1), null, true);
155
$start = $tokens[$end]['parenthesis_opener'];
158
$start = $tokens[$stackPtr]['parenthesis_opener'];
159
$end = $tokens[$stackPtr]['parenthesis_closer'];
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 %s prohibited; use %s instead';
170
$tokens[$i]['content'],
171
self::$_invalidOps[$tokenizer][$type],
173
$phpcsFile->addError($error, $i, 'NotAllowed', $data);
175
} else if (in_array($type, self::$_validOps) === true) {
179
if ($phpcsFile->tokenizerType !== 'JS') {
180
if ($tokens[$i]['code'] === T_BOOLEAN_AND || $tokens[$i]['code'] === T_BOOLEAN_OR) {
183
// When the instanceof operator is used with another operator
184
// like ===, you can get more ops than are required.
185
if ($foundOps > $requiredOps) {
186
$foundOps = $requiredOps;
189
// If we get to here and we have not found the right number of
190
// comparison operators, then we must have had an implicit
191
// true operation ie. if ($a) instead of the required
192
// if ($a === true), so let's add an error.
193
if ($requiredOps !== $foundOps) {
194
$error = 'Implicit true comparisons prohibited; use === TRUE instead';
195
$phpcsFile->addError($error, $stackPtr, 'ImplicitTrue');
204
if ($phpcsFile->tokenizerType !== 'JS') {
205
if ($foundOps < $requiredOps) {
206
$error = 'Implicit true comparisons prohibited; use === TRUE instead';
207
$phpcsFile->addError($error, $stackPtr, 'ImplicitTrue');