PageRenderTime 60ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/script/lib/PHP/CodeSniffer/Standards/Squiz/Sniffs/Formatting/OperatorBracketSniff.php

https://bitbucket.org/chamilo/chamilo/
PHP | 254 lines | 147 code | 34 blank | 73 comment | 43 complexity | 5eb2c97b682a14a9d5a2e280184780d3 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-2.1, LGPL-3.0, GPL-3.0, MIT
  1. <?php
  2. /**
  3. * Squiz_Sniffs_Formatting_OperationBracketSniff.
  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: OperatorBracketSniff.php 291581 2009-12-02 03:57:02Z squiz $
  14. * @link http://pear.php.net/package/PHP_CodeSniffer
  15. */
  16. /**
  17. * Squiz_Sniffs_Formatting_OperationBracketSniff.
  18. *
  19. * Tests that all arithmetic operations are bracketed.
  20. *
  21. * @category PHP
  22. * @package PHP_CodeSniffer
  23. * @author Greg Sherwood <gsherwood@squiz.net>
  24. * @author Marc McIntyre <mmcintyre@squiz.net>
  25. * @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
  26. * @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
  27. * @version Release: 1.2.2
  28. * @link http://pear.php.net/package/PHP_CodeSniffer
  29. */
  30. class Squiz_Sniffs_Formatting_OperatorBracketSniff implements PHP_CodeSniffer_Sniff
  31. {
  32. /**
  33. * A list of tokenizers this sniff supports.
  34. *
  35. * @var array
  36. */
  37. public $supportedTokenizers = array(
  38. 'PHP',
  39. 'JS',
  40. );
  41. /**
  42. * Returns an array of tokens this test wants to listen for.
  43. *
  44. * @return array
  45. */
  46. public function register()
  47. {
  48. return PHP_CodeSniffer_Tokens::$operators;
  49. }//end register()
  50. /**
  51. * Processes this test, when one of its tokens is encountered.
  52. *
  53. * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
  54. * @param int $stackPtr The position of the current token in the
  55. * stack passed in $tokens.
  56. *
  57. * @return void
  58. */
  59. public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
  60. {
  61. $tokens = $phpcsFile->getTokens();
  62. if ($phpcsFile->tokenizerType === 'JS' && $tokens[$stackPtr]['code'] === T_PLUS) {
  63. // JavaScript uses the plus operator for string concatenation as well
  64. // so we cannot accurately determine if it is a string concat or addition.
  65. // So just ignore it.
  66. return;
  67. }
  68. // If the & is a reference, then we don't want to check for brackets.
  69. if ($tokens[$stackPtr]['code'] === T_BITWISE_AND && $phpcsFile->isReference($stackPtr) === true) {
  70. return;
  71. }
  72. // There is one instance where brackets aren't needed, which involves
  73. // the minus sign being used to assign a negative number to a variable.
  74. if ($tokens[$stackPtr]['code'] === T_MINUS) {
  75. // Check to see if we are trying to return -n.
  76. $prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr - 1), null, true);
  77. if ($tokens[$prev]['code'] === T_RETURN) {
  78. return;
  79. }
  80. $number = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
  81. if ($tokens[$number]['code'] === T_LNUMBER || $tokens[$number]['code'] === T_DNUMBER) {
  82. $previous = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
  83. if ($previous !== false) {
  84. $isAssignment = in_array($tokens[$previous]['code'], PHP_CodeSniffer_Tokens::$assignmentTokens);
  85. $isEquality = in_array($tokens[$previous]['code'], PHP_CodeSniffer_Tokens::$equalityTokens);
  86. $isComparison = in_array($tokens[$previous]['code'], PHP_CodeSniffer_Tokens::$comparisonTokens);
  87. if ($isAssignment === true || $isEquality === true || $isComparison === true) {
  88. // This is a negative assignment or comparion.
  89. // We need to check that the minus and the number are
  90. // adjacent.
  91. if (($number - $stackPtr) !== 1) {
  92. $error = 'No space allowed between minus sign and number';
  93. $phpcsFile->addError($error, $stackPtr);
  94. }
  95. return;
  96. }
  97. }
  98. }
  99. }//end if
  100. $lastBracket = false;
  101. if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
  102. $parenthesis = array_reverse($tokens[$stackPtr]['nested_parenthesis'], true);
  103. foreach ($parenthesis as $bracket => $endBracket) {
  104. $prevToken = $phpcsFile->findPrevious(T_WHITESPACE, ($bracket - 1), null, true);
  105. $prevCode = $tokens[$prevToken]['code'];
  106. if ($prevCode === T_ISSET) {
  107. // This operation is inside an isset() call, but has
  108. // no bracket of it's own.
  109. break;
  110. }
  111. if ($prevCode === T_STRING || $prevCode === T_SWITCH) {
  112. // We allow very simple operations to not be bracketed.
  113. // For example, ceil($one / $two).
  114. $allowed = array(
  115. T_VARIABLE,
  116. T_LNUMBER,
  117. T_DNUMBER,
  118. T_STRING,
  119. T_WHITESPACE,
  120. T_THIS,
  121. T_OBJECT_OPERATOR,
  122. T_OPEN_SQUARE_BRACKET,
  123. T_CLOSE_SQUARE_BRACKET,
  124. T_MODULUS,
  125. );
  126. for ($prev = ($stackPtr - 1); $prev > $bracket; $prev--) {
  127. if (in_array($tokens[$prev]['code'], $allowed) === true) {
  128. continue;
  129. }
  130. if ($tokens[$prev]['code'] === T_CLOSE_PARENTHESIS) {
  131. $prev = $tokens[$prev]['parenthesis_opener'];
  132. } else {
  133. break;
  134. }
  135. }
  136. if ($prev !== $bracket) {
  137. break;
  138. }
  139. for ($next = ($stackPtr + 1); $next < $endBracket; $next++) {
  140. if (in_array($tokens[$next]['code'], $allowed) === true) {
  141. continue;
  142. }
  143. if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) {
  144. $next = $tokens[$next]['parenthesis_closer'];
  145. } else {
  146. break;
  147. }
  148. }
  149. if ($next !== $endBracket) {
  150. break;
  151. }
  152. }//end if
  153. if (in_array($prevCode, PHP_CodeSniffer_Tokens::$scopeOpeners) === true) {
  154. // This operation is inside an a control structure like FOREACH
  155. // or IF, but has no bracket of it's own.
  156. // The only control structure allowed to do this is SWITCH.
  157. if ($prevCode !== T_SWITCH) {
  158. break;
  159. }
  160. }
  161. if ($prevCode === T_OPEN_PARENTHESIS) {
  162. // These are two open parenthesis in a row. If the current
  163. // one doesn't enclose the operator, go to the previous one.
  164. if ($endBracket < $stackPtr) {
  165. continue;
  166. }
  167. }
  168. $lastBracket = $bracket;
  169. break;
  170. }//end foreach
  171. }//end if
  172. if ($lastBracket === false) {
  173. // It is not in a bracketed statement at all.
  174. $previousToken = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true, null, true);
  175. if ($previousToken !== false) {
  176. // A list of tokens that indicate that the token is not
  177. // part of an arithmetic operation.
  178. $invalidTokens = array(
  179. T_COMMA,
  180. T_COLON,
  181. T_OPEN_PARENTHESIS,
  182. T_OPEN_SQUARE_BRACKET,
  183. );
  184. if (in_array($tokens[$previousToken]['code'], $invalidTokens) === false) {
  185. $error = 'Arithmetic operation must be bracketed';
  186. $phpcsFile->addError($error, $stackPtr);
  187. }
  188. return;
  189. }
  190. } else if ($tokens[$lastBracket]['parenthesis_closer'] < $stackPtr) {
  191. // There are a set of brackets in front of it that don't include it.
  192. $error = 'Arithmetic operation must be bracketed';
  193. $phpcsFile->addError($error, $stackPtr);
  194. return;
  195. } else {
  196. // We are enclosed in a set of bracket, so the last thing to
  197. // check is that we are not also enclosed in square brackets
  198. // like this: ($array[$index + 1]), which is invalid.
  199. $brackets = array(
  200. T_OPEN_SQUARE_BRACKET,
  201. T_CLOSE_SQUARE_BRACKET,
  202. );
  203. $squareBracket = $phpcsFile->findPrevious($brackets, ($stackPtr - 1), $lastBracket);
  204. if ($squareBracket !== false && $tokens[$squareBracket]['code'] === T_OPEN_SQUARE_BRACKET) {
  205. $closeSquareBracket = $phpcsFile->findNext($brackets, ($stackPtr + 1));
  206. if ($closeSquareBracket !== false && $tokens[$closeSquareBracket]['code'] === T_CLOSE_SQUARE_BRACKET) {
  207. $error = 'Arithmetic operation must be bracketed';
  208. $phpcsFile->addError($error, $stackPtr);
  209. }
  210. }
  211. return;
  212. }//end if
  213. $lastAssignment = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$assignmentTokens, $stackPtr, null, false, null, true);
  214. if ($lastAssignment !== false && $lastAssignment > $lastBracket) {
  215. $error = 'Arithmetic operation must be bracketed';
  216. $phpcsFile->addError($error, $stackPtr);
  217. }
  218. }//end process()
  219. }//end class
  220. ?>