Completed
Pull Request — master (#13)
by Tim
01:53
created

MethodDocSniff::process()   F

Complexity

Conditions 20
Paths 363

Size

Total Lines 85
Code Lines 50

Duplication

Lines 27
Ratio 31.76 %

Code Coverage

Tests 49
CRAP Score 20.024

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 27
loc 85
ccs 49
cts 51
cp 0.9608
rs 3.6699
cc 20
eloc 50
nc 363
nop 2
crap 20.024

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
declare(strict_types=1);
4
5
6
namespace BestIt\Sniffs\Commenting;
7
8
use PHP_CodeSniffer_File;
9
use PHP_CodeSniffer_Sniff;
10
11
/**
12
 * This Sniff checks the method phpdoc
13
 *
14
 * It is a modified version of the Generic DocCommentSniff adjusted for the bestit codestyle
15
 *
16
 * @package BestIt\Sniffs\Commenting
17
 *
18
 * @author Nils Hardeweg <[email protected]>
19
 */
20
class MethodDocSniff implements PHP_CodeSniffer_Sniff
21
{
22
    #region constants
23
    /**
24
     * Code for an empty doc block
25
     *
26
     * @var string
27
     */
28
    const CODE_EMPTY = 'Empty';
29
30
    /**
31
     * Message for an empty doc block
32
     *
33
     * @var string
34
     */
35
    const MESSAGE_DOC_EMPTY = 'Doc comment is empty';
36
37
    /**
38
     * Code for a Spacing Error after the Summary
39
     *
40
     * @var string
41
     */
42
    const CODE_SPACING_AFTER = 'SpacingAfter';
43
44
    /**
45
     * Message for a Spacing Error after the Summary
46
     *
47
     * @var string
48
     */
49
    const MESSAGE_SPACING_AFTER = 'Additional blank lines found at end of doc comment';
50
51
    /**
52
     * Code for missing spacing between descriptions
53
     *
54
     * @var string
55
     */
56
    const CODE_SPACING_BETWEEN = 'SpacingBetween';
57
58
    /**
59
     * Message for missing spacing between descriptions
60
     *
61
     * @var string
62
     */
63
    const MESSAGE_SPACING_BETWEEN = 'There must be exactly one blank line between descriptions in a doc comment';
64
65
    /**
66
     * Code for missing spacing before the tags
67
     *
68
     * @var string
69
     */
70
    const CODE_SPACING_BEFORE_TAGS = 'SpacingBeforeTags';
71
72
    /**
73
     * Message for missing spacing before the tags
74
     *
75
     * @var string
76
     */
77
    const MESSAGE_SPACING_BEFORE_TAGS = 'There must be exactly one blank line before the tags in a doc comment';
78
79
    /**
80
     * Code for missing short description (Summary)
81
     *
82
     * @var string
83
     */
84
    const CODE_MISSING_SHORT = 'MissingShort';
85
86
    /**
87
     * Message for missing short description (Summary)
88
     *
89
     * @var string
90
     */
91
    const MESSAGE_MISSING_SHORT = 'Missing short description in doc comment';
92
93
    /**
94
     * Code for not capitalized short description
95
     *
96
     * @var string
97
     */
98
    const CODE_SHORT_NOT_CAPITAL = 'ShortNotCapital';
99
100
    /**
101
     * Message for not capitalized short description
102
     *
103
     * @var string
104
     */
105
    const MESSAGE_SHORT_NOT_CAPITAL = 'Doc comment short description must start with a capital letter';
106
107
    /**
108
     * Code for not Capitalized long description
109
     *
110
     * @var string
111
     */
112
    const CODE_LONG_NOT_CAPITAL = 'LongNotCapital';
113
114
    /**
115
     * Message for not Capitalized long description
116
     *
117
     * @var string
118
     */
119
    const MESSAGE_LONG_NOT_CAPITAL = 'Doc comment long description must start with a capital letter';
120
121
    /**
122
     * Code for empty lines before the short description
123
     *
124
     * @var string
125
     */
126
    const CODE_SPACING_BEFORE_SHORT = 'SpacingBeforeShort';
127
128
    /**
129
     * Message for empty lines before the short description
130
     *
131
     * @var string
132
     */
133
    const MESSAGE_CODE_SPACING_BEFORE = 'Doc comment short description must be on the first line';
134
    #endregion
135
136
    /**
137
     * A list of tokenizers this sniff supports.
138
     *
139
     * @var array
140
     */
141
    public $supportedTokenizers = ['PHP', 'JS'];
142
143
    /**
144
     * Returns an array of tokens this test wants to listen for.
145
     *
146
     * @return array
147
     */
148 8
    public function register()
149
    {
150 8
        return [T_DOC_COMMENT_OPEN_TAG];
151
    }
152
153
    /**
154
     * Processes this test, when one of its tokens is encountered.
155
     *
156
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
157
     * @param int $stackPtr The position of the current token in the stack passed in $tokens.
158
     *
159
     * @return void
160
     */
161 8
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
162
    {
163 8
        $tokens = $phpcsFile->getTokens();
164 8
        $commentStart = $stackPtr;
165 8
        $commentEnd = $tokens[$stackPtr]['comment_closer'];
166
167 8
        $empty = [T_DOC_COMMENT_WHITESPACE, T_DOC_COMMENT_STAR];
168
169 8
        $short = $phpcsFile->findNext($empty, $stackPtr + 1, $commentEnd, true);
170 8
        if ($short === false) {
171
            // No content at all.
172 1
            $error = self::MESSAGE_DOC_EMPTY;
173 1
            $phpcsFile->addError($error, $stackPtr, self::CODE_EMPTY);
174 1
            return;
175
        }
176
177
        // The last line of the comment should just be the */ code.
178 7
        $prev = $phpcsFile->findPrevious($empty, $commentEnd - 1, $stackPtr, true);
179
180
        // Check for additional blank lines at the end of the comment.
181 7 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...
182
            $error = self::MESSAGE_SPACING_AFTER;
183
            $phpcsFile->addError($error, $commentEnd, self::CODE_SPACING_AFTER);
184
        }
185
186
        // Check for a comment description.
187 7 View Code Duplication
        if ($tokens[$short]['code'] !== T_DOC_COMMENT_STRING
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...
188 7
            && $tokens[$short]['content'] !== '@inheritdoc'
189 7
            && $tokens[$short]['content'] !== '@var') {
190 1
            $error = self::MESSAGE_MISSING_SHORT;
191 1
            $phpcsFile->addError($error, $stackPtr, self::CODE_MISSING_SHORT);
192 1
            return;
193
        }
194
195
        // No extra newline before short description.
196 6 View Code Duplication
        if ($tokens[$short]['line'] !== ($tokens[$stackPtr]['line'] + 1) && $tokens[$short]['content'] !== '@var') {
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...
197 1
            $error = self::MESSAGE_CODE_SPACING_BEFORE;
198 1
            $phpcsFile->addError($error, $short, self::CODE_SPACING_BEFORE_SHORT);
199
        }
200
201 6
        $shortContent = $tokens[$short]['content'];
202
        /** @var int $shortEnd */
203 6
        $shortEnd = $short;
204
205 6
        if (preg_match('/^\p{Ll}/u', $shortContent) === 1) {
206 1
            $error = self::MESSAGE_SHORT_NOT_CAPITAL;
207 1
            $phpcsFile->addError($error, $short, self::CODE_SHORT_NOT_CAPITAL);
208
        }
209
210 6
        $long = $phpcsFile->findNext($empty, $shortEnd + 1, $commentEnd - 1, true);
211 6
        if ($long !== false && $tokens[$long]['code'] === T_DOC_COMMENT_STRING) {
212 2 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...
213 1
                $error = self::MESSAGE_LONG_NOT_CAPITAL;
214 1
                $phpcsFile->addError($error, $long, self::CODE_LONG_NOT_CAPITAL);
215
            }
216
        }
217
218 6
        $long = $phpcsFile->findNext($empty, $shortEnd + 1, $commentEnd - 1, true);
219 6
        if ($long !== false && $tokens[$long]['code'] === T_DOC_COMMENT_STRING) {
220 2 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...
221 1
                $error = self::MESSAGE_SPACING_BETWEEN;
222 1
                $phpcsFile->addError($error, $long, self::CODE_SPACING_BETWEEN);
223
            }
224
225 2 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...
226 1
                $error = self::MESSAGE_LONG_NOT_CAPITAL;
227 1
                $phpcsFile->addError($error, $long, self::CODE_LONG_NOT_CAPITAL);
228
            }
229
        }
230
231 6
        if (empty($tokens[$commentStart]['comment_tags'])) {
232
            // No tags in the comment.
233 1
            return;
234
        }
235
236 6
        $firstTag = $tokens[$commentStart]['comment_tags'][0];
237 6
        $prev = $phpcsFile->findPrevious($empty, $firstTag - 1, $stackPtr, true);
238 6
        if ($tokens[$firstTag]['line'] !== ($tokens[$prev]['line'] + 2)
239 6
            && $tokens[$short]['content'] !== '@inheritdoc'
240 6
            && $tokens[$short]['content'] !== '@var'
241
        ) {
242 1
            $error = self::MESSAGE_SPACING_BEFORE_TAGS;
243 1
            $phpcsFile->addError($error, $firstTag, self::CODE_SPACING_BEFORE_TAGS);
244
        }
245 6
    }
246
}
247