Completed
Pull Request — master (#19)
by
unknown
08:16
created

GeneralDocSniff::checkEmptyLineBeforeComment()   C

Complexity

Conditions 10
Paths 30

Size

Total Lines 51
Code Lines 28

Duplication

Lines 29
Ratio 56.86 %

Code Coverage

Tests 27
CRAP Score 10

Importance

Changes 0
Metric Value
dl 29
loc 51
ccs 27
cts 27
cp 1
rs 6
c 0
b 0
f 0
cc 10
eloc 28
nc 30
nop 0
crap 10

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
namespace BestIt\Sniffs\Commenting;
4
5
use PHP_CodeSniffer_File;
6
use PHP_CodeSniffer_Sniff;
7
8
/**
9
 * Class GeneralDocSniff
10
 *
11
 * @package BestIt\Sniffs\Commenting
12
 * @author Nick Lubisch <[email protected]>
13
 */
14
class GeneralDocSniff implements PHP_CodeSniffer_Sniff
15
{
16
    /**
17
     * Code that there is no line before the comment.
18
     *
19
     * @var string
20
     */
21
    const CODE_NO_LINE_BEFORE_COMMENT = 'NoLineBeforeComment';
22
23
    /**
24
     * Message that there is no line before the comment.
25
     *
26
     * @var string
27
     */
28
    const MESSAGE_NO_LINE_BEFORE_COMMENT = 'There is no line before the comment.';
29
30
    /**
31
     * Code that are too much lines before comment.
32
     *
33
     * @var string
34
     */
35
    const CODE_MUCH_LINES_BEFORE_COMMENT = 'MuchLinesBeforeComment';
36
37
    /**
38
     * Message that are too much lines before comment.
39
     *
40
     * @var string
41
     */
42
    const MESSAGE_MUCH_LINES_BEFORE_COMMENT = 'There are more than one lines before the comment.';
43
44
    /**
45
     * Code that are too much spaces between comment tag fragments.
46
     *
47
     * @var string
48
     */
49
    const CODE_WRONG_COMMENT_TAG_SPACING = 'WrongCommentTagSpacing';
50
    
51
    /**
52
     * Message that are too much spaces between comment tag fragments.
53
     *
54
     * @var string
55
     */
56
    const MESSAGE_WRONG_COMMENT_TAG_SPACING = 'There must only be 1 space between comment tag fragments.';
57
58
    /**
59
     * The PHP_CodeSniffer file where the token was found.
60
     *
61
     * @var PHP_CodeSniffer_File CodeSniffer file.
62
     */
63
    private $phpcsFile;
64
65
    /**
66
     * The cs file token stack.
67
     *
68
     * @var array
69
     */
70
    private $tokens;
71
72
    /**
73
     * Pointer of the comment start token.
74
     *
75
     * @var int
76
     */
77
    private $commentStartPtr;
78
79
    /**
80
     * Token of the comment start
81
     *
82
     * @var array
83
     */
84
    private $commentStartToken;
85
86
    /**
87
     * Registers the tokens that this sniff wants to listen for.
88
     *
89
     * @return int[] List of tokens to listen for
90
     */
91 4
    public function register()
92
    {
93
        return [
94 4
            T_DOC_COMMENT_OPEN_TAG
95
        ];
96
    }
97
98
    /**
99
     * Called when one of the token types that this sniff is listening for is found.
100
     *
101
     * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where the token was found.
102
     * @param int $commentStartPtr The position in the PHP_CodeSniffer file's token stack where the token was found.
103
     *
104
     * @return void|int Optionally returns a stack pointer.
105
     */
106 4
    public function process(PHP_CodeSniffer_File $phpcsFile, $commentStartPtr)
107
    {
108 4
        $this->phpcsFile = $phpcsFile;
109 4
        $this->tokens = $phpcsFile->getTokens();
110 4
        $this->commentStartPtr = $commentStartPtr;
111 4
        $this->commentStartToken = $this->tokens[$commentStartPtr];
112
113 4
        $this->checkEmptyLineBeforeComment();
114 4
        $this->checkCommentTagsSpacing();
115 4
    }
116
117
    /**
118
     * Checks if an empty line is before the comment.
119
     *
120
     * @return void
121
     */
122 4
    private function checkEmptyLineBeforeComment()
123
    {
124 4
        $prevNonSpacePtr = $this->phpcsFile->findPrevious(T_WHITESPACE, $this->commentStartPtr - 1, null, true);
125 4
        $prevNonSpaceToken = $this->tokens[$prevNonSpacePtr];
126
127 4
        $hasPrevCurlyBrace = $prevNonSpaceToken['type'] === 'T_OPEN_CURLY_BRACKET';
128
129 4
        $whitespacePtrs = [];
130 4
        for ($i = $prevNonSpacePtr + 1; $i < $this->commentStartPtr; $i++) {
131 4
            $whitespaceToken = $this->tokens[$i];
132
133 4
            if ($whitespaceToken['column'] === 1 && $this->commentStartToken['line'] !== $whitespaceToken['line']) {
134 4
                $whitespacePtrs[] = $i;
135
            }
136
        }
137
138 4
        $expectedLines = $hasPrevCurlyBrace ? 0 : 1;
139
140
        //More than one line before comment
141 4 View Code Duplication
        if (count($whitespacePtrs) > $expectedLines) {
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...
142 1
            $fixMuchLines = $this->phpcsFile->addFixableError(
143 1
                self::MESSAGE_MUCH_LINES_BEFORE_COMMENT,
144 1
                $this->commentStartPtr,
145 1
                self::CODE_MUCH_LINES_BEFORE_COMMENT
146
            );
147
148 1
            if ($fixMuchLines) {
149 1
                $this->fixMuchLinesBeforeComment(
150
                    $whitespacePtrs,
151
                    $hasPrevCurlyBrace
152
                );
153
            }
154
155 1
            return;
156
        }
157
158
        //No line before comment
159 4 View Code Duplication
        if (!$hasPrevCurlyBrace && count($whitespacePtrs) === 0) {
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...
160 1
            $fixNoLine = $this->phpcsFile->addFixableError(
161 1
                self::MESSAGE_NO_LINE_BEFORE_COMMENT,
162 1
                $this->commentStartPtr,
163 1
                self::CODE_NO_LINE_BEFORE_COMMENT
164
            );
165
166 1
            if ($fixNoLine) {
167 1
                $this->fixNoLineBeforeComment();
168
            }
169
170 1
            return;
171
        }
172 4
    }
173
174
    /**
175
     * Check if there is a comment tag alignment.
176
     *
177
     * @return void
178
     */
179 4
    private function checkCommentTagsSpacing()
180
    {
181 4
        $commentTagPtrs = $this->commentStartToken['comment_tags'];
182
183 4
        if (count($commentTagPtrs) === 0) {
184 3
            return;
185
        }
186
187
        /**
188
         * Array of comment tag pointers.
189
         *
190
         * @var int[] $commentTagPtrs
191
         */
192 4
        foreach ($commentTagPtrs as $commentTagPtr) {
193 4
            $this->checkCommentTagSpacing($commentTagPtr);
194
        }
195 4
    }
196
197
    /**
198
     * Checks a single comment tag alignment.
199
     *
200
     * @param int $commentTagPtr Pointer to comment tag.
201
     *
202
     * @return void
203
     */
204 4
    private function checkCommentTagSpacing($commentTagPtr)
205
    {
206 4
        $lineEndingPtr = $this->phpcsFile->findNext(
207 4
            T_DOC_COMMENT_WHITESPACE,
208
            $commentTagPtr,
209 4
            null,
210 4
            false,
211 4
            $this->phpcsFile->eolChar
212
        );
213
214 4
        for ($tagFragmentPtr = $commentTagPtr; $tagFragmentPtr < $lineEndingPtr; $tagFragmentPtr++) {
215 4
            $tagFragmentToken = $this->tokens[$tagFragmentPtr];
216
217 4
            if ($tagFragmentToken['type'] === 'T_DOC_COMMENT_STRING') {
218 4
                $this->checkCommentTagStringSpacing($tagFragmentPtr);
219
            }
220
221 4
            if ($tagFragmentToken['type'] === 'T_DOC_COMMENT_WHITESPACE' && $tagFragmentToken['length'] > 1) {
222 1
                $this->checkCommentTagWhiteSpacing($tagFragmentPtr);
223
            }
224
        }
225 4
    }
226
227
    /**
228
     * Checks comment tag strings spacing.
229
     *
230
     * @param int $tagStringPtr Pointer to the beginning of a tag
231
     *
232
     * @return void
233
     */
234 4 View Code Duplication
    private function checkCommentTagStringSpacing($tagStringPtr)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
235
    {
236 4
        $tagStringToken = $this->tokens[$tagStringPtr];
237
238 4
        $tagStringContent = $tagStringToken['content'];
239
240 4
        if (preg_replace('/\s\s+/', ' ', $tagStringContent) !== $tagStringContent) {
241 1
            $fixStringAlignment = $this->phpcsFile->addFixableError(
242 1
                self::MESSAGE_WRONG_COMMENT_TAG_SPACING,
243
                $tagStringPtr,
244 1
                self::CODE_WRONG_COMMENT_TAG_SPACING
245
            );
246
247 1
            if ($fixStringAlignment) {
248 1
                $this->fixCommentTagStringSpacing($tagStringPtr);
249
            }
250
        }
251 4
    }
252
253
    /**
254
     * Fixes comment tag string spacing.
255
     *
256
     * @param int $tagStringPtr Pointer to the beginning of a tag
257
     *
258
     * @return void
259
     */
260 1
    private function fixCommentTagStringSpacing($tagStringPtr)
261
    {
262 1
        $tagStringToken = $this->tokens[$tagStringPtr];
263 1
        $tagStringContent = $tagStringToken['content'];
264
265 1
        $this->phpcsFile->fixer->replaceToken(
266
            $tagStringPtr,
267 1
            preg_replace('/\s\s+/', ' ', $tagStringContent)
268
        );
269 1
    }
270
271
    /**
272
     * Fixes too long comment tag whitespaces.
273
     *
274
     * @param int $whitespacePtr Pointer to whitespace which is too long.
275
     *
276
     * @return void
277
     */
278 1
    private function fixCommentTagSpacing($whitespacePtr)
279
    {
280 1
        $this->phpcsFile->fixer->replaceToken($whitespacePtr, ' ');
281 1
    }
282
283
    /**
284
     * Fixes lines before comment.
285
     *
286
     * @param int[] $whitespacePtrs Pointers of all whitespaces before comment.
287
     * @param bool $noWhitespace Indicator which controls if there should be minimum one whitespace or not.
288
     *
289
     * @return void
290
     */
291 1
    private function fixMuchLinesBeforeComment(array $whitespacePtrs, $noWhitespace = false)
292
    {
293 1
        $this->phpcsFile->fixer->beginChangeset();
294
295 1
        foreach ($whitespacePtrs as $whitespaceIndex => $whitespacePtr) {
296 1
            if ($whitespaceIndex === 0 && !$noWhitespace) {
297 1
                continue;
298
            }
299
300 1
            $this->phpcsFile->fixer->replaceToken($whitespacePtr, '');
301
        }
302
303 1
        $this->phpcsFile->fixer->endChangeset();
304 1
    }
305
306
    /**
307
     * Fixes no line before comment.
308
     *
309
     * @return void
310
     */
311 1
    private function fixNoLineBeforeComment()
312
    {
313 1
        $this->phpcsFile->fixer->beginChangeset();
314
315 1
        if ($this->commentStartToken['column'] === 1) {
316 1
            $this->phpcsFile->fixer->addNewlineBefore($this->commentStartPtr);
317
        } else {
318 1
            $this->phpcsFile->fixer->addNewlineBefore($this->commentStartPtr - 1);
319
        }
320
321 1
        $this->phpcsFile->fixer->endChangeset();
322 1
    }
323
324
    /**
325
     * Checks given whitespace for proper spacing.
326
     *
327
     * @param int $whitespacePtr Pointer to whitespace to check.
328
     *
329
     * @return void
330
     */
331 1
    private function checkCommentTagWhiteSpacing($whitespacePtr)
332
    {
333 1
        $fixWrongWhitespace = $this->phpcsFile->addFixableError(
334 1
            self::MESSAGE_WRONG_COMMENT_TAG_SPACING,
335
            $whitespacePtr,
336 1
            self::CODE_WRONG_COMMENT_TAG_SPACING
337
        );
338
339 1
        if ($fixWrongWhitespace) {
340 1
            $this->fixCommentTagSpacing($whitespacePtr);
341
        }
342 1
    }
343
}
344