/build/phpcs/Joomla/Sniffs/Functions/FunctionCallSignatureSniff.php

https://github.com/dextercowley/joomla-cms · PHP · 257 lines · 121 code · 38 blank · 98 comment · 32 complexity · fb02683f68fc994a069dda8969f7fb0b MD5 · raw file

  1. <?php
  2. /**
  3. * Joomla_Sniffs_Functions_FunctionCallSignatureSniff.
  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: FunctionCallSignatureSniff.php 284575 2009-07-22 02:58:19Z squiz $
  14. * @link http://pear.php.net/package/PHP_CodeSniffer
  15. */
  16. /**
  17. * Joomla_Sniffs_Functions_FunctionCallSignatureSniff.
  18. *
  19. * @category PHP
  20. * @package PHP_CodeSniffer
  21. * @author Greg Sherwood <gsherwood@squiz.net>
  22. * @author Marc McIntyre <mmcintyre@squiz.net>
  23. * @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
  24. * @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
  25. * @version Release: 1.3.0RC2
  26. * @link http://pear.php.net/package/PHP_CodeSniffer
  27. */
  28. class Joomla_Sniffs_Functions_FunctionCallSignatureSniff implements PHP_CodeSniffer_Sniff
  29. {
  30. /**
  31. * Returns an array of tokens this test wants to listen for.
  32. *
  33. * @return array
  34. */
  35. public function register()
  36. {
  37. return array(T_STRING);
  38. }//end register()
  39. /**
  40. * Processes this test, when one of its tokens is encountered.
  41. *
  42. * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
  43. * @param int $stackPtr The position of the current token
  44. * in the stack passed in $tokens.
  45. *
  46. * @return void
  47. */
  48. public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
  49. {
  50. $tokens = $phpcsFile->getTokens();
  51. // Find the next non-empty token.
  52. $openBracket = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr + 1), null, true);
  53. if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) {
  54. // Not a function call.
  55. return;
  56. }
  57. if (isset($tokens[$openBracket]['parenthesis_closer']) === false) {
  58. // Not a function call.
  59. return;
  60. }
  61. // Find the previous non-empty token.
  62. $search = PHP_CodeSniffer_Tokens::$emptyTokens;
  63. $search[] = T_BITWISE_AND;
  64. $previous = $phpcsFile->findPrevious($search, ($stackPtr - 1), null, true);
  65. if ($tokens[$previous]['code'] === T_FUNCTION) {
  66. // It's a function definition, not a function call.
  67. return;
  68. }
  69. $closeBracket = $tokens[$openBracket]['parenthesis_closer'];
  70. if (($stackPtr + 1) !== $openBracket) {
  71. // Checking this: $value = my_function[*](...).
  72. $error = 'Space before opening parenthesis of function call prohibited';
  73. $phpcsFile->addError($error, $stackPtr, 'SpaceBeforeOpenBracket');
  74. }
  75. $next = $phpcsFile->findNext(T_WHITESPACE, ($closeBracket + 1), null, true);
  76. if ($tokens[$next]['code'] === T_SEMICOLON) {
  77. if (in_array($tokens[($closeBracket + 1)]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === true) {
  78. $error = 'Space after closing parenthesis of function call prohibited';
  79. $phpcsFile->addError($error, $closeBracket, 'SpaceAfterCloseBracket');
  80. }
  81. }
  82. // Check if this is a single line or multi-line function call.
  83. if ($tokens[$openBracket]['line'] === $tokens[$closeBracket]['line']) {
  84. $this->processSingleLineCall($phpcsFile, $stackPtr, $openBracket, $tokens);
  85. } else {
  86. $this->processMultiLineCall($phpcsFile, $stackPtr, $openBracket, $tokens);
  87. }
  88. }//end process()
  89. /**
  90. * Processes single-line calls.
  91. *
  92. * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
  93. * @param int $stackPtr The position of the current token
  94. * in the stack passed in $tokens.
  95. * @param int $openBracket The position of the openning bracket
  96. * in the stack passed in $tokens.
  97. * @param array $tokens The stack of tokens that make up
  98. * the file.
  99. *
  100. * @return void
  101. */
  102. public function processSingleLineCall(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $openBracket, $tokens)
  103. {
  104. if ($tokens[($openBracket + 1)]['code'] === T_WHITESPACE) {
  105. // Checking this: $value = my_function([*]...).
  106. $error = 'Space after opening parenthesis of function call prohibited';
  107. $phpcsFile->addError($error, $stackPtr, 'SpaceAfterOpenBracket');
  108. }
  109. $closer = $tokens[$openBracket]['parenthesis_closer'];
  110. if ($tokens[($closer - 1)]['code'] === T_WHITESPACE) {
  111. // Checking this: $value = my_function(...[*]).
  112. $between = $phpcsFile->findNext(T_WHITESPACE, ($openBracket + 1), null, true);
  113. // Only throw an error if there is some content between the parenthesis.
  114. // i.e., Checking for this: $value = my_function().
  115. // If there is no content, then we would have thrown an error in the
  116. // previous IF statement because it would look like this:
  117. // $value = my_function( ).
  118. if ($between !== $closer) {
  119. $error = 'Space before closing parenthesis of function call prohibited';
  120. $phpcsFile->addError($error, $closer, 'SpaceBeforeCloseBracket');
  121. }
  122. }
  123. }//end processSingleLineCall()
  124. /**
  125. * Processes multi-line calls.
  126. *
  127. * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
  128. * @param int $stackPtr The position of the current token
  129. * in the stack passed in $tokens.
  130. * @param int $openBracket The position of the openning bracket
  131. * in the stack passed in $tokens.
  132. * @param array $tokens The stack of tokens that make up
  133. * the file.
  134. *
  135. * @return void
  136. */
  137. public function processMultiLineCall(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $openBracket, $tokens)
  138. {
  139. // We need to work out how far indented the function
  140. // call itself is, so we can work out how far to
  141. // indent the arguments.
  142. $functionIndent = 0;
  143. for ($i = ($stackPtr - 1); $i >= 0; $i--) {
  144. if ($tokens[$i]['line'] !== $tokens[$stackPtr]['line']) {
  145. $i++;
  146. break;
  147. }
  148. }
  149. if ($tokens[$i]['code'] === T_WHITESPACE) {
  150. $functionIndent = strlen($tokens[$i]['content']);
  151. }
  152. // Each line between the parenthesis should be indented 4 spaces.
  153. $closeBracket = $tokens[$openBracket]['parenthesis_closer'];
  154. $lastLine = $tokens[$openBracket]['line'];
  155. for ($i = ($openBracket + 1); $i < $closeBracket; $i++) {
  156. // Skip nested function calls.
  157. if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS) {
  158. $i = $tokens[$i]['parenthesis_closer'];
  159. $lastLine = $tokens[$i]['line'];
  160. continue;
  161. }
  162. if ($tokens[$i]['line'] !== $lastLine) {
  163. $lastLine = $tokens[$i]['line'];
  164. // We changed lines, so this should be a whitespace indent token.
  165. if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$heredocTokens) === true) {
  166. // Ignore heredoc indentation.
  167. continue;
  168. }
  169. if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$stringTokens) === true) {
  170. if ($tokens[$i]['code'] === $tokens[($i - 1)]['code']) {
  171. // Ignore multi-line string indentation.
  172. continue;
  173. }
  174. }
  175. if ($tokens[$i]['line'] === $tokens[$closeBracket]['line']) {
  176. // Closing brace needs to be indented to the same level
  177. // as the function call.
  178. $expectedIndent = $functionIndent;
  179. } else {
  180. $expectedIndent = ($functionIndent + 4);
  181. }
  182. if ($tokens[$i]['code'] !== T_WHITESPACE) {
  183. $foundIndent = 0;
  184. } else {
  185. $foundIndent = strlen($tokens[$i]['content']);
  186. }
  187. if ($expectedIndent !== $foundIndent) {
  188. // TODO AJE Allow for tab indents instead of spaces
  189. // $error = 'Multi-line function call not indented correctly; expected %s spaces but found %s';
  190. // $data = array(
  191. // $expectedIndent,
  192. // $foundIndent,
  193. // );
  194. // $phpcsFile->addError($error, $i, 'Indent', $data);
  195. }
  196. }//end if
  197. // Skip the rest of a closure.
  198. if ($tokens[$i]['code'] === T_CLOSURE) {
  199. $i = $tokens[$i]['scope_closer'];
  200. $lastLine = $tokens[$i]['line'];
  201. continue;
  202. }
  203. }//end for
  204. if ($tokens[($openBracket + 1)]['content'] !== $phpcsFile->eolChar
  205. && T_CONSTANT_ENCAPSED_STRING != $tokens[($openBracket + 1)]['code'])// allow a '"'
  206. {
  207. $error = 'Opening parenthesis of a multi-line function call must be the last content on the line';
  208. $phpcsFile->addError($error, $stackPtr, 'ContentAfterOpenBracket');
  209. }
  210. $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBracket - 1), null, true);
  211. if ($tokens[$prev]['line'] === $tokens[$closeBracket]['line']
  212. && T_CONSTANT_ENCAPSED_STRING != $tokens[$prev]['code'])// allow a '"'
  213. {
  214. $error = 'Closing parenthesis of a multi-line function call must be on a line by itself';
  215. $phpcsFile->addError($error, $closeBracket, 'CloseBracketLine');
  216. }
  217. }//end processMultiLineCall()
  218. }//end class
  219. ?>