Completed
Pull Request — master (#57)
by
unknown
03:05
created

EmptyLinesDocSniff   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 110
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 9
lcom 1
cbo 4
dl 0
loc 110
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A processToken() 0 4 1
A register() 0 4 1
B searchEmptyLines() 0 53 7
1
<?php
2
3
declare(strict_types=1);
4
5
namespace BestIt\Sniffs\Commenting;
6
7
use BestIt\CodeSniffer\Helper\LineHelper;
8
use BestIt\Sniffs\AbstractSniff;
9
use PHP_CodeSniffer\Files\File;
10
11
/**
12
 * Class EmptyLinesDocSniff.
13
 *
14
 * @author Mika Bertels <[email protected]>
15
 * @package BestIt\Sniffs\Commenting
16
 */
17
class EmptyLinesDocSniff extends AbstractSniff
18
{
19
    /**
20
     * Code when an empty line is detected.
21
     *
22
     * @var string CODE_EMPTY_LINES_FOUND
23
     */
24
    public const CODE_EMPTY_LINES_FOUND = 'EmptyLinesFound';
25
26
    /**
27
     * Error message when empty line is detected.
28
     *
29
     * @var string ERROR_EMPTY_LINES_FOUND
30
     */
31
    private const ERROR_EMPTY_LINES_FOUND = 'There are too many empty lines in your doc-block!';
32
33
    /**
34
     * Process token within scope.
35
     *
36
     * @return void
37
     */
38
    protected function processToken(): void
39
    {
40
        $this->searchEmptyLines($this->file, $this->stackPos);
0 ignored issues
show
Bug introduced by
It seems like $this->file can be null; however, searchEmptyLines() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
41
    }
42
43
    /**
44
     * Registers the tokens that this sniff wants to listen for.
45
     *
46
     * An example return value for a sniff that wants to listen for whitespace
47
     * and any comments would be:
48
     *
49
     * <code>
50
     *    return array(
51
     *            T_WHITESPACE,
52
     *            T_DOC_COMMENT,
53
     *            T_COMMENT,
54
     *           );
55
     * </code>
56
     *
57
     * @return int[]
58
     * @see    Tokens.php
59
     */
60
    public function register(): array
61
    {
62
        return [T_DOC_COMMENT_OPEN_TAG];
63
    }
64
65
    /**
66
     * Process method for tokens within scope and also outside scope.
67
     *
68
     * @param File $phpcsFile The sniffed file.
69
     * @param int $searchPosition
70
     *
71
     * @return void
72
     */
73
    private function searchEmptyLines(File $phpcsFile, int $searchPosition): void
74
    {
75
        $endOfDoc = $phpcsFile->findEndOfStatement($searchPosition);
76
77
        do {
78
            $currentToken = $phpcsFile->getTokens()[$searchPosition];
79
            $nextTokenPosition = (int) $phpcsFile->findNext(
80
                [T_DOC_COMMENT_WHITESPACE, T_DOC_COMMENT_STAR],
81
                $searchPosition + 1,
82
                $endOfDoc,
83
                true
84
            );
85
86
            if ($hasToken = ($nextTokenPosition > 0)) {
87
                $nextToken = $phpcsFile->getTokens()[$nextTokenPosition];
88
                $hasTooManyLines = ($nextToken['line'] - $currentToken['line']) > 2;
89
90
                if ($hasTooManyLines) {
91
                    $isFixing = $phpcsFile->addFixableError(
92
                        self::ERROR_EMPTY_LINES_FOUND,
93
                        $nextTokenPosition,
94
                        self::CODE_EMPTY_LINES_FOUND
95
                    );
96
97
                    if ($isFixing) {
98
                        $movement = 2;
99
100
                        if ($nextToken['type'] === 'T_DOC_COMMENT_CLOSE_TAG') {
101
                            $movement = 1;
102
                        }
103
104
                        $phpcsFile->fixer->beginChangeset();
105
106
                        (new LineHelper($this->file))->removeLines(
0 ignored issues
show
Bug introduced by
It seems like $this->file can be null; however, __construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
107
                            $currentToken['line'] + $movement,
108
                            $nextToken['line'] - 1
109
                        );
110
111
                        $phpcsFile->fixer->endChangeset();
112
                    }
113
                }
114
115
                $phpcsFile->recordMetric(
116
                    $searchPosition,
117
                    'DocBlock has too many lines',
118
                    $hasTooManyLines ? 'yes' : 'no'
119
                );
120
121
                $searchPosition = $nextTokenPosition;
122
123
            }
124
        } while ($hasToken);
125
    }
126
}
127