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 ( ebb7bf...0a5ff4 )
by Chris
02:41 queued 11s
created

PEAR_Sniffs_Commenting_FunctionCommentSniff::processParams()   F

Complexity

Conditions 27
Paths 17856

Size

Total Lines 180
Code Lines 117

Duplication

Lines 87
Ratio 48.33 %

Importance

Changes 0
Metric Value
cc 27
eloc 117
nc 17856
nop 3
dl 87
loc 180
rs 2
c 0
b 0
f 0

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
 * 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
/**
17
 * Parses and verifies the doc comments for functions.
18
 *
19
 * @category  PHP
20
 * @package   PHP_CodeSniffer
21
 * @author    Greg Sherwood <[email protected]>
22
 * @author    Marc McIntyre <[email protected]>
23
 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
24
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
25
 * @version   Release: @package_version@
26
 * @link      http://pear.php.net/package/PHP_CodeSniffer
27
 */
28
class PEAR_Sniffs_Commenting_FunctionCommentSniff implements PHP_CodeSniffer_Sniff
29
{
30
31
32
    /**
33
     * Returns an array of tokens this test wants to listen for.
34
     *
35
     * @return array
36
     */
37
    public function register()
38
    {
39
        return array(T_FUNCTION);
40
41
    }//end register()
42
43
44
    /**
45
     * Processes this test, when one of its tokens is encountered.
46
     *
47
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
48
     * @param int                  $stackPtr  The position of the current token
49
     *                                        in the stack passed in $tokens.
50
     *
51
     * @return void
52
     */
53
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
54
    {
55
        $tokens = $phpcsFile->getTokens();
56
        $find   = PHP_CodeSniffer_Tokens::$methodPrefixes;
57
        $find[] = T_WHITESPACE;
58
59
        $commentEnd = $phpcsFile->findPrevious($find, ($stackPtr - 1), null, true);
60
        if ($tokens[$commentEnd]['code'] === T_COMMENT) {
61
            // Inline comments might just be closing comments for
62
            // control structures or functions instead of function comments
63
            // using the wrong comment type. If there is other code on the line,
64
            // assume they relate to that code.
65
            $prev = $phpcsFile->findPrevious($find, ($commentEnd - 1), null, true);
66
            if ($prev !== false && $tokens[$prev]['line'] === $tokens[$commentEnd]['line']) {
67
                $commentEnd = $prev;
68
            }
69
        }
70
71
        if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG
72
            && $tokens[$commentEnd]['code'] !== T_COMMENT
73
        ) {
74
            $phpcsFile->addError('Missing function doc comment', $stackPtr, 'Missing');
75
            $phpcsFile->recordMetric($stackPtr, 'Function has doc comment', 'no');
76
            return;
77
        } else {
78
            $phpcsFile->recordMetric($stackPtr, 'Function has doc comment', 'yes');
79
        }
80
81
        if ($tokens[$commentEnd]['code'] === T_COMMENT) {
82
            $phpcsFile->addError('You must use "/**" style comments for a function comment', $stackPtr, 'WrongStyle');
83
            return;
84
        }
85
86
        if ($tokens[$commentEnd]['line'] !== ($tokens[$stackPtr]['line'] - 1)) {
87
            $error = 'There must be no blank lines after the function comment';
88
            $phpcsFile->addError($error, $commentEnd, 'SpacingAfter');
89
        }
90
91
        $commentStart = $tokens[$commentEnd]['comment_opener'];
92
        foreach ($tokens[$commentStart]['comment_tags'] as $tag) {
93
            if ($tokens[$tag]['content'] === '@see') {
94
                // Make sure the tag isn't empty.
95
                $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd);
96
                if ($string === false || $tokens[$string]['line'] !== $tokens[$tag]['line']) {
97
                    $error = 'Content missing for @see tag in function comment';
98
                    $phpcsFile->addError($error, $tag, 'EmptySees');
99
                }
100
            }
101
        }
102
103
        $this->processReturn($phpcsFile, $stackPtr, $commentStart);
104
        $this->processThrows($phpcsFile, $stackPtr, $commentStart);
105
        $this->processParams($phpcsFile, $stackPtr, $commentStart);
106
107
    }//end process()
108
109
110
    /**
111
     * Process the return comment of this function comment.
112
     *
113
     * @param PHP_CodeSniffer_File $phpcsFile    The file being scanned.
114
     * @param int                  $stackPtr     The position of the current token
115
     *                                           in the stack passed in $tokens.
116
     * @param int                  $commentStart The position in the stack where the comment started.
117
     *
118
     * @return void
119
     */
120
    protected function processReturn(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $commentStart)
121
    {
122
        $tokens = $phpcsFile->getTokens();
123
124
        // Skip constructor and destructor.
125
        $methodName      = $phpcsFile->getDeclarationName($stackPtr);
126
        $isSpecialMethod = ($methodName === '__construct' || $methodName === '__destruct');
127
128
        $return = null;
129
        foreach ($tokens[$commentStart]['comment_tags'] as $tag) {
130
            if ($tokens[$tag]['content'] === '@return') {
131
                if ($return !== null) {
132
                    $error = 'Only 1 @return tag is allowed in a function comment';
133
                    $phpcsFile->addError($error, $tag, 'DuplicateReturn');
134
                    return;
135
                }
136
137
                $return = $tag;
138
            }
139
        }
140
141
        if ($isSpecialMethod === true) {
142
            return;
143
        }
144
145
        if ($return !== null) {
146
            $content = $tokens[($return + 2)]['content'];
147
            if (empty($content) === true || $tokens[($return + 2)]['code'] !== T_DOC_COMMENT_STRING) {
148
                $error = 'Return type missing for @return tag in function comment';
149
                $phpcsFile->addError($error, $return, 'MissingReturnType');
150
            }
151
        } else {
152
            $error = 'Missing @return tag in function comment';
153
            $phpcsFile->addError($error, $tokens[$commentStart]['comment_closer'], 'MissingReturn');
154
        }//end if
155
156
    }//end processReturn()
157
158
159
    /**
160
     * Process any throw tags that this function comment has.
161
     *
162
     * @param PHP_CodeSniffer_File $phpcsFile    The file being scanned.
163
     * @param int                  $stackPtr     The position of the current token
164
     *                                           in the stack passed in $tokens.
165
     * @param int                  $commentStart The position in the stack where the comment started.
166
     *
167
     * @return void
168
     */
169
    protected function processThrows(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $commentStart)
170
    {
171
        $tokens = $phpcsFile->getTokens();
172
173
        $throws = array();
174
        foreach ($tokens[$commentStart]['comment_tags'] as $tag) {
175
            if ($tokens[$tag]['content'] !== '@throws') {
176
                continue;
177
            }
178
179
            $exception = null;
180
            $comment   = null;
181
            if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) {
182
                $matches = array();
183
                preg_match('/([^\s]+)(?:\s+(.*))?/', $tokens[($tag + 2)]['content'], $matches);
184
                $exception = $matches[1];
185
                if (isset($matches[2]) === true) {
186
                    $comment = $matches[2];
187
                }
188
            }
189
190
            if ($exception === null) {
191
                $error = 'Exception type missing for @throws tag in function comment';
192
                $phpcsFile->addError($error, $tag, 'InvalidThrows');
193
            }
194
        }//end foreach
195
196
    }//end processThrows()
197
198
199
    /**
200
     * Process the function parameter comments.
201
     *
202
     * @param PHP_CodeSniffer_File $phpcsFile    The file being scanned.
203
     * @param int                  $stackPtr     The position of the current token
204
     *                                           in the stack passed in $tokens.
205
     * @param int                  $commentStart The position in the stack where the comment started.
206
     *
207
     * @return void
208
     */
209
    protected function processParams(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $commentStart)
210
    {
211
        $tokens = $phpcsFile->getTokens();
212
213
        $params  = array();
214
        $maxType = 0;
215
        $maxVar  = 0;
216
        foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) {
217
            if ($tokens[$tag]['content'] !== '@param') {
218
                continue;
219
            }
220
221
            $type      = '';
222
            $typeSpace = 0;
223
            $var       = '';
224
            $varSpace  = 0;
225
            $comment   = '';
226
            if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) {
227
                $matches = array();
228
                preg_match('/([^$&.]+)(?:((?:\.\.\.)?(?:\$|&)[^\s]+)(?:(\s+)(.*))?)?/', $tokens[($tag + 2)]['content'], $matches);
229
230
                if (empty($matches) === false) {
231
                    $typeLen   = strlen($matches[1]);
232
                    $type      = trim($matches[1]);
233
                    $typeSpace = ($typeLen - strlen($type));
234
                    $typeLen   = strlen($type);
235
                    if ($typeLen > $maxType) {
236
                        $maxType = $typeLen;
237
                    }
238
                }
239
240
                if (isset($matches[2]) === true) {
241
                    $var    = $matches[2];
242
                    $varLen = strlen($var);
243
                    if ($varLen > $maxVar) {
244
                        $maxVar = $varLen;
245
                    }
246
247
                    if (isset($matches[4]) === true) {
248
                        $varSpace = strlen($matches[3]);
249
                        $comment  = $matches[4];
250
251
                        // Any strings until the next tag belong to this comment.
252
                        if (isset($tokens[$commentStart]['comment_tags'][($pos + 1)]) === true) {
253
                            $end = $tokens[$commentStart]['comment_tags'][($pos + 1)];
254
                        } else {
255
                            $end = $tokens[$commentStart]['comment_closer'];
256
                        }
257
258
                        for ($i = ($tag + 3); $i < $end; $i++) {
259
                            if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) {
260
                                $comment .= ' '.$tokens[$i]['content'];
261
                            }
262
                        }
263
                    } else {
264
                        $error = 'Missing parameter comment';
265
                        $phpcsFile->addError($error, $tag, 'MissingParamComment');
266
                    }
267
                } else {
268
                    $error = 'Missing parameter name';
269
                    $phpcsFile->addError($error, $tag, 'MissingParamName');
270
                }//end if
271
            } else {
272
                $error = 'Missing parameter type';
273
                $phpcsFile->addError($error, $tag, 'MissingParamType');
274
            }//end if
275
276
            $params[] = array(
277
                         'tag'        => $tag,
278
                         'type'       => $type,
279
                         'var'        => $var,
280
                         'comment'    => $comment,
281
                         'type_space' => $typeSpace,
282
                         'var_space'  => $varSpace,
283
                        );
284
        }//end foreach
285
286
        $realParams  = $phpcsFile->getMethodParameters($stackPtr);
287
        $foundParams = array();
288
289
        // We want to use ... for all variable length arguments, so added
290
        // this prefix to the variable name so comparisons are easier.
291
        foreach ($realParams as $pos => $param) {
292
            if ($param['variable_length'] === true) {
293
                $realParams[$pos]['name'] = '...'.$realParams[$pos]['name'];
294
            }
295
        }
296
297
        foreach ($params as $pos => $param) {
298
            if ($param['var'] === '') {
299
                continue;
300
            }
301
302
            $foundParams[] = $param['var'];
303
304
            // Check number of spaces after the type.
305
            $spaces = ($maxType - strlen($param['type']) + 1);
306
            if ($param['type_space'] !== $spaces) {
307
                $error = 'Expected %s spaces after parameter type; %s found';
308
                $data  = array(
309
                          $spaces,
310
                          $param['type_space'],
311
                         );
312
313
                $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamType', $data);
314
                if ($fix === true) {
315
                    $content  = $param['type'];
316
                    $content .= str_repeat(' ', $spaces);
317
                    $content .= $param['var'];
318
                    $content .= str_repeat(' ', $param['var_space']);
319
                    $content .= $param['comment'];
320
                    $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content);
321
                }
322
            }
323
324
            // Make sure the param name is correct.
325
            if (isset($realParams[$pos]) === true) {
326
                $realName = $realParams[$pos]['name'];
327
                if ($realName !== $param['var']) {
328
                    $code = 'ParamNameNoMatch';
329
                    $data = array(
330
                             $param['var'],
331
                             $realName,
332
                            );
333
334
                    $error = 'Doc comment for parameter %s does not match ';
335
                    if (strtolower($param['var']) === strtolower($realName)) {
336
                        $error .= 'case of ';
337
                        $code   = 'ParamNameNoCaseMatch';
338
                    }
339
340
                    $error .= 'actual variable name %s';
341
342
                    $phpcsFile->addError($error, $param['tag'], $code, $data);
343
                }
344
            } else if (substr($param['var'], -4) !== ',...') {
345
                // We must have an extra parameter comment.
346
                $error = 'Superfluous parameter comment';
347
                $phpcsFile->addError($error, $param['tag'], 'ExtraParamComment');
348
            }//end if
349
350
            if ($param['comment'] === '') {
351
                continue;
352
            }
353
354
            // Check number of spaces after the var name.
355
            $spaces = ($maxVar - strlen($param['var']) + 1);
356
            if ($param['var_space'] !== $spaces) {
357
                $error = 'Expected %s spaces after parameter name; %s found';
358
                $data  = array(
359
                          $spaces,
360
                          $param['var_space'],
361
                         );
362
363
                $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamName', $data);
364
                if ($fix === true) {
365
                    $content  = $param['type'];
366
                    $content .= str_repeat(' ', $param['type_space']);
367
                    $content .= $param['var'];
368
                    $content .= str_repeat(' ', $spaces);
369
                    $content .= $param['comment'];
370
                    $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content);
371
                }
372
            }
373
        }//end foreach
374
375
        $realNames = array();
376
        foreach ($realParams as $realParam) {
377
            $realNames[] = $realParam['name'];
378
        }
379
380
        // Report missing comments.
381
        $diff = array_diff($realNames, $foundParams);
382
        foreach ($diff as $neededParam) {
383
            $error = 'Doc comment for parameter "%s" missing';
384
            $data  = array($neededParam);
385
            $phpcsFile->addError($error, $commentStart, 'MissingParamTag', $data);
386
        }
387
388
    }//end processParams()
389
390
391
}//end class
392