• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PHPCSStandards / PHP_CodeSniffer / 15036337869

15 May 2025 04:03AM UTC coverage: 78.375% (-0.2%) from 78.556%
15036337869

Pull #856

github

web-flow
Merge 93f570b46 into f5e7943d0
Pull Request #856: [Doc] Cover all errors of PEAR ClassDeclaration

25112 of 32041 relevant lines covered (78.37%)

69.4 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

96.98
/src/Standards/PEAR/Sniffs/Commenting/FunctionCommentSniff.php
1
<?php
2
/**
3
 * Parses and verifies the doc comments for functions.
4
 *
5
 * @author    Greg Sherwood <gsherwood@squiz.net>
6
 * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
7
 * @license   https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8
 */
9

10
namespace PHP_CodeSniffer\Standards\PEAR\Sniffs\Commenting;
11

12
use PHP_CodeSniffer\Files\File;
13
use PHP_CodeSniffer\Sniffs\Sniff;
14
use PHP_CodeSniffer\Util\Tokens;
15

16
class FunctionCommentSniff implements Sniff
17
{
18

19
    /**
20
     * Disable the check for functions with a lower visibility than the value given.
21
     *
22
     * Allowed values are public, protected, and private.
23
     *
24
     * @var string
25
     */
26
    public $minimumVisibility = 'private';
27

28
    /**
29
     * Array of methods which do not require a return type.
30
     *
31
     * @var array
32
     */
33
    public $specialMethods = [
34
        '__construct',
35
        '__destruct',
36
    ];
37

38

39
    /**
40
     * Returns an array of tokens this test wants to listen for.
41
     *
42
     * @return array<int|string>
43
     */
44
    public function register()
3✔
45
    {
46
        return [T_FUNCTION];
3✔
47

48
    }//end register()
49

50

51
    /**
52
     * Processes this test, when one of its tokens is encountered.
53
     *
54
     * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
55
     * @param int                         $stackPtr  The position of the current token
56
     *                                               in the stack passed in $tokens.
57
     *
58
     * @return void
59
     */
60
    public function process(File $phpcsFile, $stackPtr)
3✔
61
    {
62
        $scopeModifier = $phpcsFile->getMethodProperties($stackPtr)['scope'];
3✔
63
        if (($scopeModifier === 'protected'
2✔
64
            && $this->minimumVisibility === 'public')
3✔
65
            || ($scopeModifier === 'private'
2✔
66
            && ($this->minimumVisibility === 'public' || $this->minimumVisibility === 'protected'))
3✔
67
        ) {
1✔
68
            return;
3✔
69
        }
70

71
        $tokens = $phpcsFile->getTokens();
3✔
72
        $ignore = Tokens::$methodPrefixes;
3✔
73
        $ignore[T_WHITESPACE] = T_WHITESPACE;
3✔
74

75
        for ($commentEnd = ($stackPtr - 1); $commentEnd >= 0; $commentEnd--) {
3✔
76
            if (isset($ignore[$tokens[$commentEnd]['code']]) === true) {
3✔
77
                continue;
3✔
78
            }
79

80
            if ($tokens[$commentEnd]['code'] === T_ATTRIBUTE_END
3✔
81
                && isset($tokens[$commentEnd]['attribute_opener']) === true
3✔
82
            ) {
1✔
83
                $commentEnd = $tokens[$commentEnd]['attribute_opener'];
3✔
84
                continue;
3✔
85
            }
86

87
            break;
3✔
88
        }
89

90
        if ($tokens[$commentEnd]['code'] === T_COMMENT) {
3✔
91
            // Inline comments might just be closing comments for
92
            // control structures or functions instead of function comments
93
            // using the wrong comment type. If there is other code on the line,
94
            // assume they relate to that code.
95
            $prev = $phpcsFile->findPrevious($ignore, ($commentEnd - 1), null, true);
3✔
96
            if ($prev !== false && $tokens[$prev]['line'] === $tokens[$commentEnd]['line']) {
3✔
97
                $commentEnd = $prev;
3✔
98
            }
1✔
99
        }
1✔
100

101
        if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG
3✔
102
            && $tokens[$commentEnd]['code'] !== T_COMMENT
3✔
103
        ) {
1✔
104
            $function = $phpcsFile->getDeclarationName($stackPtr);
3✔
105
            $phpcsFile->addError(
3✔
106
                'Missing doc comment for function %s()',
3✔
107
                $stackPtr,
3✔
108
                'Missing',
3✔
109
                [$function]
3✔
110
            );
2✔
111
            $phpcsFile->recordMetric($stackPtr, 'Function has doc comment', 'no');
3✔
112
            return;
3✔
113
        } else {
114
            $phpcsFile->recordMetric($stackPtr, 'Function has doc comment', 'yes');
3✔
115
        }
116

117
        if ($tokens[$commentEnd]['code'] === T_COMMENT) {
3✔
118
            $phpcsFile->addError('You must use "/**" style comments for a function comment', $stackPtr, 'WrongStyle');
3✔
119
            return;
3✔
120
        }
121

122
        // Check there are no blank lines in the preamble for the property,
123
        // but ignore blank lines _within_ attributes as that's not the concern of this sniff.
124
        if ($tokens[$commentEnd]['line'] !== ($tokens[$stackPtr]['line'] - 1)) {
3✔
125
            for ($i = ($commentEnd + 1); $i < $stackPtr; $i++) {
3✔
126
                // Skip over the contents of attributes.
127
                if (isset($tokens[$i]['attribute_closer']) === true) {
3✔
128
                    $i = $tokens[$i]['attribute_closer'];
3✔
129
                    continue;
3✔
130
                }
131

132
                if ($tokens[$i]['column'] !== 1
3✔
133
                    || $tokens[$i]['code'] !== T_WHITESPACE
3✔
134
                    || $tokens[$i]['line'] === $tokens[($i + 1)]['line']
3✔
135
                    // Do not report blank lines after a PHPCS annotation as removing the blank lines could change the meaning.
136
                    || isset(Tokens::$phpcsCommentTokens[$tokens[($i - 1)]['code']]) === true
3✔
137
                ) {
1✔
138
                    continue;
3✔
139
                }
140

141
                $nextNonWhitespace = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), null, true);
3✔
142
                $error = 'There must be no blank lines between the function comment and the declaration';
3✔
143
                $fix   = $phpcsFile->addFixableError($error, $i, 'SpacingAfter');
3✔
144

145
                if ($fix === true) {
3✔
146
                    $phpcsFile->fixer->beginChangeset();
3✔
147

148
                    for ($j = $i; $j < $nextNonWhitespace; $j++) {
3✔
149
                        if ($tokens[$j]['line'] === $tokens[$nextNonWhitespace]['line']) {
3✔
150
                            break;
3✔
151
                        }
152

153
                        $phpcsFile->fixer->replaceToken($j, '');
3✔
154
                    }
1✔
155

156
                    $phpcsFile->fixer->endChangeset();
3✔
157
                }
1✔
158

159
                $i = $nextNonWhitespace;
3✔
160
            }//end for
1✔
161
        }//end if
1✔
162

163
        $commentStart = $tokens[$commentEnd]['comment_opener'];
3✔
164
        foreach ($tokens[$commentStart]['comment_tags'] as $tag) {
3✔
165
            if ($tokens[$tag]['content'] === '@see') {
3✔
166
                // Make sure the tag isn't empty.
167
                $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd);
3✔
168
                if ($string === false || $tokens[$string]['line'] !== $tokens[$tag]['line']) {
3✔
169
                    $error = 'Content missing for @see tag in function comment';
×
170
                    $phpcsFile->addError($error, $tag, 'EmptySees');
×
171
                }
172
            }
1✔
173
        }
1✔
174

175
        $this->processReturn($phpcsFile, $stackPtr, $commentStart);
3✔
176
        $this->processThrows($phpcsFile, $stackPtr, $commentStart);
3✔
177
        $this->processParams($phpcsFile, $stackPtr, $commentStart);
3✔
178

179
    }//end process()
2✔
180

181

182
    /**
183
     * Process the return comment of this function comment.
184
     *
185
     * @param \PHP_CodeSniffer\Files\File $phpcsFile    The file being scanned.
186
     * @param int                         $stackPtr     The position of the current token
187
     *                                                  in the stack passed in $tokens.
188
     * @param int                         $commentStart The position in the stack where the comment started.
189
     *
190
     * @return void
191
     */
192
    protected function processReturn(File $phpcsFile, $stackPtr, $commentStart)
3✔
193
    {
194
        $tokens = $phpcsFile->getTokens();
3✔
195

196
        // Skip constructor and destructor.
197
        $methodName      = $phpcsFile->getDeclarationName($stackPtr);
3✔
198
        $isSpecialMethod = in_array($methodName,  $this->specialMethods, true);
3✔
199

200
        $return = null;
3✔
201
        foreach ($tokens[$commentStart]['comment_tags'] as $tag) {
3✔
202
            if ($tokens[$tag]['content'] === '@return') {
3✔
203
                if ($return !== null) {
3✔
204
                    $error = 'Only 1 @return tag is allowed in a function comment';
×
205
                    $phpcsFile->addError($error, $tag, 'DuplicateReturn');
×
206
                    return;
×
207
                }
208

209
                $return = $tag;
3✔
210
            }
1✔
211
        }
1✔
212

213
        if ($return !== null) {
3✔
214
            $content = $tokens[($return + 2)]['content'];
3✔
215
            if (empty($content) === true || $tokens[($return + 2)]['code'] !== T_DOC_COMMENT_STRING) {
3✔
216
                $error = 'Return type missing for @return tag in function comment';
3✔
217
                $phpcsFile->addError($error, $return, 'MissingReturnType');
3✔
218
            }
1✔
219
        } else {
1✔
220
            if ($isSpecialMethod === true) {
3✔
221
                return;
3✔
222
            }
223

224
            $error = 'Missing @return tag in function comment';
3✔
225
            $phpcsFile->addError($error, $tokens[$commentStart]['comment_closer'], 'MissingReturn');
3✔
226
        }//end if
227

228
    }//end processReturn()
2✔
229

230

231
    /**
232
     * Process any throw tags that this function comment has.
233
     *
234
     * @param \PHP_CodeSniffer\Files\File $phpcsFile    The file being scanned.
235
     * @param int                         $stackPtr     The position of the current token
236
     *                                                  in the stack passed in $tokens.
237
     * @param int                         $commentStart The position in the stack where the comment started.
238
     *
239
     * @return void
240
     */
241
    protected function processThrows(File $phpcsFile, $stackPtr, $commentStart)
3✔
242
    {
243
        $tokens = $phpcsFile->getTokens();
3✔
244

245
        foreach ($tokens[$commentStart]['comment_tags'] as $tag) {
3✔
246
            if ($tokens[$tag]['content'] !== '@throws') {
3✔
247
                continue;
3✔
248
            }
249

250
            $exception = null;
3✔
251
            if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) {
3✔
252
                $matches = [];
3✔
253
                preg_match('/([^\s]+)(?:\s+(.*))?/', $tokens[($tag + 2)]['content'], $matches);
3✔
254
                $exception = $matches[1];
3✔
255
            }
1✔
256

257
            if ($exception === null) {
3✔
258
                $error = 'Exception type missing for @throws tag in function comment';
3✔
259
                $phpcsFile->addError($error, $tag, 'InvalidThrows');
3✔
260
            }
1✔
261
        }//end foreach
1✔
262

263
    }//end processThrows()
2✔
264

265

266
    /**
267
     * Process the function parameter comments.
268
     *
269
     * @param \PHP_CodeSniffer\Files\File $phpcsFile    The file being scanned.
270
     * @param int                         $stackPtr     The position of the current token
271
     *                                                  in the stack passed in $tokens.
272
     * @param int                         $commentStart The position in the stack where the comment started.
273
     *
274
     * @return void
275
     */
276
    protected function processParams(File $phpcsFile, $stackPtr, $commentStart)
3✔
277
    {
278
        $tokens = $phpcsFile->getTokens();
3✔
279

280
        $params  = [];
3✔
281
        $maxType = 0;
3✔
282
        $maxVar  = 0;
3✔
283
        foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) {
3✔
284
            if ($tokens[$tag]['content'] !== '@param') {
3✔
285
                continue;
3✔
286
            }
287

288
            $type          = '';
3✔
289
            $typeSpace     = 0;
3✔
290
            $var           = '';
3✔
291
            $varSpace      = 0;
3✔
292
            $comment       = '';
3✔
293
            $commentEnd    = 0;
3✔
294
            $commentTokens = [];
3✔
295

296
            if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) {
3✔
297
                $matches = [];
3✔
298
                preg_match('/((?:(?![$.]|&(?=\$)).)*)(?:((?:\.\.\.)?(?:\$|&)[^\s]+)(?:(\s+)(.*))?)?/', $tokens[($tag + 2)]['content'], $matches);
3✔
299

300
                if (empty($matches) === false) {
3✔
301
                    $typeLen   = strlen($matches[1]);
3✔
302
                    $type      = trim($matches[1]);
3✔
303
                    $typeSpace = ($typeLen - strlen($type));
3✔
304
                    $typeLen   = strlen($type);
3✔
305
                    if ($typeLen > $maxType) {
3✔
306
                        $maxType = $typeLen;
3✔
307
                    }
1✔
308
                }
1✔
309

310
                if (isset($matches[2]) === true) {
3✔
311
                    $var    = $matches[2];
3✔
312
                    $varLen = strlen($var);
3✔
313
                    if ($varLen > $maxVar) {
3✔
314
                        $maxVar = $varLen;
3✔
315
                    }
1✔
316

317
                    if (isset($matches[4]) === true) {
3✔
318
                        $varSpace = strlen($matches[3]);
3✔
319
                        $comment  = $matches[4];
3✔
320

321
                        // Any strings until the next tag belong to this comment.
322
                        if (isset($tokens[$commentStart]['comment_tags'][($pos + 1)]) === true) {
3✔
323
                            $end = $tokens[$commentStart]['comment_tags'][($pos + 1)];
3✔
324
                        } else {
1✔
325
                            $end = $tokens[$commentStart]['comment_closer'];
×
326
                        }
327

328
                        for ($i = ($tag + 3); $i < $end; $i++) {
3✔
329
                            if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) {
3✔
330
                                $comment        .= ' '.$tokens[$i]['content'];
3✔
331
                                $commentEnd      = $i;
3✔
332
                                $commentTokens[] = $i;
3✔
333
                            }
1✔
334
                        }
1✔
335
                    } else {
1✔
336
                        $error = 'Missing parameter comment';
3✔
337
                        $phpcsFile->addError($error, $tag, 'MissingParamComment');
3✔
338
                    }//end if
339
                } else {
1✔
340
                    $error = 'Missing parameter name';
3✔
341
                    $phpcsFile->addError($error, $tag, 'MissingParamName');
3✔
342
                }//end if
343
            } else {
1✔
344
                $error = 'Missing parameter type';
3✔
345
                $phpcsFile->addError($error, $tag, 'MissingParamType');
3✔
346
            }//end if
347

348
            $params[] = [
3✔
349
                'tag'            => $tag,
3✔
350
                'type'           => $type,
3✔
351
                'var'            => $var,
3✔
352
                'comment'        => $comment,
3✔
353
                'comment_end'    => $commentEnd,
3✔
354
                'comment_tokens' => $commentTokens,
3✔
355
                'type_space'     => $typeSpace,
3✔
356
                'var_space'      => $varSpace,
3✔
357
            ];
1✔
358
        }//end foreach
1✔
359

360
        $realParams  = $phpcsFile->getMethodParameters($stackPtr);
3✔
361
        $foundParams = [];
3✔
362

363
        // We want to use ... for all variable length arguments, so add
364
        // this prefix to the variable name so comparisons are easier.
365
        foreach ($realParams as $pos => $param) {
3✔
366
            if ($param['variable_length'] === true) {
3✔
367
                $realParams[$pos]['name'] = '...'.$realParams[$pos]['name'];
3✔
368
            }
1✔
369
        }
1✔
370

371
        foreach ($params as $pos => $param) {
3✔
372
            if ($param['var'] === '') {
3✔
373
                continue;
3✔
374
            }
375

376
            $foundParams[] = $param['var'];
3✔
377

378
            if (trim($param['type']) !== '') {
3✔
379
                // Check number of spaces after the type.
380
                $spaces = ($maxType - strlen($param['type']) + 1);
3✔
381
                if ($param['type_space'] !== $spaces) {
3✔
382
                    $error = 'Expected %s spaces after parameter type; %s found';
3✔
383
                    $data  = [
1✔
384
                        $spaces,
3✔
385
                        $param['type_space'],
3✔
386
                    ];
2✔
387

388
                    $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamType', $data);
3✔
389
                    if ($fix === true) {
3✔
390
                        $commentToken = ($param['tag'] + 2);
3✔
391

392
                        $content  = $param['type'];
3✔
393
                        $content .= str_repeat(' ', $spaces);
3✔
394
                        $content .= $param['var'];
3✔
395
                        $content .= str_repeat(' ', $param['var_space']);
3✔
396

397
                        $wrapLength = ($tokens[$commentToken]['length'] - $param['type_space'] - $param['var_space'] - strlen($param['type']) - strlen($param['var']));
3✔
398

399
                        $star        = $phpcsFile->findPrevious(T_DOC_COMMENT_STAR, $param['tag']);
3✔
400
                        $spaceLength = (strlen($content) + $tokens[($commentToken - 1)]['length'] + $tokens[($commentToken - 2)]['length']);
3✔
401

402
                        $padding  = str_repeat(' ', ($tokens[$star]['column'] - 1));
3✔
403
                        $padding .= '* ';
3✔
404
                        $padding .= str_repeat(' ', $spaceLength);
3✔
405

406
                        $content .= wordwrap(
3✔
407
                            $param['comment'],
3✔
408
                            $wrapLength,
3✔
409
                            $phpcsFile->eolChar.$padding
3✔
410
                        );
2✔
411

412
                        $phpcsFile->fixer->replaceToken($commentToken, $content);
3✔
413
                        for ($i = ($commentToken + 1); $i <= $param['comment_end']; $i++) {
3✔
414
                            $phpcsFile->fixer->replaceToken($i, '');
×
415
                        }
416
                    }//end if
1✔
417
                }//end if
1✔
418
            }//end if
1✔
419

420
            // Make sure the param name is correct.
421
            if (isset($realParams[$pos]) === true) {
3✔
422
                $realName = $realParams[$pos]['name'];
3✔
423
                if ($realName !== $param['var']) {
3✔
424
                    $code = 'ParamNameNoMatch';
3✔
425
                    $data = [
1✔
426
                        $param['var'],
3✔
427
                        $realName,
3✔
428
                    ];
2✔
429

430
                    $error = 'Doc comment for parameter %s does not match ';
3✔
431
                    if (strtolower($param['var']) === strtolower($realName)) {
3✔
432
                        $error .= 'case of ';
×
433
                        $code   = 'ParamNameNoCaseMatch';
×
434
                    }
435

436
                    $error .= 'actual variable name %s';
3✔
437

438
                    $phpcsFile->addError($error, $param['tag'], $code, $data);
3✔
439
                }
1✔
440
            } else if (substr($param['var'], -4) !== ',...') {
3✔
441
                // We must have an extra parameter comment.
442
                $error = 'Superfluous parameter comment';
3✔
443
                $phpcsFile->addError($error, $param['tag'], 'ExtraParamComment');
3✔
444
            }//end if
1✔
445

446
            if ($param['comment'] === '') {
3✔
447
                continue;
3✔
448
            }
449

450
            // Check number of spaces after the param name.
451
            $spaces = ($maxVar - strlen($param['var']) + 1);
3✔
452
            if ($param['var_space'] !== $spaces) {
3✔
453
                $error = 'Expected %s spaces after parameter name; %s found';
3✔
454
                $data  = [
1✔
455
                    $spaces,
3✔
456
                    $param['var_space'],
3✔
457
                ];
2✔
458

459
                $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamName', $data);
3✔
460
                if ($fix === true) {
3✔
461
                    $commentToken = ($param['tag'] + 2);
3✔
462

463
                    $content  = $param['type'];
3✔
464
                    $content .= str_repeat(' ', $param['type_space']);
3✔
465
                    $content .= $param['var'];
3✔
466
                    $content .= str_repeat(' ', $spaces);
3✔
467

468
                    $wrapLength = ($tokens[$commentToken]['length'] - $param['type_space'] - $param['var_space'] - strlen($param['type']) - strlen($param['var']));
3✔
469

470
                    $star        = $phpcsFile->findPrevious(T_DOC_COMMENT_STAR, $param['tag']);
3✔
471
                    $spaceLength = (strlen($content) + $tokens[($commentToken - 1)]['length'] + $tokens[($commentToken - 2)]['length']);
3✔
472

473
                    $padding  = str_repeat(' ', ($tokens[$star]['column'] - 1));
3✔
474
                    $padding .= '* ';
3✔
475
                    $padding .= str_repeat(' ', $spaceLength);
3✔
476

477
                    $content .= wordwrap(
3✔
478
                        $param['comment'],
3✔
479
                        $wrapLength,
3✔
480
                        $phpcsFile->eolChar.$padding
3✔
481
                    );
2✔
482

483
                    $phpcsFile->fixer->replaceToken($commentToken, $content);
3✔
484
                    for ($i = ($commentToken + 1); $i <= $param['comment_end']; $i++) {
3✔
485
                        $phpcsFile->fixer->replaceToken($i, '');
3✔
486
                    }
1✔
487
                }//end if
1✔
488
            }//end if
1✔
489

490
            // Check the alignment of multi-line param comments.
491
            if ($param['tag'] !== $param['comment_end']) {
3✔
492
                $wrapLength = ($tokens[($param['tag'] + 2)]['length'] - $param['type_space'] - $param['var_space'] - strlen($param['type']) - strlen($param['var']));
3✔
493

494
                $startColumn = ($tokens[($param['tag'] + 2)]['column'] + $tokens[($param['tag'] + 2)]['length'] - $wrapLength);
3✔
495

496
                $star     = $phpcsFile->findPrevious(T_DOC_COMMENT_STAR, $param['tag']);
3✔
497
                $expected = ($startColumn - $tokens[$star]['column'] - 1);
3✔
498

499
                foreach ($param['comment_tokens'] as $commentToken) {
3✔
500
                    if ($tokens[$commentToken]['column'] === $startColumn) {
3✔
501
                        continue;
3✔
502
                    }
503

504
                    $found = 0;
3✔
505
                    if ($tokens[($commentToken - 1)]['code'] === T_DOC_COMMENT_WHITESPACE) {
3✔
506
                        $found = $tokens[($commentToken - 1)]['length'];
3✔
507
                    }
1✔
508

509
                    $error = 'Parameter comment not aligned correctly; expected %s spaces but found %s';
3✔
510
                    $data  = [
1✔
511
                        $expected,
3✔
512
                        $found,
3✔
513
                    ];
2✔
514

515
                    if ($found < $expected) {
3✔
516
                        $code = 'ParamCommentAlignment';
3✔
517
                    } else {
1✔
518
                        $code = 'ParamCommentAlignmentExceeded';
3✔
519
                    }
520

521
                    $fix = $phpcsFile->addFixableError($error, $commentToken, $code, $data);
3✔
522
                    if ($fix === true) {
3✔
523
                        $padding = str_repeat(' ', $expected);
3✔
524
                        if ($tokens[($commentToken - 1)]['code'] === T_DOC_COMMENT_WHITESPACE) {
3✔
525
                            $phpcsFile->fixer->replaceToken(($commentToken - 1), $padding);
3✔
526
                        } else {
1✔
527
                            $phpcsFile->fixer->addContentBefore($commentToken, $padding);
×
528
                        }
529
                    }
1✔
530
                }//end foreach
1✔
531
            }//end if
1✔
532
        }//end foreach
1✔
533

534
        $realNames = [];
3✔
535
        foreach ($realParams as $realParam) {
3✔
536
            $realNames[] = $realParam['name'];
3✔
537
        }
1✔
538

539
        // Report missing comments.
540
        $diff = array_diff($realNames, $foundParams);
3✔
541
        foreach ($diff as $neededParam) {
3✔
542
            $error = 'Doc comment for parameter "%s" missing';
3✔
543
            $data  = [$neededParam];
3✔
544
            $phpcsFile->addError($error, $commentStart, 'MissingParamTag', $data);
3✔
545
        }
1✔
546

547
    }//end processParams()
2✔
548

549

550
}//end class
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc