Completed
Pull Request — master (#30)
by
unknown
13:33 queued 55s
created

SpaceAfterDeclareSniff::handleNoWhitespaceFound()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 9

Duplication

Lines 14
Ratio 100 %

Code Coverage

Tests 9
CRAP Score 2

Importance

Changes 0
Metric Value
dl 14
loc 14
ccs 9
cts 9
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 9
nc 2
nop 2
crap 2
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace BestIt\Sniffs\Formatting;
6
7
use PHP_CodeSniffer\Files\File;
8
use PHP_CodeSniffer\Sniffs\Sniff;
9
10
/**
11
 * Class SpaceAfterDeclareSniff
12
 *
13
 * @package BestIt\Sniffs\Formatting
14
 *
15
 * @author Nick Lubisch <[email protected]>
16
 */
17
class SpaceAfterDeclareSniff implements Sniff
18
{
19
    /**
20
     * Error message when no whitespace is found.
21
     *
22
     * @var string
23
     */
24
    const MESSAGE_NO_WHITESPACE_FOUND = 'There is no whitespace after declare-statement.';
25
26
    /**
27
     * Code when no whitespace is found.
28
     *
29
     * @var string
30
     */
31
    const CODE_NO_WHITESPACE_FOUND = 'NoWhitespaceFound';
32
33
    /**
34
     * Error message when more than one whitespaces are found.
35
     *
36
     * @var string
37
     */
38
    const MESSAGE_MUCH_WHITESPACE_FOUND = 'There are more than one whitespaces after declare-statement.';
39
40
    /**
41
     * Code when more than one whitespaces are found.
42
     *
43
     * @var string
44
     */
45
    const CODE_MUCH_WHITESPACE_FOUND = 'MuchWhitespaceFound';
46
47
    /**
48
     * Error message when blank lines in a group are found.
49
     *
50
     * @var string
51
     */
52 5
    const MESSAGE_GROUP_BLANK_LINE_FOUND = 'Multpile declare-statements should be grouped without a blank line.';
53
54
    /**
55 5
     * Code when whitespaces in a group are found.
56
     *
57
     * @var string
58
     */
59
    const CODE_GROUP_BLANK_LINE_FOUND = 'GroupBlankLineFound';
60
61
    /**
62
     * Registers the tokens that this sniff wants to listen for.
63
     *
64
     * @return int[] List of tokens to listen for
65
     */
66
    public function register(): array
67 4
    {
68
        return [
69 4
            T_DECLARE
70
        ];
71 4
    }
72
73 4
    /**
74 4
     * Called when one of the token types that this sniff is listening for is found.
75
     *
76 4
     * @param File $phpcsFile The PHP_CodeSniffer file where the token was found.
77 3
     * @param int $stackPtr The position in the PHP_CodeSniffer file's token stack where the token was found.
78
     *
79 3
     * @return void Optionally returns a stack pointer.
80
     */
81
    public function process(File $phpcsFile, $stackPtr)
82 4
    {
83
        $tokens = $phpcsFile->getTokens();
84 4
85 1
        $semicolonPtr = $phpcsFile->findEndOfStatement($stackPtr);
86
87
        $secondSpacePtr = $semicolonPtr + 2;
88 3
        $secondSpaceToken = $tokens[$secondSpacePtr];
89
90 3
        $nextDeclarePtr = $phpcsFile->findNext(T_DECLARE, $semicolonPtr, null, false);
91 1
92
        $whiteSpaceInGroupPtr = $phpcsFile->findNext(T_WHITESPACE, $secondSpacePtr, $nextDeclarePtr, false);
0 ignored issues
show
Security Bug introduced by
It seems like $nextDeclarePtr defined by $phpcsFile->findNext(T_D...icolonPtr, null, false) on line 90 can also be of type false; however, PHP_CodeSniffer\Files\File::findNext() does only seem to accept integer|null, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
93 1
94
95 3
        //Declare statement group detected
96
        if ($secondSpaceToken['code'] === T_DECLARE) {
97
            return;
98
        }
99
100
        //Declare statement group with blank lines detected
101
        if ($nextDeclarePtr && $whiteSpaceInGroupPtr) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $nextDeclarePtr of type integer|false is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
Bug Best Practice introduced by
The expression $whiteSpaceInGroupPtr of type integer|false is loosely compared to true; this is ambiguous if the integer can be zero. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
102
            $this->handleBlankLineInGroup($phpcsFile, $semicolonPtr, $whiteSpaceInGroupPtr, $nextDeclarePtr);
103
            return;
104
        }
105 3
106
        //Single declare statement with no following whitespace detected
107 3
        if ($secondSpaceToken['code'] !== T_WHITESPACE) {
108 3
            $this->handleNoWhitespaceFound($phpcsFile, $semicolonPtr);
109 3
110 3
            return;
111
        }
112
113 3
        $nextNonSpacePtr = $phpcsFile->findNext(T_WHITESPACE, $secondSpacePtr, null, true);
114 3
115 3
        if ($nextNonSpacePtr === false) {
116 3
            return;
117
        }
118 3
119
        $nextNonSpaceToken = $tokens[$nextNonSpacePtr];
120
121
        //Detect too many whitespaces after declare statement
122
        if (($nextNonSpaceToken['line'] - $secondSpaceToken['line']) > 1) {
123
            $this->handleMuchWhitespacesFound($phpcsFile, $semicolonPtr, $secondSpacePtr, $nextNonSpacePtr);
124
125
            return;
126
        }
127
    }
128
129
    /**
130 1
     * Handles when no whitespace is found.
131
     *
132
     * @param File $phpcsFile The php cs file
133
     * @param int $semicolonPtr Pointer to the semicolon token
134
     *
135
     * @return void
136 1
     */
137 1 View Code Duplication
    private function handleNoWhitespaceFound(File $phpcsFile, int $semicolonPtr)
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...
138 1
    {
139 1
        $fixNoWhitespace = $phpcsFile->addFixableError(
140
            self::MESSAGE_NO_WHITESPACE_FOUND,
141
            $semicolonPtr,
142 1
            self::CODE_NO_WHITESPACE_FOUND
143 1
        );
144 1
145 1
        if ($fixNoWhitespace) {
146
            $phpcsFile->fixer->beginChangeset();
147 1
            $phpcsFile->fixer->addNewline($semicolonPtr);
148
            $phpcsFile->fixer->endChangeset();
149 1
        }
150
    }
151
152
    /**
153
     * Handles when more than one whitespaces are found.
154
     *
155
     * @param File $phpcsFile The php cs file
156
     * @param int $semicolonPtr Pointer to the semicolon
157
     * @param int $secondSpacePtr Pointer to the second space
158
     * @param int $nextNonSpacePtr Pointer to the next non space token
159
     *
160
     * @return void
161
     */
162 View Code Duplication
    private function handleMuchWhitespacesFound(
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...
163
        File $phpcsFile,
164
        int $semicolonPtr,
165
        int $secondSpacePtr,
166
        int $nextNonSpacePtr
167
    ) {
168
        $fixMuchWhitespaces = $phpcsFile->addFixableError(
169
            self::MESSAGE_MUCH_WHITESPACE_FOUND,
170
            $semicolonPtr,
171
            self::CODE_MUCH_WHITESPACE_FOUND
172
        );
173
174
        if ($fixMuchWhitespaces) {
175
            $phpcsFile->fixer->beginChangeset();
176
            for ($i = $secondSpacePtr; $i < $nextNonSpacePtr; $i++) {
177
                $phpcsFile->fixer->replaceToken($i, '');
178
            }
179
            $phpcsFile->fixer->endChangeset();
180
        }
181
    }
182
183
    /**
184
     * Handles blank lines found in declare group.
185
     *
186
     * @param File $phpcsFile The php cs file
187
     * @param int $semicolonPtr Pointer to the semicolon
188
     * @param int $secondSpacePtr Pointer to the second space
189
     * @param int $nextNonSpacePtr Pointer to the next non space token
190
     *
191
     * @return void
192
     */
193 View Code Duplication
    private function handleBlankLineInGroup(
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...
194
        File $phpcsFile,
195
        int $semicolonPtr,
196
        int $secondSpacePtr,
197
        int $nextNonSpacePtr
198
    ) {
199
        $fixGroupBlankLines = $phpcsFile->addFixableError(
200
            self::MESSAGE_GROUP_BLANK_LINE_FOUND,
201
            $semicolonPtr,
202
            self::CODE_GROUP_BLANK_LINE_FOUND
203
        );
204
205
        if ($fixGroupBlankLines) {
206
            $phpcsFile->fixer->beginChangeset();
207
            for ($i = $secondSpacePtr; $i < $nextNonSpacePtr; $i++) {
208
                $phpcsFile->fixer->replaceToken($i, '');
209
            }
210
            $phpcsFile->fixer->endChangeset();
211
        }
212
    }
213
}
214