3
* Squiz_Sniffs_Operators_IncrementDecrementUsageSniff.
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: IncrementDecrementUsageSniff.php,v 1.6 2008/02/28 22:40:50 squiz Exp $
14
* @link http://pear.php.net/package/PHP_CodeSniffer
18
* Squiz_Sniffs_Operators_IncrementDecrementUsageSniff.
20
* Tests that the ++ operators are used when possible and not
21
* used when it makes the code confusing.
24
* @package PHP_CodeSniffer
25
* @author Greg Sherwood <gsherwood@squiz.net>
26
* @author Marc McIntyre <mmcintyre@squiz.net>
27
* @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
28
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
29
* @version Release: 1.1.0
30
* @link http://pear.php.net/package/PHP_CodeSniffer
32
class Squiz_Sniffs_Operators_IncrementDecrementUsageSniff implements PHP_CodeSniffer_Sniff
37
* Returns an array of tokens this test wants to listen for.
41
public function register()
55
* Processes this test, when one of its tokens is encountered.
57
* @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
58
* @param int $stackPtr The position of the current token
59
* in the stack passed in $tokens.
63
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
65
$tokens = $phpcsFile->getTokens();
67
if ($tokens[$stackPtr]['code'] === T_INC || $tokens[$stackPtr]['code'] === T_DEC) {
68
$this->processIncDec($phpcsFile, $stackPtr);
70
$this->processAssignment($phpcsFile, $stackPtr);
77
* Checks to ensure increment and decrement operators are not confusing.
79
* @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
80
* @param int $stackPtr The position of the current token
81
* in the stack passed in $tokens.
85
protected function processIncDec(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
87
$tokens = $phpcsFile->getTokens();
89
// Work out where the variable is so we know where to
90
// start looking for other operators.
91
if ($tokens[($stackPtr - 1)]['code'] === T_VARIABLE) {
92
$start = ($stackPtr + 1);
94
$start = ($stackPtr + 2);
97
$next = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, $start, null, true);
98
if ($next === false) {
102
if (in_array($tokens[$next]['code'], PHP_CodeSniffer_Tokens::$arithmeticTokens) === true) {
103
$error = 'Increment and decrement operators cannot be used in an arithmetic operation';
104
$phpcsFile->addError($error, $stackPtr);
108
$prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($start - 3), null, true);
109
if ($prev === false) {
113
// Check if this is in a string concat.
114
if ($tokens[$next]['code'] === T_STRING_CONCAT || $tokens[$prev]['code'] === T_STRING_CONCAT) {
115
$error = 'Increment and decrement operators must be bracketed when used in string concatenation';
116
$phpcsFile->addError($error, $stackPtr);
119
}//end processIncDec()
123
* Checks to ensure increment and decrement operators are used.
125
* @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
126
* @param int $stackPtr The position of the current token
127
* in the stack passed in $tokens.
131
protected function processAssignment(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
133
$tokens = $phpcsFile->getTokens();
135
$assignedVar = $phpcsFile->findPrevious(array(T_VARIABLE), ($stackPtr - 1), null, false);
136
// Not an assignment, return.
137
if ($assignedVar === false) {
141
$statementEnd = $phpcsFile->findNext(array(T_SEMICOLON, T_CLOSE_PARENTHESIS, T_CLOSE_SQUARE_BRACKET, T_CLOSE_CURLY_BRACKET), $stackPtr);
143
// If there is anything other than variables, numbers, spaces or operators we need to return.
144
$noiseTokens = $phpcsFile->findNext(array(T_LNUMBER, T_VARIABLE, T_WHITESPACE, T_PLUS, T_MINUS, T_OPEN_PARENTHESIS), ($stackPtr + 1), $statementEnd, true);
146
if ($noiseTokens !== false) {
150
// If we are already using += or -=, we need to ignore
151
// the statement if a variable is being used.
152
if ($tokens[$stackPtr]['code'] !== T_EQUAL) {
153
$nextVar = $phpcsFile->findNext(T_VARIABLE, ($stackPtr + 1), $statementEnd);
154
if ($nextVar !== false) {
159
if ($tokens[$stackPtr]['code'] === T_EQUAL) {
160
$nextVar = ($stackPtr + 1);
161
$previousVariable = ($stackPtr + 1);
163
while (($nextVar = $phpcsFile->findNext(T_VARIABLE, ($nextVar + 1), $statementEnd)) !== false) {
164
$previousVariable = $nextVar;
168
if ($variableCount !== 1) {
172
$nextVar = $previousVariable;
173
if ($tokens[$nextVar]['content'] !== $tokens[$assignedVar]['content']) {
178
// We have only one variable, and it's the same as what is being assigned,
179
// so we need to check what is being added or subtracted.
180
$nextNumber = ($stackPtr + 1);
181
$previousNumber = ($stackPtr + 1);
183
while (($nextNumber = $phpcsFile->findNext(array(T_LNUMBER), ($nextNumber + 1), $statementEnd, false)) !== false) {
184
$previousNumber = $nextNumber;
188
if ($numberCount !== 1) {
192
$nextNumber = $previousNumber;
193
if ($tokens[$nextNumber]['content'] === '1') {
194
if ($tokens[$stackPtr]['code'] === T_EQUAL) {
195
$operator = $tokens[$phpcsFile->findNext(array(T_PLUS, T_MINUS), ($stackPtr + 1), $statementEnd)]['content'];
197
$operator = substr($tokens[$stackPtr]['content'], 0, 1);
200
// If we are adding or subtracting negative value, the operator
201
// needs to be reversed.
202
if ($tokens[$stackPtr]['code'] !== T_EQUAL) {
203
$negative = $phpcsFile->findPrevious(T_MINUS, ($nextNumber - 1), $stackPtr);
204
if ($negative !== false) {
205
$operator = ($operator === '+') ? '-' : '+';
209
$expected = $tokens[$assignedVar]['content'].$operator.$operator;
210
$found = $phpcsFile->getTokensAsString($assignedVar, ($statementEnd - $assignedVar + 1));
212
if ($operator === '+') {
213
$error = 'Increment';
215
$error = 'Decrement';
218
$error .= " operators should be used where possible; found \"$found\" but expected \"$expected\"";
219
$phpcsFile->addError($error, $stackPtr);
222
}//end processAssignment()