PHPCSHelper::getMethodParameters()   F
last analyzed

Complexity

Conditions 42
Paths 490

Size

Total Lines 181

Duplication

Lines 37
Ratio 20.44 %

Importance

Changes 0
Metric Value
dl 37
loc 181
rs 0.5666
c 0
b 0
f 0
cc 42
nc 490
nop 2

How to fix   Long Method    Complexity   

Long Method

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:

1
<?php
2
/**
3
 * PHPCompatibility, an external standard for PHP_CodeSniffer.
4
 *
5
 * @package   PHPCompatibility
6
 * @copyright 2012-2019 PHPCompatibility Contributors
7
 * @license   https://opensource.org/licenses/LGPL-3.0 LGPL3
8
 * @link      https://github.com/PHPCompatibility/PHPCompatibility
9
 */
10
11
namespace PHPCompatibility;
12
13
use PHP_CodeSniffer_Exception as PHPCS_Exception;
14
use PHP_CodeSniffer_File as File;
15
use PHP_CodeSniffer_Tokens as Tokens;
16
17
/**
18
 * PHPCS cross-version compatibility helper class.
19
 *
20
 * A number of PHPCS classes were split up into several classes in PHPCS 3.x
21
 * Those classes cannot be aliased as they don't represent the same object.
22
 * This class provides helper methods for functions which were contained in
23
 * one of these classes and which are used within the PHPCompatibility library.
24
 *
25
 * Additionally, this class contains some duplicates of PHPCS native methods.
26
 * These methods have received bug fixes or improved functionality between the
27
 * lowest supported PHPCS version and the latest PHPCS stable version and
28
 * to provide the same results cross-version, PHPCompatibility needs to use
29
 * the up-to-date versions of these methods.
30
 *
31
 * @since 8.0.0
32
 * @since 8.2.0 The duplicate PHPCS methods have been moved from the `Sniff`
33
 *              base class to this class.
34
 */
35
class PHPCSHelper
36
{
37
38
    /**
39
     * Get the PHPCS version number.
40
     *
41
     * @since 8.0.0
42
     *
43
     * @return string
44
     */
45
    public static function getVersion()
46
    {
47
        if (\defined('\PHP_CodeSniffer\Config::VERSION')) {
48
            // PHPCS 3.x.
49
            return \PHP_CodeSniffer\Config::VERSION;
50
        } else {
51
            // PHPCS 2.x.
52
            return \PHP_CodeSniffer::VERSION;
53
        }
54
    }
55
56
57
    /**
58
     * Pass config data to PHPCS.
59
     *
60
     * PHPCS cross-version compatibility helper.
61
     *
62
     * @since 8.0.0
63
     *
64
     * @param string      $key   The name of the config value.
65
     * @param string|null $value The value to set. If null, the config entry
66
     *                           is deleted, reverting it to the default value.
67
     * @param boolean     $temp  Set this config data temporarily for this script run.
68
     *                           This will not write the config data to the config file.
69
     *
70
     * @return void
71
     */
72
    public static function setConfigData($key, $value, $temp = false)
73
    {
74
        if (method_exists('\PHP_CodeSniffer\Config', 'setConfigData')) {
75
            // PHPCS 3.x.
76
            \PHP_CodeSniffer\Config::setConfigData($key, $value, $temp);
77
        } else {
78
            // PHPCS 2.x.
79
            \PHP_CodeSniffer::setConfigData($key, $value, $temp);
80
        }
81
    }
82
83
84
    /**
85
     * Get the value of a single PHPCS config key.
86
     *
87
     * @since 8.0.0
88
     *
89
     * @param string $key The name of the config value.
90
     *
91
     * @return string|null
92
     */
93
    public static function getConfigData($key)
94
    {
95
        if (method_exists('\PHP_CodeSniffer\Config', 'getConfigData')) {
96
            // PHPCS 3.x.
97
            return \PHP_CodeSniffer\Config::getConfigData($key);
98
        } else {
99
            // PHPCS 2.x.
100
            return \PHP_CodeSniffer::getConfigData($key);
101
        }
102
    }
103
104
105
    /**
106
     * Get the value of a single PHPCS config key.
107
     *
108
     * This config key can be set in the `CodeSniffer.conf` file, on the
109
     * command-line or in a ruleset.
110
     *
111
     * @since 8.2.0
112
     *
113
     * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
114
     * @param string                $key       The name of the config value.
115
     *
116
     * @return string|null
117
     */
118
    public static function getCommandLineData(File $phpcsFile, $key)
119
    {
120
        if (class_exists('\PHP_CodeSniffer\Config')) {
121
            // PHPCS 3.x.
122
            $config = $phpcsFile->config;
123
            if (isset($config->{$key})) {
124
                return $config->{$key};
125
            }
126
        } else {
127
            // PHPCS 2.x.
128
            $config = $phpcsFile->phpcs->cli->getCommandLineValues();
129
            if (isset($config[$key])) {
130
                return $config[$key];
131
            }
132
        }
133
134
        return null;
135
    }
136
137
138
    /**
139
     * Returns the position of the first non-whitespace token in a statement.
140
     *
141
     * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File`
142
     * class and introduced in PHPCS 2.1.0 and improved in PHPCS 2.7.1.
143
     *
144
     * Once the minimum supported PHPCS version for this standard goes beyond
145
     * that, this method can be removed and calls to it replaced with
146
     * `$phpcsFile->findStartOfStatement($start, $ignore)` calls.
147
     *
148
     * Last synced with PHPCS version: PHPCS 3.3.2 at commit 6ad28354c04b364c3c71a34e4a18b629cc3b231e}
149
     *
150
     * @since 9.1.0
151
     *
152
     * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile.
153
     * @param int                   $start     The position to start searching from in the token stack.
154
     * @param int|array             $ignore    Token types that should not be considered stop points.
155
     *
156
     * @return int
157
     */
158
    public static function findStartOfStatement(File $phpcsFile, $start, $ignore = null)
159
    {
160
        if (version_compare(self::getVersion(), '2.7.1', '>=') === true) {
161
            return $phpcsFile->findStartOfStatement($start, $ignore);
162
        }
163
164
        $tokens    = $phpcsFile->getTokens();
165
        $endTokens = Tokens::$blockOpeners;
166
167
        $endTokens[\T_COLON]            = true;
168
        $endTokens[\T_COMMA]            = true;
169
        $endTokens[\T_DOUBLE_ARROW]     = true;
170
        $endTokens[\T_SEMICOLON]        = true;
171
        $endTokens[\T_OPEN_TAG]         = true;
172
        $endTokens[\T_CLOSE_TAG]        = true;
173
        $endTokens[\T_OPEN_SHORT_ARRAY] = true;
174
175 View Code Duplication
        if ($ignore !== null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
176
            $ignore = (array) $ignore;
177
            foreach ($ignore as $code) {
178
                if (isset($endTokens[$code]) === true) {
179
                    unset($endTokens[$code]);
180
                }
181
            }
182
        }
183
184
        $lastNotEmpty = $start;
185
186
        for ($i = $start; $i >= 0; $i--) {
187
            if (isset($endTokens[$tokens[$i]['code']]) === true) {
188
                // Found the end of the previous statement.
189
                return $lastNotEmpty;
190
            }
191
192
            if (isset($tokens[$i]['scope_opener']) === true
193
                && $i === $tokens[$i]['scope_closer']
194
            ) {
195
                // Found the end of the previous scope block.
196
                return $lastNotEmpty;
197
            }
198
199
            // Skip nested statements.
200 View Code Duplication
            if (isset($tokens[$i]['bracket_opener']) === true
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
201
                && $i === $tokens[$i]['bracket_closer']
202
            ) {
203
                $i = $tokens[$i]['bracket_opener'];
204
            } elseif (isset($tokens[$i]['parenthesis_opener']) === true
205
                && $i === $tokens[$i]['parenthesis_closer']
206
            ) {
207
                $i = $tokens[$i]['parenthesis_opener'];
208
            }
209
210 View Code Duplication
            if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
211
                $lastNotEmpty = $i;
212
            }
213
        }//end for
214
215
        return 0;
216
    }
217
218
219
    /**
220
     * Returns the position of the last non-whitespace token in a statement.
221
     *
222
     * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File`
223
     * class and introduced in PHPCS 2.1.0 and improved in PHPCS 2.7.1 and 3.3.0.
224
     *
225
     * Once the minimum supported PHPCS version for this standard goes beyond
226
     * that, this method can be removed and calls to it replaced with
227
     * `$phpcsFile->findEndOfStatement($start, $ignore)` calls.
228
     *
229
     * Last synced with PHPCS version: PHPCS 3.3.0-alpha at commit f5d899dcb5c534a1c3cca34668624517856ba823}
230
     *
231
     * @since 8.2.0
232
     *
233
     * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile.
234
     * @param int                   $start     The position to start searching from in the token stack.
235
     * @param int|array             $ignore    Token types that should not be considered stop points.
236
     *
237
     * @return int
238
     */
239
    public static function findEndOfStatement(File $phpcsFile, $start, $ignore = null)
240
    {
241
        if (version_compare(self::getVersion(), '3.3.0', '>=') === true) {
242
            return $phpcsFile->findEndOfStatement($start, $ignore);
243
        }
244
245
        $tokens    = $phpcsFile->getTokens();
246
        $endTokens = array(
247
            \T_COLON                => true,
248
            \T_COMMA                => true,
249
            \T_DOUBLE_ARROW         => true,
250
            \T_SEMICOLON            => true,
251
            \T_CLOSE_PARENTHESIS    => true,
252
            \T_CLOSE_SQUARE_BRACKET => true,
253
            \T_CLOSE_CURLY_BRACKET  => true,
254
            \T_CLOSE_SHORT_ARRAY    => true,
255
            \T_OPEN_TAG             => true,
256
            \T_CLOSE_TAG            => true,
257
        );
258
259 View Code Duplication
        if ($ignore !== null) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
260
            $ignore = (array) $ignore;
261
            foreach ($ignore as $code) {
262
                if (isset($endTokens[$code]) === true) {
263
                    unset($endTokens[$code]);
264
                }
265
            }
266
        }
267
268
        $lastNotEmpty = $start;
269
270
        for ($i = $start; $i < $phpcsFile->numTokens; $i++) {
271
            if ($i !== $start && isset($endTokens[$tokens[$i]['code']]) === true) {
272
                // Found the end of the statement.
273
                if ($tokens[$i]['code'] === \T_CLOSE_PARENTHESIS
274
                    || $tokens[$i]['code'] === \T_CLOSE_SQUARE_BRACKET
275
                    || $tokens[$i]['code'] === \T_CLOSE_CURLY_BRACKET
276
                    || $tokens[$i]['code'] === \T_CLOSE_SHORT_ARRAY
277
                    || $tokens[$i]['code'] === \T_OPEN_TAG
278
                    || $tokens[$i]['code'] === \T_CLOSE_TAG
279
                ) {
280
                    return $lastNotEmpty;
281
                }
282
283
                return $i;
284
            }
285
286
            // Skip nested statements.
287
            if (isset($tokens[$i]['scope_closer']) === true
288
                && ($i === $tokens[$i]['scope_opener']
289
                || $i === $tokens[$i]['scope_condition'])
290
            ) {
291
                if ($i === $start && isset(Tokens::$scopeOpeners[$tokens[$i]['code']]) === true) {
292
                    return $tokens[$i]['scope_closer'];
293
                }
294
295
                $i = $tokens[$i]['scope_closer'];
296 View Code Duplication
            } elseif (isset($tokens[$i]['bracket_closer']) === true
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
297
                && $i === $tokens[$i]['bracket_opener']
298
            ) {
299
                $i = $tokens[$i]['bracket_closer'];
300
            } elseif (isset($tokens[$i]['parenthesis_closer']) === true
301
                && $i === $tokens[$i]['parenthesis_opener']
302
            ) {
303
                $i = $tokens[$i]['parenthesis_closer'];
304
            }
305
306 View Code Duplication
            if (isset(Tokens::$emptyTokens[$tokens[$i]['code']]) === false) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
307
                $lastNotEmpty = $i;
308
            }
309
        }//end for
310
311
        return ($phpcsFile->numTokens - 1);
312
    }
313
314
315
    /**
316
     * Returns the name of the class that the specified class extends
317
     * (works for classes, anonymous classes and interfaces).
318
     *
319
     * Returns FALSE on error or if there is no extended class name.
320
     *
321
     * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File`
322
     * class, but with some improvements which have been introduced in
323
     * PHPCS 2.8.0.
324
     * {@link https://github.com/squizlabs/PHP_CodeSniffer/commit/0011d448119d4c568e3ac1f825ae78815bf2cc34}.
325
     *
326
     * Once the minimum supported PHPCS version for this standard goes beyond
327
     * that, this method can be removed and calls to it replaced with
328
     * `$phpcsFile->findExtendedClassName($stackPtr)` calls.
329
     *
330
     * Last synced with PHPCS version: PHPCS 3.1.0-alpha at commit a9efcc9b0703f3f9f4a900623d4e97128a6aafc6}
331
     *
332
     * @since 7.1.4
333
     * @since 8.2.0 Moved from the `Sniff` class to this class.
334
     *
335
     * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile.
336
     * @param int                   $stackPtr  The position of the class token in the stack.
337
     *
338
     * @return string|false
339
     */
340
    public static function findExtendedClassName(File $phpcsFile, $stackPtr)
341
    {
342
        if (version_compare(self::getVersion(), '3.1.0', '>=') === true) {
343
            return $phpcsFile->findExtendedClassName($stackPtr);
344
        }
345
346
        $tokens = $phpcsFile->getTokens();
347
348
        // Check for the existence of the token.
349
        if (isset($tokens[$stackPtr]) === false) {
350
            return false;
351
        }
352
353 View Code Duplication
        if ($tokens[$stackPtr]['code'] !== \T_CLASS
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
354
            && $tokens[$stackPtr]['type'] !== 'T_ANON_CLASS'
355
            && $tokens[$stackPtr]['type'] !== 'T_INTERFACE'
356
        ) {
357
            return false;
358
        }
359
360
        if (isset($tokens[$stackPtr]['scope_closer']) === false) {
361
            return false;
362
        }
363
364
        $classCloserIndex = $tokens[$stackPtr]['scope_closer'];
365
        $extendsIndex     = $phpcsFile->findNext(\T_EXTENDS, $stackPtr, $classCloserIndex);
366
        if ($extendsIndex === false) {
367
            return false;
368
        }
369
370
        $find = array(
371
            \T_NS_SEPARATOR,
372
            \T_STRING,
373
            \T_WHITESPACE,
374
        );
375
376
        $end  = $phpcsFile->findNext($find, ($extendsIndex + 1), $classCloserIndex, true);
377
        $name = $phpcsFile->getTokensAsString(($extendsIndex + 1), ($end - $extendsIndex - 1));
378
        $name = trim($name);
379
380
        if ($name === '') {
381
            return false;
382
        }
383
384
        return $name;
385
    }
386
387
388
    /**
389
     * Returns the name(s) of the interface(s) that the specified class implements.
390
     *
391
     * Returns FALSE on error or if there are no implemented interface names.
392
     *
393
     * {@internal Duplicate of same method as introduced in PHPCS 2.7.
394
     * This method also includes an improvement we use which was only introduced
395
     * in PHPCS 2.8.0, so only defer to upstream for higher versions.
396
     * Once the minimum supported PHPCS version for this sniff library goes beyond
397
     * that, this method can be removed and calls to it replaced with
398
     * `$phpcsFile->findImplementedInterfaceNames($stackPtr)` calls.}
399
     *
400
     * @since 7.0.3
401
     * @since 8.2.0 Moved from the `Sniff` class to this class.
402
     *
403
     * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
404
     * @param int                   $stackPtr  The position of the class token.
405
     *
406
     * @return array|false
407
     */
408
    public static function findImplementedInterfaceNames(File $phpcsFile, $stackPtr)
409
    {
410
        if (version_compare(self::getVersion(), '2.7.1', '>') === true) {
411
            return $phpcsFile->findImplementedInterfaceNames($stackPtr);
412
        }
413
414
        $tokens = $phpcsFile->getTokens();
415
416
        // Check for the existence of the token.
417
        if (isset($tokens[$stackPtr]) === false) {
418
            return false;
419
        }
420
421
        if ($tokens[$stackPtr]['code'] !== \T_CLASS
422
            && $tokens[$stackPtr]['type'] !== 'T_ANON_CLASS'
423
        ) {
424
            return false;
425
        }
426
427
        if (isset($tokens[$stackPtr]['scope_closer']) === false) {
428
            return false;
429
        }
430
431
        $classOpenerIndex = $tokens[$stackPtr]['scope_opener'];
432
        $implementsIndex  = $phpcsFile->findNext(\T_IMPLEMENTS, $stackPtr, $classOpenerIndex);
433
        if ($implementsIndex === false) {
434
            return false;
435
        }
436
437
        $find = array(
438
            \T_NS_SEPARATOR,
439
            \T_STRING,
440
            \T_WHITESPACE,
441
            \T_COMMA,
442
        );
443
444
        $end  = $phpcsFile->findNext($find, ($implementsIndex + 1), ($classOpenerIndex + 1), true);
445
        $name = $phpcsFile->getTokensAsString(($implementsIndex + 1), ($end - $implementsIndex - 1));
446
        $name = trim($name);
447
448
        if ($name === '') {
449
            return false;
450
        } else {
451
            $names = explode(',', $name);
452
            $names = array_map('trim', $names);
453
            return $names;
454
        }
455
    }
456
457
458
    /**
459
     * Returns the method parameters for the specified function token.
460
     *
461
     * Each parameter is in the following format:
462
     *
463
     * <code>
464
     *   0 => array(
465
     *         'name'              => '$var',  // The variable name.
466
     *         'token'             => integer, // The stack pointer to the variable name.
467
     *         'content'           => string,  // The full content of the variable definition.
468
     *         'pass_by_reference' => boolean, // Is the variable passed by reference?
469
     *         'variable_length'   => boolean, // Is the param of variable length through use of `...` ?
470
     *         'type_hint'         => string,  // The type hint for the variable.
471
     *         'type_hint_token'   => integer, // The stack pointer to the type hint
472
     *                                         // or false if there is no type hint.
473
     *         'nullable_type'     => boolean, // Is the variable using a nullable type?
474
     *        )
475
     * </code>
476
     *
477
     * Parameters with default values have an additional array index of
478
     * 'default' with the value of the default as a string.
479
     *
480
     * {@internal Duplicate of same method as contained in the `\PHP_CodeSniffer_File`
481
     * class.
482
     *
483
     * Last synced with PHPCS version: PHPCS 3.3.0-alpha at commit 53a28408d345044c0360c2c1b4a2aaebf4a3b8c9}
484
     *
485
     * @since 7.0.3
486
     * @since 8.2.0 Moved from the `Sniff` class to this class.
487
     *
488
     * @param \PHP_CodeSniffer_File $phpcsFile Instance of phpcsFile.
489
     * @param int                   $stackPtr  The position in the stack of the
490
     *                                         function token to acquire the
491
     *                                         parameters for.
492
     *
493
     * @return array|false
494
     * @throws \PHP_CodeSniffer_Exception If the specified $stackPtr is not of
495
     *                                    type T_FUNCTION or T_CLOSURE.
496
     */
497
    public static function getMethodParameters(File $phpcsFile, $stackPtr)
498
    {
499
        if (version_compare(self::getVersion(), '3.3.0', '>=') === true) {
500
            return $phpcsFile->getMethodParameters($stackPtr);
501
        }
502
503
        $tokens = $phpcsFile->getTokens();
504
505
        // Check for the existence of the token.
506
        if (isset($tokens[$stackPtr]) === false) {
507
            return false;
508
        }
509
510 View Code Duplication
        if ($tokens[$stackPtr]['code'] !== \T_FUNCTION
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
511
            && $tokens[$stackPtr]['code'] !== \T_CLOSURE
512
        ) {
513
            throw new PHPCS_Exception('$stackPtr must be of type T_FUNCTION or T_CLOSURE');
514
        }
515
516
        $opener = $tokens[$stackPtr]['parenthesis_opener'];
517
        $closer = $tokens[$stackPtr]['parenthesis_closer'];
518
519
        $vars            = array();
520
        $currVar         = null;
521
        $paramStart      = ($opener + 1);
522
        $defaultStart    = null;
523
        $paramCount      = 0;
524
        $passByReference = false;
525
        $variableLength  = false;
526
        $typeHint        = '';
527
        $typeHintToken   = false;
528
        $nullableType    = false;
529
530
        for ($i = $paramStart; $i <= $closer; $i++) {
531
            // Check to see if this token has a parenthesis or bracket opener. If it does
532
            // it's likely to be an array which might have arguments in it. This
533
            // could cause problems in our parsing below, so lets just skip to the
534
            // end of it.
535
            if (isset($tokens[$i]['parenthesis_opener']) === true) {
536
                // Don't do this if it's the close parenthesis for the method.
537
                if ($i !== $tokens[$i]['parenthesis_closer']) {
538
                    $i = ($tokens[$i]['parenthesis_closer'] + 1);
539
                }
540
            }
541
542
            if (isset($tokens[$i]['bracket_opener']) === true) {
543
                // Don't do this if it's the close parenthesis for the method.
544
                if ($i !== $tokens[$i]['bracket_closer']) {
545
                    $i = ($tokens[$i]['bracket_closer'] + 1);
546
                }
547
            }
548
549
            switch ($tokens[$i]['type']) {
550
                case 'T_BITWISE_AND':
551
                    if ($defaultStart === null) {
552
                        $passByReference = true;
553
                    }
554
                    break;
555
                case 'T_VARIABLE':
556
                    $currVar = $i;
557
                    break;
558
                case 'T_ELLIPSIS':
559
                    $variableLength = true;
560
                    break;
561
                case 'T_ARRAY_HINT': // Pre-PHPCS 3.3.0.
562
                case 'T_CALLABLE':
563
                    if ($typeHintToken === false) {
564
                        $typeHintToken = $i;
565
                    }
566
567
                    $typeHint .= $tokens[$i]['content'];
568
                    break;
569
                case 'T_SELF':
570
                case 'T_PARENT':
571 View Code Duplication
                case 'T_STATIC':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
572
                    // Self and parent are valid, static invalid, but was probably intended as type hint.
573
                    if (isset($defaultStart) === false) {
574
                        if ($typeHintToken === false) {
575
                            $typeHintToken = $i;
576
                        }
577
578
                        $typeHint .= $tokens[$i]['content'];
579
                    }
580
                    break;
581
                case 'T_STRING':
582
                    // This is a string, so it may be a type hint, but it could
583
                    // also be a constant used as a default value.
584
                    $prevComma = false;
585 View Code Duplication
                    for ($t = $i; $t >= $opener; $t--) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
586
                        if ($tokens[$t]['code'] === \T_COMMA) {
587
                            $prevComma = $t;
588
                            break;
589
                        }
590
                    }
591
592
                    if ($prevComma !== false) {
593
                        $nextEquals = false;
594 View Code Duplication
                        for ($t = $prevComma; $t < $i; $t++) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
595
                            if ($tokens[$t]['code'] === \T_EQUAL) {
596
                                $nextEquals = $t;
597
                                break;
598
                            }
599
                        }
600
601
                        if ($nextEquals !== false) {
602
                            break;
603
                        }
604
                    }
605
606
                    if ($defaultStart === null) {
607
                        if ($typeHintToken === false) {
608
                            $typeHintToken = $i;
609
                        }
610
611
                        $typeHint .= $tokens[$i]['content'];
612
                    }
613
                    break;
614 View Code Duplication
                case 'T_NS_SEPARATOR':
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
615
                    // Part of a type hint or default value.
616
                    if ($defaultStart === null) {
617
                        if ($typeHintToken === false) {
618
                            $typeHintToken = $i;
619
                        }
620
621
                        $typeHint .= $tokens[$i]['content'];
622
                    }
623
                    break;
624
                case 'T_NULLABLE':
625
                case 'T_INLINE_THEN': // Pre-PHPCS 2.8.0.
626
                    if ($defaultStart === null) {
627
                        $nullableType = true;
628
                        $typeHint    .= $tokens[$i]['content'];
629
                    }
630
                    break;
631
                case 'T_CLOSE_PARENTHESIS':
632
                case 'T_COMMA':
633
                    // If it's null, then there must be no parameters for this
634
                    // method.
635
                    if ($currVar === null) {
636
                        break;
637
                    }
638
639
                    $vars[$paramCount]            = array();
640
                    $vars[$paramCount]['token']   = $currVar;
641
                    $vars[$paramCount]['name']    = $tokens[$currVar]['content'];
642
                    $vars[$paramCount]['content'] = trim($phpcsFile->getTokensAsString($paramStart, ($i - $paramStart)));
643
644
                    if ($defaultStart !== null) {
645
                        $vars[$paramCount]['default'] = trim(
646
                            $phpcsFile->getTokensAsString(
647
                                $defaultStart,
648
                                ($i - $defaultStart)
649
                            )
650
                        );
651
                    }
652
653
                    $vars[$paramCount]['pass_by_reference'] = $passByReference;
654
                    $vars[$paramCount]['variable_length']   = $variableLength;
655
                    $vars[$paramCount]['type_hint']         = $typeHint;
656
                    $vars[$paramCount]['type_hint_token']   = $typeHintToken;
657
                    $vars[$paramCount]['nullable_type']     = $nullableType;
658
659
                    // Reset the vars, as we are about to process the next parameter.
660
                    $defaultStart    = null;
661
                    $paramStart      = ($i + 1);
662
                    $passByReference = false;
663
                    $variableLength  = false;
664
                    $typeHint        = '';
665
                    $typeHintToken   = false;
666
                    $nullableType    = false;
667
668
                    $paramCount++;
669
                    break;
670
                case 'T_EQUAL':
671
                    $defaultStart = ($i + 1);
672
                    break;
673
            }//end switch
674
        }//end for
675
676
        return $vars;
677
    }
678
}
679