GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — develop ( 699b70...879176 )
by Chris
13:23
created

Squiz_Sniffs_Commenting_FunctionCommentSniff   D

Complexity

Total Complexity 105

Size/Duplication

Total Lines 565
Duplicated Lines 29.2 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
dl 165
loc 565
rs 4.8717
c 0
b 0
f 0
wmc 105
lcom 1
cbo 4

3 Methods

Rating   Name   Duplication   Size   Complexity  
F processReturn() 29 112 25
C processThrows() 10 57 13
F processParams() 126 348 67

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Squiz_Sniffs_Commenting_FunctionCommentSniff often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Squiz_Sniffs_Commenting_FunctionCommentSniff, and based on these observations, apply Extract Interface, too.

1
<?php
1 ignored issue
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 32 and the first side effect is on line 17.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * Parses and verifies the doc comments for functions.
4
 *
5
 * PHP version 5
6
 *
7
 * @category  PHP
8
 * @package   PHP_CodeSniffer
9
 * @author    Greg Sherwood <[email protected]>
10
 * @author    Marc McIntyre <[email protected]>
11
 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
12
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
13
 * @link      http://pear.php.net/package/PHP_CodeSniffer
14
 */
15
16
if (class_exists('PEAR_Sniffs_Commenting_FunctionCommentSniff', true) === false) {
17
    throw new PHP_CodeSniffer_Exception('Class PEAR_Sniffs_Commenting_FunctionCommentSniff not found');
18
}
19
20
/**
21
 * Parses and verifies the doc comments for functions.
22
 *
23
 * @category  PHP
24
 * @package   PHP_CodeSniffer
25
 * @author    Greg Sherwood <[email protected]>
26
 * @author    Marc McIntyre <[email protected]>
27
 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
28
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
29
 * @version   Release: @package_version@
30
 * @link      http://pear.php.net/package/PHP_CodeSniffer
31
 */
32
class Squiz_Sniffs_Commenting_FunctionCommentSniff extends PEAR_Sniffs_Commenting_FunctionCommentSniff
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
33
{
34
35
    /**
36
     * The current PHP version.
37
     *
38
     * @var integer
39
     */
40
    private $_phpVersion = null;
41
42
43
    /**
44
     * Process the return comment of this function comment.
45
     *
46
     * @param PHP_CodeSniffer_File $phpcsFile    The file being scanned.
47
     * @param int                  $stackPtr     The position of the current token
48
     *                                           in the stack passed in $tokens.
49
     * @param int                  $commentStart The position in the stack where the comment started.
50
     *
51
     * @return void
52
     */
53
    protected function processReturn(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $commentStart)
54
    {
55
        $tokens = $phpcsFile->getTokens();
56
57
        // Skip constructor and destructor.
58
        $methodName      = $phpcsFile->getDeclarationName($stackPtr);
59
        $isSpecialMethod = ($methodName === '__construct' || $methodName === '__destruct');
60
61
        $return = null;
62 View Code Duplication
        foreach ($tokens[$commentStart]['comment_tags'] as $tag) {
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...
63
            if ($tokens[$tag]['content'] === '@return') {
64
                if ($return !== null) {
65
                    $error = 'Only 1 @return tag is allowed in a function comment';
66
                    $phpcsFile->addError($error, $tag, 'DuplicateReturn');
67
                    return;
68
                }
69
70
                $return = $tag;
71
            }
72
        }
73
74
        if ($isSpecialMethod === true) {
75
            return;
76
        }
77
78
        if ($return !== null) {
79
            $content = $tokens[($return + 2)]['content'];
80
            if (empty($content) === true || $tokens[($return + 2)]['code'] !== T_DOC_COMMENT_STRING) {
81
                $error = 'Return type missing for @return tag in function comment';
82
                $phpcsFile->addError($error, $return, 'MissingReturnType');
83
            } else {
84
                // Check return type (can be multiple, separated by '|').
85
                $typeNames      = explode('|', $content);
86
                $suggestedNames = array();
87
                foreach ($typeNames as $i => $typeName) {
88
                    $suggestedName = PHP_CodeSniffer::suggestType($typeName);
89
                    if (in_array($suggestedName, $suggestedNames) === false) {
90
                        $suggestedNames[] = $suggestedName;
91
                    }
92
                }
93
94
                $suggestedType = implode('|', $suggestedNames);
95 View Code Duplication
                if ($content !== $suggestedType) {
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...
96
                    $error = 'Expected "%s" but found "%s" for function return type';
97
                    $data  = array(
98
                              $suggestedType,
99
                              $content,
100
                             );
101
                    $fix   = $phpcsFile->addFixableError($error, $return, 'InvalidReturn', $data);
102
                    if ($fix === true) {
103
                        $phpcsFile->fixer->replaceToken(($return + 2), $suggestedType);
104
                    }
105
                }
106
107
                // Support both a return type and a description. The return type
108
                // is anything up to the first space.
109
                $returnParts = explode(' ', $content, 2);
110
                $returnType  = $returnParts[0];
111
112
                // If the return type is void, make sure there is
113
                // no return statement in the function.
114
                if ($returnType === 'void') {
115
                    if (isset($tokens[$stackPtr]['scope_closer']) === true) {
116
                        $endToken = $tokens[$stackPtr]['scope_closer'];
117
                        for ($returnToken = $stackPtr; $returnToken < $endToken; $returnToken++) {
118
                            if ($tokens[$returnToken]['code'] === T_CLOSURE) {
119
                                $returnToken = $tokens[$returnToken]['scope_closer'];
120
                                continue;
121
                            }
122
123
                            if ($tokens[$returnToken]['code'] === T_RETURN
124
                                || $tokens[$returnToken]['code'] === T_YIELD
125
                            ) {
126
                                break;
127
                            }
128
                        }
129
130
                        if ($returnToken !== $endToken) {
131
                            // If the function is not returning anything, just
132
                            // exiting, then there is no problem.
133
                            $semicolon = $phpcsFile->findNext(T_WHITESPACE, ($returnToken + 1), null, true);
134
                            if ($tokens[$semicolon]['code'] !== T_SEMICOLON) {
135
                                $error = 'Function return type is void, but function contains return statement';
136
                                $phpcsFile->addError($error, $return, 'InvalidReturnVoid');
137
                            }
138
                        }
139
                    }//end if
140
                } else if ($returnType !== 'mixed') {
141
                    // If return type is not void, there needs to be a return statement
142
                    // somewhere in the function that returns something.
143
                    if (isset($tokens[$stackPtr]['scope_closer']) === true) {
144
                        $endToken    = $tokens[$stackPtr]['scope_closer'];
145
                        $returnToken = $phpcsFile->findNext(array(T_RETURN, T_YIELD), $stackPtr, $endToken);
146
                        if ($returnToken === false) {
147
                            $error = 'Function return type is not void, but function has no return statement';
148
                            $phpcsFile->addError($error, $return, 'InvalidNoReturn');
149 View Code Duplication
                        } else {
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...
150
                            $semicolon = $phpcsFile->findNext(T_WHITESPACE, ($returnToken + 1), null, true);
151
                            if ($tokens[$semicolon]['code'] === T_SEMICOLON) {
152
                                $error = 'Function return type is not void, but function is returning void here';
153
                                $phpcsFile->addError($error, $returnToken, 'InvalidReturnNotVoid');
154
                            }
155
                        }
156
                    }
157
                }//end if
158
            }//end if
159
        } else {
160
            $error = 'Missing @return tag in function comment';
161
            $phpcsFile->addError($error, $tokens[$commentStart]['comment_closer'], 'MissingReturn');
162
        }//end if
163
164
    }//end processReturn()
165
166
167
    /**
168
     * Process any throw tags that this function comment has.
169
     *
170
     * @param PHP_CodeSniffer_File $phpcsFile    The file being scanned.
171
     * @param int                  $stackPtr     The position of the current token
172
     *                                           in the stack passed in $tokens.
173
     * @param int                  $commentStart The position in the stack where the comment started.
174
     *
175
     * @return void
176
     */
177
    protected function processThrows(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $commentStart)
178
    {
179
        $tokens = $phpcsFile->getTokens();
180
181
        $throws = array();
0 ignored issues
show
Unused Code introduced by
$throws is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
182
        foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) {
183
            if ($tokens[$tag]['content'] !== '@throws') {
184
                continue;
185
            }
186
187
            $exception = null;
188
            $comment   = null;
189
            if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) {
190
                $matches = array();
191
                preg_match('/([^\s]+)(?:\s+(.*))?/', $tokens[($tag + 2)]['content'], $matches);
192
                $exception = $matches[1];
193
                if (isset($matches[2]) === true && trim($matches[2]) !== '') {
194
                    $comment = $matches[2];
195
                }
196
            }
197
198
            if ($exception === null) {
199
                $error = 'Exception type and comment missing for @throws tag in function comment';
200
                $phpcsFile->addError($error, $tag, 'InvalidThrows');
201
            } else if ($comment === null) {
202
                $error = 'Comment missing for @throws tag in function comment';
203
                $phpcsFile->addError($error, $tag, 'EmptyThrows');
204
            } else {
205
                // Any strings until the next tag belong to this comment.
206 View Code Duplication
                if (isset($tokens[$commentStart]['comment_tags'][($pos + 1)]) === 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...
207
                    $end = $tokens[$commentStart]['comment_tags'][($pos + 1)];
208
                } else {
209
                    $end = $tokens[$commentStart]['comment_closer'];
210
                }
211
212 View Code Duplication
                for ($i = ($tag + 3); $i < $end; $i++) {
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...
213
                    if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) {
214
                        $comment .= ' '.$tokens[$i]['content'];
215
                    }
216
                }
217
218
                // Starts with a capital letter and ends with a fullstop.
219
                $firstChar = $comment{0};
220
                if (strtoupper($firstChar) !== $firstChar) {
221
                    $error = '@throws tag comment must start with a capital letter';
222
                    $phpcsFile->addError($error, ($tag + 2), 'ThrowsNotCapital');
223
                }
224
225
                $lastChar = substr($comment, -1);
226
                if ($lastChar !== '.') {
227
                    $error = '@throws tag comment must end with a full stop';
228
                    $phpcsFile->addError($error, ($tag + 2), 'ThrowsNoFullStop');
229
                }
230
            }//end if
231
        }//end foreach
232
233
    }//end processThrows()
234
235
236
    /**
237
     * Process the function parameter comments.
238
     *
239
     * @param PHP_CodeSniffer_File $phpcsFile    The file being scanned.
240
     * @param int                  $stackPtr     The position of the current token
241
     *                                           in the stack passed in $tokens.
242
     * @param int                  $commentStart The position in the stack where the comment started.
243
     *
244
     * @return void
245
     */
246
    protected function processParams(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $commentStart)
247
    {
248 View Code Duplication
        if ($this->_phpVersion === 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...
249
            $this->_phpVersion = PHP_CodeSniffer::getConfigData('php_version');
0 ignored issues
show
Documentation Bug introduced by
It seems like \PHP_CodeSniffer::getConfigData('php_version') can also be of type string. However, the property $_phpVersion is declared as type integer. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
250
            if ($this->_phpVersion === null) {
251
                $this->_phpVersion = PHP_VERSION_ID;
252
            }
253
        }
254
255
        $tokens = $phpcsFile->getTokens();
256
257
        $params  = array();
258
        $maxType = 0;
259
        $maxVar  = 0;
260
        foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) {
261
            if ($tokens[$tag]['content'] !== '@param') {
262
                continue;
263
            }
264
265
            $type         = '';
266
            $typeSpace    = 0;
267
            $var          = '';
268
            $varSpace     = 0;
269
            $comment      = '';
270
            $commentLines = array();
271
            if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) {
272
                $matches = array();
273
                preg_match('/([^$&.]+)(?:((?:\.\.\.)?(?:\$|&)[^\s]+)(?:(\s+)(.*))?)?/', $tokens[($tag + 2)]['content'], $matches);
274
275 View Code Duplication
                if (empty($matches) === 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...
276
                    $typeLen   = strlen($matches[1]);
277
                    $type      = trim($matches[1]);
278
                    $typeSpace = ($typeLen - strlen($type));
279
                    $typeLen   = strlen($type);
280
                    if ($typeLen > $maxType) {
281
                        $maxType = $typeLen;
282
                    }
283
                }
284
285
                if (isset($matches[2]) === true) {
286
                    $var    = $matches[2];
287
                    $varLen = strlen($var);
288
                    if ($varLen > $maxVar) {
289
                        $maxVar = $varLen;
290
                    }
291
292
                    if (isset($matches[4]) === true) {
293
                        $varSpace       = strlen($matches[3]);
294
                        $comment        = $matches[4];
295
                        $commentLines[] = array(
296
                                           'comment' => $comment,
297
                                           'token'   => ($tag + 2),
298
                                           'indent'  => $varSpace,
299
                                          );
300
301
                        // Any strings until the next tag belong to this comment.
302 View Code Duplication
                        if (isset($tokens[$commentStart]['comment_tags'][($pos + 1)]) === 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...
303
                            $end = $tokens[$commentStart]['comment_tags'][($pos + 1)];
304
                        } else {
305
                            $end = $tokens[$commentStart]['comment_closer'];
306
                        }
307
308
                        for ($i = ($tag + 3); $i < $end; $i++) {
309
                            if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) {
310
                                $indent = 0;
311
                                if ($tokens[($i - 1)]['code'] === T_DOC_COMMENT_WHITESPACE) {
312
                                    $indent = strlen($tokens[($i - 1)]['content']);
313
                                }
314
315
                                $comment       .= ' '.$tokens[$i]['content'];
316
                                $commentLines[] = array(
317
                                                   'comment' => $tokens[$i]['content'],
318
                                                   'token'   => $i,
319
                                                   'indent'  => $indent,
320
                                                  );
321
                            }
322
                        }
323
                    } else {
324
                        $error = 'Missing parameter comment';
325
                        $phpcsFile->addError($error, $tag, 'MissingParamComment');
326
                        $commentLines[] = array('comment' => '');
327
                    }//end if
328
                } else {
329
                    $error = 'Missing parameter name';
330
                    $phpcsFile->addError($error, $tag, 'MissingParamName');
331
                }//end if
332
            } else {
333
                $error = 'Missing parameter type';
334
                $phpcsFile->addError($error, $tag, 'MissingParamType');
335
            }//end if
336
337
            $params[] = array(
338
                         'tag'          => $tag,
339
                         'type'         => $type,
340
                         'var'          => $var,
341
                         'comment'      => $comment,
342
                         'commentLines' => $commentLines,
343
                         'type_space'   => $typeSpace,
344
                         'var_space'    => $varSpace,
345
                        );
346
        }//end foreach
347
348
        $realParams  = $phpcsFile->getMethodParameters($stackPtr);
349
        $foundParams = array();
350
351
        // We want to use ... for all variable length arguments, so added
352
        // this prefix to the variable name so comparisons are easier.
353 View Code Duplication
        foreach ($realParams as $pos => $param) {
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
            if ($param['variable_length'] === true) {
355
                $realParams[$pos]['name'] = '...'.$realParams[$pos]['name'];
356
            }
357
        }
358
359
        foreach ($params as $pos => $param) {
360
            // If the type is empty, the whole line is empty.
361
            if ($param['type'] === '') {
362
                continue;
363
            }
364
365
            // Check the param type value.
366
            $typeNames = explode('|', $param['type']);
367
            foreach ($typeNames as $typeName) {
368
                $suggestedName = PHP_CodeSniffer::suggestType($typeName);
369
                if ($typeName !== $suggestedName) {
370
                    $error = 'Expected "%s" but found "%s" for parameter type';
371
                    $data  = array(
372
                              $suggestedName,
373
                              $typeName,
374
                             );
375
376
                    $fix = $phpcsFile->addFixableError($error, $param['tag'], 'IncorrectParamVarName', $data);
377
                    if ($fix === true) {
378
                        $content  = $suggestedName;
379
                        $content .= str_repeat(' ', $param['type_space']);
380
                        $content .= $param['var'];
381
                        $content .= str_repeat(' ', $param['var_space']);
382
                        if (isset($param['commentLines'][0]) === true) {
383
                            $content .= $param['commentLines'][0]['comment'];
384
                        }
385
386
                        $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content);
387
                    }
388
                } else if (count($typeNames) === 1) {
389
                    // Check type hint for array and custom type.
390
                    $suggestedTypeHint = '';
391
                    if (strpos($suggestedName, 'array') !== false || substr($suggestedName, -2) === '[]') {
392
                        $suggestedTypeHint = 'array';
393
                    } else if (strpos($suggestedName, 'callable') !== false) {
394
                        $suggestedTypeHint = 'callable';
395
                    } else if (strpos($suggestedName, 'callback') !== false) {
396
                        $suggestedTypeHint = 'callable';
397
                    } else if (in_array($typeName, PHP_CodeSniffer::$allowedTypes) === false) {
398
                        $suggestedTypeHint = $suggestedName;
399
                    } else if ($this->_phpVersion >= 70000) {
400
                        if ($typeName === 'string') {
401
                            $suggestedTypeHint = 'string';
402
                        } else if ($typeName === 'int' || $typeName === 'integer') {
403
                            $suggestedTypeHint = 'int';
404
                        } else if ($typeName === 'float') {
405
                            $suggestedTypeHint = 'float';
406
                        } else if ($typeName === 'bool' || $typeName === 'boolean') {
407
                            $suggestedTypeHint = 'bool';
408
                        }
409
                    }
410
411
                    if ($suggestedTypeHint !== '' && isset($realParams[$pos]) === true) {
412
                        $typeHint = $realParams[$pos]['type_hint'];
413
                        if ($typeHint === '') {
414
                            $error = 'Type hint "%s" missing for %s';
415
                            $data  = array(
416
                                      $suggestedTypeHint,
417
                                      $param['var'],
418
                                     );
419
420
                            $errorCode = 'TypeHintMissing';
421
                            if ($suggestedTypeHint === 'string'
422
                                || $suggestedTypeHint === 'int'
423
                                || $suggestedTypeHint === 'float'
424
                                || $suggestedTypeHint === 'bool'
425
                            ) {
426
                                $errorCode = 'Scalar'.$errorCode;
427
                            }
428
429
                            $phpcsFile->addError($error, $stackPtr, $errorCode, $data);
430
                        } else if ($typeHint !== substr($suggestedTypeHint, (strlen($typeHint) * -1))) {
431
                            $error = 'Expected type hint "%s"; found "%s" for %s';
432
                            $data  = array(
433
                                      $suggestedTypeHint,
434
                                      $typeHint,
435
                                      $param['var'],
436
                                     );
437
                            $phpcsFile->addError($error, $stackPtr, 'IncorrectTypeHint', $data);
438
                        }//end if
439
                    } else if ($suggestedTypeHint === '' && isset($realParams[$pos]) === true) {
440
                        $typeHint = $realParams[$pos]['type_hint'];
441
                        if ($typeHint !== '') {
442
                            $error = 'Unknown type hint "%s" found for %s';
443
                            $data  = array(
444
                                      $typeHint,
445
                                      $param['var'],
446
                                     );
447
                            $phpcsFile->addError($error, $stackPtr, 'InvalidTypeHint', $data);
448
                        }
449
                    }//end if
450
                }//end if
451
            }//end foreach
452
453
            if ($param['var'] === '') {
454
                continue;
455
            }
456
457
            $foundParams[] = $param['var'];
458
459
            // Check number of spaces after the type.
460
            $spaces = ($maxType - strlen($param['type']) + 1);
461 View Code Duplication
            if ($param['type_space'] !== $spaces) {
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...
462
                $error = 'Expected %s spaces after parameter type; %s found';
463
                $data  = array(
464
                          $spaces,
465
                          $param['type_space'],
466
                         );
467
468
                $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamType', $data);
469
                if ($fix === true) {
470
                    $phpcsFile->fixer->beginChangeset();
471
472
                    $content  = $param['type'];
473
                    $content .= str_repeat(' ', $spaces);
474
                    $content .= $param['var'];
475
                    $content .= str_repeat(' ', $param['var_space']);
476
                    $content .= $param['commentLines'][0]['comment'];
477
                    $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content);
478
479
                    // Fix up the indent of additional comment lines.
480
                    foreach ($param['commentLines'] as $lineNum => $line) {
481
                        if ($lineNum === 0
482
                            || $param['commentLines'][$lineNum]['indent'] === 0
483
                        ) {
484
                            continue;
485
                        }
486
487
                        $newIndent = ($param['commentLines'][$lineNum]['indent'] + $spaces - $param['type_space']);
488
                        $phpcsFile->fixer->replaceToken(
489
                            ($param['commentLines'][$lineNum]['token'] - 1),
490
                            str_repeat(' ', $newIndent)
491
                        );
492
                    }
493
494
                    $phpcsFile->fixer->endChangeset();
495
                }//end if
496
            }//end if
497
498
            // Make sure the param name is correct.
499 View Code Duplication
            if (isset($realParams[$pos]) === 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...
500
                $realName = $realParams[$pos]['name'];
501
                if ($realName !== $param['var']) {
502
                    $code = 'ParamNameNoMatch';
503
                    $data = array(
504
                             $param['var'],
505
                             $realName,
506
                            );
507
508
                    $error = 'Doc comment for parameter %s does not match ';
509
                    if (strtolower($param['var']) === strtolower($realName)) {
510
                        $error .= 'case of ';
511
                        $code   = 'ParamNameNoCaseMatch';
512
                    }
513
514
                    $error .= 'actual variable name %s';
515
516
                    $phpcsFile->addError($error, $param['tag'], $code, $data);
517
                }
518
            } else if (substr($param['var'], -4) !== ',...') {
519
                // We must have an extra parameter comment.
520
                $error = 'Superfluous parameter comment';
521
                $phpcsFile->addError($error, $param['tag'], 'ExtraParamComment');
522
            }//end if
523
524
            if ($param['comment'] === '') {
525
                continue;
526
            }
527
528
            // Check number of spaces after the var name.
529
            $spaces = ($maxVar - strlen($param['var']) + 1);
530 View Code Duplication
            if ($param['var_space'] !== $spaces) {
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...
531
                $error = 'Expected %s spaces after parameter name; %s found';
532
                $data  = array(
533
                          $spaces,
534
                          $param['var_space'],
535
                         );
536
537
                $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamName', $data);
538
                if ($fix === true) {
539
                    $phpcsFile->fixer->beginChangeset();
540
541
                    $content  = $param['type'];
542
                    $content .= str_repeat(' ', $param['type_space']);
543
                    $content .= $param['var'];
544
                    $content .= str_repeat(' ', $spaces);
545
                    $content .= $param['commentLines'][0]['comment'];
546
                    $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content);
547
548
                    // Fix up the indent of additional comment lines.
549
                    foreach ($param['commentLines'] as $lineNum => $line) {
550
                        if ($lineNum === 0
551
                            || $param['commentLines'][$lineNum]['indent'] === 0
552
                        ) {
553
                            continue;
554
                        }
555
556
                        $newIndent = ($param['commentLines'][$lineNum]['indent'] + $spaces - $param['var_space']);
557
                        $phpcsFile->fixer->replaceToken(
558
                            ($param['commentLines'][$lineNum]['token'] - 1),
559
                            str_repeat(' ', $newIndent)
560
                        );
561
                    }
562
563
                    $phpcsFile->fixer->endChangeset();
564
                }//end if
565
            }//end if
566
567
            // Param comments must start with a capital letter and end with the full stop.
568
            if (preg_match('/^(\p{Ll}|\P{L})/u', $param['comment']) === 1) {
569
                $error = 'Parameter comment must start with a capital letter';
570
                $phpcsFile->addError($error, $param['tag'], 'ParamCommentNotCapital');
571
            }
572
573
            $lastChar = substr($param['comment'], -1);
574
            if ($lastChar !== '.') {
575
                $error = 'Parameter comment must end with a full stop';
576
                $phpcsFile->addError($error, $param['tag'], 'ParamCommentFullStop');
577
            }
578
        }//end foreach
579
580
        $realNames = array();
581
        foreach ($realParams as $realParam) {
582
            $realNames[] = $realParam['name'];
583
        }
584
585
        // Report missing comments.
586
        $diff = array_diff($realNames, $foundParams);
587 View Code Duplication
        foreach ($diff as $neededParam) {
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...
588
            $error = 'Doc comment for parameter "%s" missing';
589
            $data  = array($neededParam);
590
            $phpcsFile->addError($error, $commentStart, 'MissingParamTag', $data);
591
        }
592
593
    }//end processParams()
594
595
596
}//end class
597