annotate vendor/drupal/coder/coder_sniffer/Drupal/Sniffs/Semantics/FunctionCall.php @ 12:7a779792577d

Update Drupal core to v8.4.5 (via Composer)
author Chris Cannam
date Fri, 23 Feb 2018 15:52:07 +0000
parents 4c8ae668cc8c
children 129ea1e6d783
rev   line source
Chris@0 1 <?php
Chris@0 2 /**
Chris@0 3 * Drupal_Sniffs_Semantics_FunctionCall.
Chris@0 4 *
Chris@0 5 * @category PHP
Chris@0 6 * @package PHP_CodeSniffer
Chris@0 7 * @link http://pear.php.net/package/PHP_CodeSniffer
Chris@0 8 */
Chris@0 9
Chris@0 10 /**
Chris@0 11 * Helper class to sniff for specific function calls.
Chris@0 12 *
Chris@0 13 * @category PHP
Chris@0 14 * @package PHP_CodeSniffer
Chris@0 15 * @link http://pear.php.net/package/PHP_CodeSniffer
Chris@0 16 */
Chris@0 17 abstract class Drupal_Sniffs_Semantics_FunctionCall implements PHP_CodeSniffer_Sniff
Chris@0 18 {
Chris@0 19
Chris@0 20 /**
Chris@0 21 * The currently processed file.
Chris@0 22 *
Chris@0 23 * @var PHP_CodeSniffer_File
Chris@0 24 */
Chris@0 25 protected $phpcsFile;
Chris@0 26
Chris@0 27 /**
Chris@0 28 * The token position of the function call.
Chris@0 29 *
Chris@0 30 * @var int
Chris@0 31 */
Chris@0 32 protected $functionCall;
Chris@0 33
Chris@0 34 /**
Chris@0 35 * The token position of the opening bracket of the function call.
Chris@0 36 *
Chris@0 37 * @var int
Chris@0 38 */
Chris@0 39 protected $openBracket;
Chris@0 40
Chris@0 41 /**
Chris@0 42 * The token position of the closing bracket of the function call.
Chris@0 43 *
Chris@0 44 * @var int
Chris@0 45 */
Chris@0 46 protected $closeBracket;
Chris@0 47
Chris@0 48 /**
Chris@0 49 * Internal cache to save the calculated arguments of the function call.
Chris@0 50 *
Chris@0 51 * @var array
Chris@0 52 */
Chris@0 53 protected $arguments;
Chris@0 54
Chris@0 55 /**
Chris@0 56 * Whether method invocations with the same function name should be processed,
Chris@0 57 * too.
Chris@0 58 *
Chris@0 59 * @var bool
Chris@0 60 */
Chris@0 61 protected $includeMethodCalls = false;
Chris@0 62
Chris@0 63
Chris@0 64 /**
Chris@0 65 * Returns an array of tokens this test wants to listen for.
Chris@0 66 *
Chris@0 67 * @return array
Chris@0 68 */
Chris@0 69 public function register()
Chris@0 70 {
Chris@0 71 return array(T_STRING);
Chris@0 72
Chris@0 73 }//end register()
Chris@0 74
Chris@0 75
Chris@0 76 /**
Chris@0 77 * Processes this test, when one of its tokens is encountered.
Chris@0 78 *
Chris@0 79 * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
Chris@0 80 * @param int $stackPtr The position of the current token
Chris@0 81 * in the stack passed in $tokens.
Chris@0 82 *
Chris@0 83 * @return void
Chris@0 84 */
Chris@0 85 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
Chris@0 86 {
Chris@0 87 $tokens = $phpcsFile->getTokens();
Chris@0 88 $functionName = $tokens[$stackPtr]['content'];
Chris@0 89 if (in_array($functionName, $this->registerFunctionNames()) === false) {
Chris@0 90 // Not interested in this function.
Chris@0 91 return;
Chris@0 92 }
Chris@0 93
Chris@0 94 if ($this->isFunctionCall($phpcsFile, $stackPtr) === false) {
Chris@0 95 return;
Chris@0 96 }
Chris@0 97
Chris@0 98 // Find the next non-empty token.
Chris@0 99 $openBracket = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr + 1), null, true);
Chris@0 100
Chris@0 101 $this->phpcsFile = $phpcsFile;
Chris@0 102 $this->functionCall = $stackPtr;
Chris@0 103 $this->openBracket = $openBracket;
Chris@0 104 $this->closeBracket = $tokens[$openBracket]['parenthesis_closer'];
Chris@0 105 $this->arguments = array();
Chris@0 106
Chris@0 107 $this->processFunctionCall($phpcsFile, $stackPtr, $openBracket, $this->closeBracket);
Chris@0 108
Chris@0 109 }//end process()
Chris@0 110
Chris@0 111
Chris@0 112 /**
Chris@0 113 * Checks if this is a function call.
Chris@0 114 *
Chris@0 115 * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
Chris@0 116 * @param int $stackPtr The position of the current token
Chris@0 117 * in the stack passed in $tokens.
Chris@0 118 *
Chris@0 119 * @return bool
Chris@0 120 */
Chris@0 121 protected function isFunctionCall(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
Chris@0 122 {
Chris@0 123 $tokens = $phpcsFile->getTokens();
Chris@0 124 // Find the next non-empty token.
Chris@0 125 $openBracket = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr + 1), null, true);
Chris@0 126
Chris@0 127 if ($tokens[$openBracket]['code'] !== T_OPEN_PARENTHESIS) {
Chris@0 128 // Not a function call.
Chris@0 129 return false;
Chris@0 130 }
Chris@0 131
Chris@0 132 if (isset($tokens[$openBracket]['parenthesis_closer']) === false) {
Chris@0 133 // Not a function call.
Chris@0 134 return false;
Chris@0 135 }
Chris@0 136
Chris@0 137 // Find the previous non-empty token.
Chris@0 138 $search = PHP_CodeSniffer_Tokens::$emptyTokens;
Chris@0 139 $search[] = T_BITWISE_AND;
Chris@0 140 $previous = $phpcsFile->findPrevious($search, ($stackPtr - 1), null, true);
Chris@0 141 if ($tokens[$previous]['code'] === T_FUNCTION) {
Chris@0 142 // It's a function definition, not a function call.
Chris@0 143 return false;
Chris@0 144 }
Chris@0 145
Chris@0 146 if ($tokens[$previous]['code'] === T_OBJECT_OPERATOR && $this->includeMethodCalls === false) {
Chris@0 147 // It's a method invocation, not a function call.
Chris@0 148 return false;
Chris@0 149 }
Chris@0 150
Chris@0 151 if ($tokens[$previous]['code'] === T_DOUBLE_COLON && $this->includeMethodCalls === false) {
Chris@0 152 // It's a static method invocation, not a function call.
Chris@0 153 return false;
Chris@0 154 }
Chris@0 155
Chris@0 156 return true;
Chris@0 157
Chris@0 158 }//end isFunctionCall()
Chris@0 159
Chris@0 160
Chris@0 161 /**
Chris@0 162 * Returns start and end token for a given argument number.
Chris@0 163 *
Chris@0 164 * @param int $number Indicates which argument should be examined, starting with
Chris@0 165 * 1 for the first argument.
Chris@0 166 *
Chris@0 167 * @return array(string => int)
Chris@0 168 */
Chris@0 169 public function getArgument($number)
Chris@0 170 {
Chris@0 171 // Check if we already calculated the tokens for this argument.
Chris@0 172 if (isset($this->arguments[$number]) === true) {
Chris@0 173 return $this->arguments[$number];
Chris@0 174 }
Chris@0 175
Chris@0 176 $tokens = $this->phpcsFile->getTokens();
Chris@0 177 // Start token of the first argument.
Chris@0 178 $start = $this->phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($this->openBracket + 1), null, true);
Chris@0 179 if ($start === $this->closeBracket) {
Chris@0 180 // Function call has no arguments, so return false.
Chris@0 181 return false;
Chris@0 182 }
Chris@0 183
Chris@0 184 // End token of the last argument.
Chris@0 185 $end = $this->phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($this->closeBracket - 1), null, true);
Chris@0 186 $lastArgEnd = $end;
Chris@0 187 $nextSeperator = $this->openBracket;
Chris@0 188 $counter = 1;
Chris@0 189 while (($nextSeperator = $this->phpcsFile->findNext(T_COMMA, ($nextSeperator + 1), $this->closeBracket)) !== false) {
Chris@0 190 // Make sure the comma belongs directly to this function call,
Chris@0 191 // and is not inside a nested function call or array.
Chris@0 192 $brackets = $tokens[$nextSeperator]['nested_parenthesis'];
Chris@0 193 $lastBracket = array_pop($brackets);
Chris@0 194 if ($lastBracket !== $this->closeBracket) {
Chris@0 195 continue;
Chris@0 196 }
Chris@0 197
Chris@0 198 // Update the end token of the current argument.
Chris@0 199 $end = $this->phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($nextSeperator - 1), null, true);
Chris@0 200 // Save the calculated findings for the current argument.
Chris@0 201 $this->arguments[$counter] = array(
Chris@0 202 'start' => $start,
Chris@0 203 'end' => $end,
Chris@0 204 );
Chris@0 205 if ($counter === $number) {
Chris@0 206 break;
Chris@0 207 }
Chris@0 208
Chris@0 209 $counter++;
Chris@0 210 $start = $this->phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($nextSeperator + 1), null, true);
Chris@0 211 $end = $lastArgEnd;
Chris@0 212 }//end while
Chris@0 213
Chris@0 214 // If the counter did not reach the passed number something is wrong.
Chris@0 215 if ($counter !== $number) {
Chris@0 216 return false;
Chris@0 217 }
Chris@0 218
Chris@0 219 $this->arguments[$counter] = array(
Chris@0 220 'start' => $start,
Chris@0 221 'end' => $end,
Chris@0 222 );
Chris@0 223 return $this->arguments[$counter];
Chris@0 224
Chris@0 225 }//end getArgument()
Chris@0 226
Chris@0 227
Chris@0 228 }//end class