PageRenderTime 51ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/script/lib/PHP/CodeSniffer/Standards/Squiz/Sniffs/PHP/NonExecutableCodeSniff.php

https://bitbucket.org/chamilo/chamilo-dev/
PHP | 271 lines | 163 code | 37 blank | 71 comment | 31 complexity | be8a12b4b8283f4985de4c497d486396 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_PHP_InnerFunctionsSniff.
  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: NonExecutableCodeSniff.php 293565 2010-01-15 01:18:35Z squiz $
  14. * @link http://pear.php.net/package/PHP_CodeSniffer
  15. */
  16. /**
  17. * Squiz_Sniffs_PHP_NonExecutableCodeSniff.
  18. *
  19. * Warns about code that can never been executed. This happens when a function
  20. * returns before the code, or a break ends execution of a statement etc.
  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 Squiz Pty Ltd (ABN 77 084 670 600)
  27. * @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
  28. * @version Release: 1.2.2
  29. * @link http://pear.php.net/package/PHP_CodeSniffer
  30. */
  31. class Squiz_Sniffs_PHP_NonExecutableCodeSniff implements PHP_CodeSniffer_Sniff
  32. {
  33. /**
  34. * Returns an array of tokens this test wants to listen for.
  35. *
  36. * @return array
  37. */
  38. public function register()
  39. {
  40. return array(T_BREAK, T_CONTINUE, T_RETURN, T_EXIT);
  41. } //end register()
  42. /**
  43. * Processes this test, when one of its tokens is encountered.
  44. *
  45. * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
  46. * @param int $stackPtr The position of the current token in
  47. * the stack passed in $tokens.
  48. *
  49. * @return void
  50. */
  51. public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
  52. {
  53. $tokens = $phpcsFile->getTokens();
  54. if ($tokens[$stackPtr]['code'] === T_RETURN)
  55. {
  56. $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
  57. if ($tokens[$next]['code'] === T_SEMICOLON)
  58. {
  59. $next = $phpcsFile->findNext(T_WHITESPACE, ($next + 1), null, true);
  60. if ($tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET)
  61. {
  62. // If this is the closing brace of a function
  63. // then this return statement doesn't return anything
  64. // and is not required anyway.
  65. $owner = $tokens[$next]['scope_condition'];
  66. if ($tokens[$owner]['code'] === T_FUNCTION)
  67. {
  68. $warning = 'Empty return statement not required here';
  69. $phpcsFile->addWarning($warning, $stackPtr, 'ReturnNotRequired');
  70. return;
  71. }
  72. }
  73. }
  74. }
  75. if ($tokens[$stackPtr]['code'] === T_BREAK && isset($tokens[$stackPtr]['scope_opener']) === true)
  76. {
  77. // This break closes the scope of a CASE or DEFAULT statement
  78. // so any code between this token and the next CASE, DEFAULT or
  79. // end of SWITCH token will not be executable.
  80. $next = $phpcsFile->findNext(array(T_CASE, T_DEFAULT,
  81. T_CLOSE_CURLY_BRACKET), ($stackPtr + 1));
  82. if ($next !== false)
  83. {
  84. $lastLine = $tokens[($stackPtr + 1)]['line'];
  85. for($i = ($stackPtr + 1); $i < $next; $i ++)
  86. {
  87. if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens :: $emptyTokens) === true)
  88. {
  89. continue;
  90. }
  91. $line = $tokens[$i]['line'];
  92. if ($line > $lastLine)
  93. {
  94. $type = substr($tokens[$stackPtr]['type'], 2);
  95. $warning = "Code after $type statement cannot be executed";
  96. $phpcsFile->addWarning($warning, $i, 'Unreachable');
  97. $lastLine = $line;
  98. }
  99. }
  100. } //end if
  101. // That's all we have to check for these types of BREAK statements.
  102. return;
  103. } //end if
  104. // This token may be part of an inline condition.
  105. // If we find a closing parenthesis that belongs to a condition
  106. // we should ignore this token.
  107. $prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens :: $emptyTokens, ($stackPtr - 1), null, true);
  108. if (isset($tokens[$prev]['parenthesis_owner']) === true)
  109. {
  110. $owner = $tokens[$prev]['parenthesis_owner'];
  111. $ignore = array(T_IF, T_ELSE, T_ELSEIF);
  112. if (in_array($tokens[$owner]['code'], $ignore) === true)
  113. {
  114. return;
  115. }
  116. }
  117. $ourConditions = array_keys($tokens[$stackPtr]['conditions']);
  118. $ourTokens = $this->register();
  119. $hasConditions = empty($ourConditions);
  120. // Skip this token if it is non-executable code itself.
  121. if ($hasConditions === false)
  122. {
  123. for($i = ($stackPtr - 1); $i >= 1; $i --)
  124. {
  125. // Skip tokens that close the scope. They don't end
  126. // the execution of code.
  127. if (isset($tokens[$i]['scope_opener']) === true)
  128. {
  129. continue;
  130. }
  131. // Skip tokens that do not end execution.
  132. if (in_array($tokens[$i]['code'], $ourTokens) === false)
  133. {
  134. continue;
  135. }
  136. if (empty($tokens[$i]['conditions']) === true)
  137. {
  138. // Found an end of execution token in the global
  139. // scope, so it will be executed before us.
  140. return;
  141. }
  142. // If the deepest condition this token is in also happens
  143. // to be a condition we are in, it will get executed before us.
  144. $conditions = array_keys($tokens[$i]['conditions']);
  145. $condition = array_pop($conditions);
  146. if (in_array($condition, $ourConditions) === true)
  147. {
  148. return;
  149. }
  150. } //end for
  151. }
  152. else
  153. {
  154. // Look for other end of execution tokens in the global scope.
  155. for($i = ($stackPtr - 1); $i >= 1; $i --)
  156. {
  157. if (in_array($tokens[$i]['code'], $ourTokens) === false)
  158. {
  159. continue;
  160. }
  161. if (empty($tokens[$i]['conditions']) === false)
  162. {
  163. continue;
  164. }
  165. // Another end of execution token was before us in the
  166. // global scope, so we are not executable.
  167. return;
  168. }
  169. } //end if
  170. if ($hasConditions === false)
  171. {
  172. $condition = array_pop($ourConditions);
  173. if (isset($tokens[$condition]['scope_closer']) === false)
  174. {
  175. return;
  176. }
  177. $closer = $tokens[$condition]['scope_closer'];
  178. // If the closer for our condition is shared with other openers,
  179. // we will need to throw errors from this token to the next
  180. // shared opener (if there is one), not to the scope closer.
  181. $nextOpener = null;
  182. for($i = ($stackPtr + 1); $i < $closer; $i ++)
  183. {
  184. if (isset($tokens[$i]['scope_closer']) === true)
  185. {
  186. if ($tokens[$i]['scope_closer'] === $closer)
  187. {
  188. // We found an opener that shares the same
  189. // closing token as us.
  190. $nextOpener = $i;
  191. break;
  192. }
  193. }
  194. } //end for
  195. $start = $phpcsFile->findNext(T_SEMICOLON, ($stackPtr + 1));
  196. if ($nextOpener === null)
  197. {
  198. $end = $closer;
  199. }
  200. else
  201. {
  202. $end = $nextOpener;
  203. }
  204. }
  205. else
  206. {
  207. // This token is in the global scope.
  208. if ($tokens[$stackPtr]['code'] === T_BREAK)
  209. {
  210. return;
  211. }
  212. // Throw an error for all lines until the end of the file.
  213. $start = $phpcsFile->findNext(T_SEMICOLON, ($stackPtr + 1));
  214. $end = ($phpcsFile->numTokens - 1);
  215. } //end if
  216. $lastLine = $tokens[$start]['line'];
  217. for($i = ($start + 1); $i < $end; $i ++)
  218. {
  219. if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens :: $emptyTokens) === true)
  220. {
  221. continue;
  222. }
  223. $line = $tokens[$i]['line'];
  224. if ($line > $lastLine)
  225. {
  226. $type = substr($tokens[$stackPtr]['type'], 2);
  227. $warning = "Code after $type statement cannot be executed";
  228. $phpcsFile->addWarning($warning, $i, 'Unreachable');
  229. $lastLine = $line;
  230. }
  231. }
  232. } //end process()
  233. } //end class
  234. ?>