| Conditions | 51 |
| Paths | 48 |
| Total Lines | 240 |
| Code Lines | 145 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 0 | ||
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
| 1 | <?php |
||
| 91 | public static function getFunctionCalls($source, $line, $function) |
||
| 92 | { |
||
| 93 | static $up = array( |
||
| 94 | '(' => true, |
||
| 95 | '[' => true, |
||
| 96 | '{' => true, |
||
| 97 | T_CURLY_OPEN => true, |
||
| 98 | T_DOLLAR_OPEN_CURLY_BRACES => true, |
||
| 99 | ); |
||
| 100 | static $down = array( |
||
| 101 | ')' => true, |
||
| 102 | ']' => true, |
||
| 103 | '}' => true, |
||
| 104 | ); |
||
| 105 | static $modifiers = array( |
||
| 106 | '!', |
||
| 107 | '@', |
||
| 108 | '~', |
||
| 109 | '+', |
||
| 110 | '-', |
||
| 111 | ); |
||
| 112 | |||
| 113 | if (KINT_PHP53) { |
||
| 114 | self::$strip[T_NS_SEPARATOR] = true; |
||
| 115 | } |
||
| 116 | |||
| 117 | if (KINT_PHP56) { |
||
| 118 | self::$operator[T_POW] = true; |
||
| 119 | self::$operator[T_POW_EQUAL] = true; |
||
| 120 | } |
||
| 121 | |||
| 122 | if (KINT_PHP70) { |
||
| 123 | self::$operator[T_SPACESHIP] = true; |
||
| 124 | } |
||
| 125 | |||
| 126 | $tokens = token_get_all($source); |
||
| 127 | $cursor = 1; |
||
| 128 | $function_calls = array(); |
||
| 129 | $prev_tokens = array(null, null, null); |
||
| 130 | |||
| 131 | if (is_array($function)) { |
||
| 132 | $class = explode('\\', $function[0]); |
||
| 133 | $class = strtolower(end($class)); |
||
| 134 | $function = strtolower($function[1]); |
||
| 135 | } else { |
||
| 136 | $class = null; |
||
| 137 | $function = strtolower($function); |
||
| 138 | } |
||
| 139 | |||
| 140 | // Loop through tokens |
||
| 141 | foreach ($tokens as $index => $token) { |
||
| 142 | if (!is_array($token)) { |
||
| 143 | continue; |
||
| 144 | } |
||
| 145 | |||
| 146 | // Count newlines for line number instead of using |
||
| 147 | // $token[2] since it's not available until 5.2.2 |
||
| 148 | // Also note that certain situations (String tokens after whitespace) |
||
| 149 | // may not have the correct line number unless you do this manually |
||
| 150 | $cursor += substr_count($token[1], "\n"); |
||
| 151 | if ($cursor > $line) { |
||
| 152 | break; |
||
| 153 | } |
||
| 154 | |||
| 155 | // Store the last real tokens for later |
||
| 156 | if (isset(self::$ignore[$token[0]])) { |
||
| 157 | continue; |
||
| 158 | } else { |
||
| 159 | $prev_tokens = array($prev_tokens[1], $prev_tokens[2], $token); |
||
| 160 | } |
||
| 161 | |||
| 162 | // Check if it's the right type to be the function we're looking for |
||
| 163 | if ($token[0] !== T_STRING || strtolower($token[1]) !== $function) { |
||
| 164 | continue; |
||
| 165 | } |
||
| 166 | |||
| 167 | // Check if it's a function call |
||
| 168 | if ($tokens[self::realTokenIndex($tokens, $index, 1)] !== '(') { |
||
| 169 | continue; |
||
| 170 | } |
||
| 171 | |||
| 172 | // Check if it matches the signature |
||
| 173 | if ($class === null) { |
||
| 174 | if ($prev_tokens[1] && in_array($prev_tokens[1][0], array(T_DOUBLE_COLON, T_OBJECT_OPERATOR))) { |
||
| 175 | continue; |
||
| 176 | } |
||
| 177 | } else { |
||
| 178 | if (!$prev_tokens[1] || $prev_tokens[1][0] !== T_DOUBLE_COLON) { |
||
| 179 | continue; |
||
| 180 | } |
||
| 181 | |||
| 182 | if (!$prev_tokens[0] || $prev_tokens[0][0] !== T_STRING || strtolower($prev_tokens[0][1]) !== $class) { |
||
| 183 | continue; |
||
| 184 | } |
||
| 185 | } |
||
| 186 | |||
| 187 | $inner_cursor = $cursor; |
||
| 188 | $depth = 0; // The depth respective to the function call |
||
| 189 | $offset = 1; // The offset from the function call |
||
| 190 | $instring = false; // Whether we're in a string or not |
||
| 191 | $realtokens = false; // Whether the string contains anything meaningful or not |
||
| 192 | $params = array(); // All our collected parameters |
||
| 193 | $shortparam = array(); // The short version of the parameter |
||
| 194 | $param_start = 1; // The distance to the start of the parameter |
||
| 195 | |||
| 196 | // Loop through the following tokens until the function call ends |
||
| 197 | while (isset($tokens[$index + $offset])) { |
||
| 198 | $token = $tokens[$index + $offset]; |
||
| 199 | |||
| 200 | // Ensure that the $inner_cursor is correct and |
||
| 201 | // that $token is either a T_ constant or a string |
||
| 202 | if (is_array($token)) { |
||
| 203 | $inner_cursor += substr_count($token[1], "\n"); |
||
| 204 | } |
||
| 205 | |||
| 206 | if (!isset(self::$ignore[$token[0]]) && !isset($down[$token[0]])) { |
||
| 207 | $realtokens = true; |
||
| 208 | } |
||
| 209 | |||
| 210 | // If it's a token that makes us to up a level, increase the depth |
||
| 211 | if (isset($up[$token[0]])) { |
||
| 212 | // If this is the first paren set the start of the param to just after it |
||
| 213 | if ($depth === 0) { |
||
| 214 | $param_start = $offset + 1; |
||
| 215 | } elseif ($depth === 1) { |
||
| 216 | $shortparam[] = $token; |
||
| 217 | $realtokens = false; |
||
| 218 | } |
||
| 219 | |||
| 220 | ++$depth; |
||
| 221 | } elseif (isset($down[$token[0]])) { |
||
| 222 | --$depth; |
||
| 223 | |||
| 224 | // If this brings us down to the parameter level, and we've had |
||
| 225 | // real tokens since going up, fill the $shortparam with an ellipsis |
||
| 226 | if ($depth === 1) { |
||
| 227 | if ($realtokens) { |
||
| 228 | $shortparam[] = '...'; |
||
| 229 | } |
||
| 230 | $shortparam[] = $token; |
||
| 231 | } |
||
| 232 | } elseif ($token[0] === '"') { |
||
| 233 | // Strings use the same symbol for up and down, but we can |
||
| 234 | // only ever be inside one string, so just use a bool for that |
||
| 235 | if ($instring) { |
||
| 236 | --$depth; |
||
| 237 | if ($depth === 1) { |
||
| 238 | $shortparam[] = '...'; |
||
| 239 | } |
||
| 240 | } else { |
||
| 241 | ++$depth; |
||
| 242 | } |
||
| 243 | |||
| 244 | $instring = !$instring; |
||
| 245 | |||
| 246 | $shortparam[] = '"'; |
||
| 247 | } elseif ($depth === 1) { |
||
| 248 | if ($token[0] === ',') { |
||
| 249 | $params[] = array( |
||
| 250 | 'full' => array_slice($tokens, $index + $param_start, $offset - $param_start), |
||
| 251 | 'short' => $shortparam, |
||
| 252 | ); |
||
| 253 | $shortparam = array(); |
||
| 254 | $param_start = $offset + 1; |
||
| 255 | } elseif ($token[0] === T_CONSTANT_ENCAPSED_STRING && strlen($token[1]) > 2) { |
||
| 256 | $shortparam[] = $token[1][0].'...'.$token[1][0]; |
||
| 257 | } else { |
||
| 258 | $shortparam[] = $token; |
||
| 259 | } |
||
| 260 | } |
||
| 261 | |||
| 262 | // Depth has dropped to 0 (So we've hit the closing paren) |
||
| 263 | if ($depth <= 0) { |
||
| 264 | $params[] = array( |
||
| 265 | 'full' => array_slice($tokens, $index + $param_start, $offset - $param_start), |
||
| 266 | 'short' => $shortparam, |
||
| 267 | ); |
||
| 268 | |||
| 269 | break; |
||
| 270 | } |
||
| 271 | |||
| 272 | ++$offset; |
||
| 273 | } |
||
| 274 | |||
| 275 | // If we're not passed (or at) the line at the end |
||
| 276 | // of the function call, we're too early so skip it |
||
| 277 | if ($inner_cursor < $line) { |
||
| 278 | continue; |
||
| 279 | } |
||
| 280 | |||
| 281 | // Format the final output parameters |
||
| 282 | foreach ($params as &$param) { |
||
| 283 | $name = self::tokensFormatted($param['short']); |
||
| 284 | $expression = false; |
||
| 285 | foreach ($name as $token) { |
||
| 286 | if (self::tokenIsOperator($token)) { |
||
| 287 | $expression = true; |
||
| 288 | break; |
||
| 289 | } |
||
| 290 | } |
||
| 291 | |||
| 292 | $param = array( |
||
| 293 | 'name' => self::tokensToString($name), |
||
| 294 | 'path' => self::tokensToString(self::tokensTrim($param['full'])), |
||
| 295 | 'expression' => $expression, |
||
| 296 | ); |
||
| 297 | } |
||
| 298 | |||
| 299 | // Get the modifiers |
||
| 300 | $mods = array(); |
||
| 301 | --$index; |
||
| 302 | |||
| 303 | while (isset($tokens[$index])) { |
||
| 304 | if (isset(self::$ignore[$tokens[$index][0]])) { |
||
| 305 | --$index; |
||
| 306 | continue; |
||
| 307 | } elseif (is_array($tokens[$index]) && empty($mods)) { |
||
| 308 | if ($tokens[$index][0] === T_DOUBLE_COLON || $tokens[$index][0] === T_STRING || (KINT_PHP53 && $tokens[$index][0] === T_NS_SEPARATOR)) { |
||
| 309 | --$index; |
||
| 310 | continue; |
||
| 311 | } else { |
||
| 312 | break; |
||
| 313 | } |
||
| 314 | } elseif (in_array($tokens[$index][0], $modifiers)) { |
||
| 315 | $mods[] = $tokens[$index]; |
||
| 316 | --$index; |
||
| 317 | continue; |
||
| 318 | } else { |
||
| 319 | break; |
||
| 320 | } |
||
| 321 | } |
||
| 322 | |||
| 323 | $function_calls[] = array( |
||
| 324 | 'parameters' => $params, |
||
| 325 | 'modifiers' => $mods, |
||
| 326 | ); |
||
| 327 | } |
||
| 328 | |||
| 329 | return $function_calls; |
||
| 330 | } |
||
| 331 | |||
| 435 |
Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a
@returnannotation as described here.