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

MethodDocSniff   A

Complexity

Total Complexity 21

Size/Duplication

Total Lines 227
Duplicated Lines 11.89 %

Coupling/Cohesion

Components 0
Dependencies 1

Test Coverage

Coverage 96.23%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 21
c 1
b 0
f 0
lcom 0
cbo 1
dl 27
loc 227
ccs 51
cts 53
cp 0.9623
rs 10

2 Methods

Rating   Name   Duplication   Size   Complexity  
A register() 0 4 1
F process() 27 85 20

How to fix   Duplicated Code   

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:

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