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

Generic_Sniffs_Commenting_DocCommentSniff   F

Complexity

Total Complexity 63

Size/Duplication

Total Lines 325
Duplicated Lines 35.38 %

Coupling/Cohesion

Components 0
Dependencies 2

Importance

Changes 0
Metric Value
dl 115
loc 325
rs 3.6585
c 0
b 0
f 0
wmc 63
lcom 0
cbo 2

2 Methods

Rating   Name   Duplication   Size   Complexity  
A register() 0 5 1
F process() 115 287 62

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 Generic_Sniffs_Commenting_DocCommentSniff 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 Generic_Sniffs_Commenting_DocCommentSniff, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Ensures doc blocks follow basic formatting.
4
 *
5
 * PHP version 5
6
 *
7
 * @category  PHP
8
 * @package   PHP_CodeSniffer
9
 * @author    Greg Sherwood <[email protected]>
10
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
11
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
12
 * @link      http://pear.php.net/package/PHP_CodeSniffer
13
 */
14
15
/**
16
 * Ensures doc blocks follow basic formatting.
17
 *
18
 * @category  PHP
19
 * @package   PHP_CodeSniffer
20
 * @author    Greg Sherwood <[email protected]>
21
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
22
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
23
 * @version   Release: @package_version@
24
 * @link      http://pear.php.net/package/PHP_CodeSniffer
25
 */
26
class Generic_Sniffs_Commenting_DocCommentSniff implements PHP_CodeSniffer_Sniff
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...
27
{
28
29
    /**
30
     * A list of tokenizers this sniff supports.
31
     *
32
     * @var array
33
     */
34
    public $supportedTokenizers = array(
35
                                   'PHP',
36
                                   'JS',
37
                                  );
38
39
40
    /**
41
     * Returns an array of tokens this test wants to listen for.
42
     *
43
     * @return array
44
     */
45
    public function register()
46
    {
47
        return array(T_DOC_COMMENT_OPEN_TAG);
48
49
    }//end register()
50
51
52
    /**
53
     * Processes this test, when one of its tokens is encountered.
54
     *
55
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
56
     * @param int                  $stackPtr  The position of the current token
57
     *                                        in the stack passed in $tokens.
58
     *
59
     * @return void
60
     */
61
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
62
    {
63
        $tokens       = $phpcsFile->getTokens();
64
        $commentStart = $stackPtr;
65
        $commentEnd   = $tokens[$stackPtr]['comment_closer'];
66
67
        $empty = array(
68
                  T_DOC_COMMENT_WHITESPACE,
69
                  T_DOC_COMMENT_STAR,
70
                 );
71
72
        $short = $phpcsFile->findNext($empty, ($stackPtr + 1), $commentEnd, true);
73
        if ($short === false) {
74
            // No content at all.
75
            $error = 'Doc comment is empty';
76
            $phpcsFile->addError($error, $stackPtr, 'Empty');
77
            return;
78
        }
79
80
        // The first line of the comment should just be the /** code.
81 View Code Duplication
        if ($tokens[$short]['line'] === $tokens[$stackPtr]['line']) {
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...
82
            $error = 'The open comment tag must be the only content on the line';
83
            $fix   = $phpcsFile->addFixableError($error, $stackPtr, 'ContentAfterOpen');
84
            if ($fix === true) {
85
                $phpcsFile->fixer->beginChangeset();
86
                $phpcsFile->fixer->addNewline($stackPtr);
87
                $phpcsFile->fixer->addContentBefore($short, '* ');
88
                $phpcsFile->fixer->endChangeset();
89
            }
90
        }
91
92
        // The last line of the comment should just be the */ code.
93
        $prev = $phpcsFile->findPrevious($empty, ($commentEnd - 1), $stackPtr, true);
94
        if ($tokens[$prev]['line'] === $tokens[$commentEnd]['line']) {
95
            $error = 'The close comment tag must be the only content on the line';
96
            $fix   = $phpcsFile->addFixableError($error, $commentEnd, 'ContentBeforeClose');
97
            if ($fix === true) {
98
                $phpcsFile->fixer->addNewlineBefore($commentEnd);
99
            }
100
        }
101
102
        // Check for additional blank lines at the end of the comment.
103 View Code Duplication
        if ($tokens[$prev]['line'] < ($tokens[$commentEnd]['line'] - 1)) {
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...
104
            $error = 'Additional blank lines found at end of doc comment';
105
            $fix   = $phpcsFile->addFixableError($error, $commentEnd, 'SpacingAfter');
106
            if ($fix === true) {
107
                $phpcsFile->fixer->beginChangeset();
108
                for ($i = ($prev + 1); $i < $commentEnd; $i++) {
109
                    if ($tokens[($i + 1)]['line'] === $tokens[$commentEnd]['line']) {
110
                        break;
111
                    }
112
113
                    $phpcsFile->fixer->replaceToken($i, '');
114
                }
115
116
                $phpcsFile->fixer->endChangeset();
117
            }
118
        }
119
120
        // Check for a comment description.
121
        if ($tokens[$short]['code'] !== T_DOC_COMMENT_STRING) {
122
            $error = 'Missing short description in doc comment';
123
            $phpcsFile->addError($error, $stackPtr, 'MissingShort');
124
            return;
125
        }
126
127
        // No extra newline before short description.
128 View Code Duplication
        if ($tokens[$short]['line'] !== ($tokens[$stackPtr]['line'] + 1)) {
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...
129
            $error = 'Doc comment short description must be on the first line';
130
            $fix   = $phpcsFile->addFixableError($error, $short, 'SpacingBeforeShort');
131
            if ($fix === true) {
132
                $phpcsFile->fixer->beginChangeset();
133
                for ($i = $stackPtr; $i < $short; $i++) {
134
                    if ($tokens[$i]['line'] === $tokens[$stackPtr]['line']) {
135
                        continue;
136
                    } else if ($tokens[$i]['line'] === $tokens[$short]['line']) {
137
                        break;
138
                    }
139
140
                    $phpcsFile->fixer->replaceToken($i, '');
141
                }
142
143
                $phpcsFile->fixer->endChangeset();
144
            }
145
        }
146
147
        // Account for the fact that a short description might cover
148
        // multiple lines.
149
        $shortContent = $tokens[$short]['content'];
150
        $shortEnd     = $short;
151 View Code Duplication
        for ($i = ($short + 1); $i < $commentEnd; $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...
152
            if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) {
153
                if ($tokens[$i]['line'] === ($tokens[$shortEnd]['line'] + 1)) {
154
                    $shortContent .= $tokens[$i]['content'];
155
                    $shortEnd      = $i;
156
                } else {
157
                    break;
158
                }
159
            }
160
        }
161
162
        if (preg_match('/^\p{Ll}/u', $shortContent) === 1) {
163
            $error = 'Doc comment short description must start with a capital letter';
164
            $phpcsFile->addError($error, $short, 'ShortNotCapital');
165
        }
166
167
        $long = $phpcsFile->findNext($empty, ($shortEnd + 1), ($commentEnd - 1), true);
168
        if ($long !== false && $tokens[$long]['code'] === T_DOC_COMMENT_STRING) {
169 View Code Duplication
            if ($tokens[$long]['line'] !== ($tokens[$shortEnd]['line'] + 2)) {
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...
170
                $error = 'There must be exactly one blank line between descriptions in a doc comment';
171
                $fix   = $phpcsFile->addFixableError($error, $long, 'SpacingBetween');
172
                if ($fix === true) {
173
                    $phpcsFile->fixer->beginChangeset();
174
                    for ($i = ($shortEnd + 1); $i < $long; $i++) {
175
                        if ($tokens[$i]['line'] === $tokens[$shortEnd]['line']) {
176
                            continue;
177
                        } else if ($tokens[$i]['line'] === ($tokens[$long]['line'] - 1)) {
178
                            break;
179
                        }
180
181
                        $phpcsFile->fixer->replaceToken($i, '');
182
                    }
183
184
                    $phpcsFile->fixer->endChangeset();
185
                }
186
            }
187
188 View Code Duplication
            if (preg_match('/^\p{Ll}/u', $tokens[$long]['content']) === 1) {
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...
189
                $error = 'Doc comment long description must start with a capital letter';
190
                $phpcsFile->addError($error, $long, 'LongNotCapital');
191
            }
192
        }//end if
193
194
        if (empty($tokens[$commentStart]['comment_tags']) === true) {
195
            // No tags in the comment.
196
            return;
197
        }
198
199
        $firstTag = $tokens[$commentStart]['comment_tags'][0];
200
        $prev     = $phpcsFile->findPrevious($empty, ($firstTag - 1), $stackPtr, true);
201 View Code Duplication
        if ($tokens[$firstTag]['line'] !== ($tokens[$prev]['line'] + 2)) {
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...
202
            $error = 'There must be exactly one blank line before the tags in a doc comment';
203
            $fix   = $phpcsFile->addFixableError($error, $firstTag, 'SpacingBeforeTags');
204
            if ($fix === true) {
205
                $phpcsFile->fixer->beginChangeset();
206
                for ($i = ($prev + 1); $i < $firstTag; $i++) {
207
                    if ($tokens[$i]['line'] === $tokens[$firstTag]['line']) {
208
                        break;
209
                    }
210
211
                    $phpcsFile->fixer->replaceToken($i, '');
212
                }
213
214
                $indent = str_repeat(' ', $tokens[$stackPtr]['column']);
215
                $phpcsFile->fixer->addContent($prev, $phpcsFile->eolChar.$indent.'*'.$phpcsFile->eolChar);
216
                $phpcsFile->fixer->endChangeset();
217
            }
218
        }
219
220
        // Break out the tags into groups and check alignment within each.
221
        // A tag group is one where there are no blank lines between tags.
222
        // The param tag group is special as it requires all @param tags to be inside.
223
        $tagGroups    = array();
224
        $groupid      = 0;
225
        $paramGroupid = null;
226
        foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) {
227
            if ($pos > 0) {
228
                $prev = $phpcsFile->findPrevious(
229
                    T_DOC_COMMENT_STRING,
230
                    ($tag - 1),
231
                    $tokens[$commentStart]['comment_tags'][($pos - 1)]
232
                );
233
234
                if ($prev === false) {
235
                    $prev = $tokens[$commentStart]['comment_tags'][($pos - 1)];
236
                }
237
238
                if ($tokens[$prev]['line'] !== ($tokens[$tag]['line'] - 1)) {
239
                    $groupid++;
240
                }
241
            }
242
243
            if ($tokens[$tag]['content'] === '@param') {
244
                if (($paramGroupid === null
245
                    && empty($tagGroups[$groupid]) === false)
246
                    || ($paramGroupid !== null
247
                    && $paramGroupid !== $groupid)
248
                ) {
249
                    $error = 'Parameter tags must be grouped together in a doc comment';
250
                    $phpcsFile->addError($error, $tag, 'ParamGroup');
251
                }
252
253
                if ($paramGroupid === null) {
254
                    $paramGroupid = $groupid;
255
                }
256
            } else if ($groupid === $paramGroupid) {
257
                $error = 'Tag cannot be grouped with parameter tags in a doc comment';
258
                $phpcsFile->addError($error, $tag, 'NonParamGroup');
259
            }//end if
260
261
            $tagGroups[$groupid][] = $tag;
262
        }//end foreach
263
264
        foreach ($tagGroups as $group) {
265
            $maxLength = 0;
266
            $paddings  = array();
267
            foreach ($group as $pos => $tag) {
268
                $tagLength = strlen($tokens[$tag]['content']);
269
                if ($tagLength > $maxLength) {
270
                    $maxLength = $tagLength;
271
                }
272
273
                // Check for a value. No value means no padding needed.
274
                $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd);
275 View Code Duplication
                if ($string !== false && $tokens[$string]['line'] === $tokens[$tag]['line']) {
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
                    $paddings[$tag] = strlen($tokens[($tag + 1)]['content']);
277
                }
278
            }
279
280
            // Check that there was single blank line after the tag block
281
            // but account for a multi-line tag comments.
282
            $lastTag = $group[$pos];
0 ignored issues
show
Bug introduced by
The variable $pos does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
283
            $next    = $phpcsFile->findNext(T_DOC_COMMENT_TAG, ($lastTag + 3), $commentEnd);
284
            if ($next !== false) {
285
                $prev = $phpcsFile->findPrevious(array(T_DOC_COMMENT_TAG, T_DOC_COMMENT_STRING), ($next - 1), $commentStart);
286 View Code Duplication
                if ($tokens[$next]['line'] !== ($tokens[$prev]['line'] + 2)) {
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...
287
                    $error = 'There must be a single blank line after a tag group';
288
                    $fix   = $phpcsFile->addFixableError($error, $lastTag, 'SpacingAfterTagGroup');
289
                    if ($fix === true) {
290
                        $phpcsFile->fixer->beginChangeset();
291
                        for ($i = ($prev + 1); $i < $next; $i++) {
292
                            if ($tokens[$i]['line'] === $tokens[$next]['line']) {
293
                                break;
294
                            }
295
296
                            $phpcsFile->fixer->replaceToken($i, '');
297
                        }
298
299
                        $indent = str_repeat(' ', $tokens[$stackPtr]['column']);
300
                        $phpcsFile->fixer->addContent($prev, $phpcsFile->eolChar.$indent.'*'.$phpcsFile->eolChar);
301
                        $phpcsFile->fixer->endChangeset();
302
                    }
303
                }
304
            }//end if
305
306
            // Now check paddings.
307
            foreach ($paddings as $tag => $padding) {
308
                $required = ($maxLength - strlen($tokens[$tag]['content']) + 1);
309
310
                if ($padding !== $required) {
311
                    $error = 'Tag value indented incorrectly; expected %s spaces but found %s';
312
                    $data  = array(
313
                              $required,
314
                              $padding,
315
                             );
316
317
                    $fix = $phpcsFile->addFixableError($error, ($tag + 1), 'TagValueIndent', $data);
318
                    if ($fix === true) {
319
                        $phpcsFile->fixer->replaceToken(($tag + 1), str_repeat(' ', $required));
320
                    }
321
                }
322
            }
323
        }//end foreach
324
325
        // If there is a param group, it needs to be first.
326
        if ($paramGroupid !== null && $paramGroupid !== 0) {
327
            $error = 'Parameter tags must be defined first in a doc comment';
328
            $phpcsFile->addError($error, $tagGroups[$paramGroupid][0], 'ParamNotFirst');
329
        }
330
331
        $foundTags = array();
332
        foreach ($tokens[$stackPtr]['comment_tags'] as $pos => $tag) {
333
            $tagName = $tokens[$tag]['content'];
334
            if (isset($foundTags[$tagName]) === true) {
335
                $lastTag = $tokens[$stackPtr]['comment_tags'][($pos - 1)];
336
                if ($tokens[$lastTag]['content'] !== $tagName) {
337
                    $error = 'Tags must be grouped together in a doc comment';
338
                    $phpcsFile->addError($error, $tag, 'TagsNotGrouped');
339
                }
340
341
                continue;
342
            }
343
344
            $foundTags[$tagName] = true;
345
        }
346
347
    }//end process()
348
349
350
}//end class
351