MultipleEmptyLinesSniff   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 80
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 30
c 1
b 0
f 0
dl 0
loc 80
rs 10
wmc 12

2 Methods

Rating   Name   Duplication   Size   Complexity  
A register() 0 8 1
B process() 0 52 11
1
<?php
2
3
/**
4
 *
5
 * Check multiple consecutive newlines in a file.
6
 * Source: MediaWiki. I didn't want to add dependency to whole package (because of only one sniff).
7
 *
8
 * @link https://github.com/wikimedia/mediawiki-tools-codesniffer/blob/272835d/MediaWiki/Sniffs/WhiteSpace/MultipleEmptyLinesSniff.php
9
 */
10
11
namespace MO4\Sniffs\WhiteSpace;
12
13
use PHP_CodeSniffer\Files\File;
14
use PHP_CodeSniffer\Sniffs\Sniff;
15
16
class MultipleEmptyLinesSniff implements Sniff
17
{
18
    /**
19
     * Registers the tokens that this sniff wants to listen for.
20
     *
21
     * @return array<int, int>
22
     *
23
     * @see Tokens.php
24
     */
25
    public function register(): array
26
    {
27
        return [
28
            // Assume most comments end with a newline
29
            T_COMMENT,
30
            // Assume all <?php open tags end with a newline
31
            T_OPEN_TAG,
32
            T_WHITESPACE,
33
        ];
34
    }
35
36
    /**
37
     * @phpcsSuppress SlevomatCodingStandard.TypeHints.ParameterTypeHint
38
     *
39
     * @param File $phpcsFile
40
     * @param int  $stackPtr  The current token index.
41
     *
42
     * @return void|int
43
     */
44
    public function process(File $phpcsFile, $stackPtr)
45
    {
46
        $tokens = $phpcsFile->getTokens();
47
48
        // This sniff intentionally doesn't care about whitespace at the end of the file
49
        if (!isset($tokens[$stackPtr + 3])
50
            || $tokens[$stackPtr + 2]['line'] === $tokens[$stackPtr + 3]['line']
51
        ) {
52
            return $stackPtr + 3;
53
        }
54
55
        if ($tokens[$stackPtr + 1]['line'] === $tokens[$stackPtr + 2]['line']) {
56
            return $stackPtr + 2;
57
        }
58
59
        // Finally, check the assumption the current token is or ends with a newline
60
        if ($tokens[$stackPtr]['line'] === $tokens[$stackPtr + 1]['line']) {
61
            return;
62
        }
63
64
        // Search for the next non-newline token
65
        $next = $stackPtr + 1;
66
67
        while (isset($tokens[$next + 1]) &&
68
            $tokens[$next]['code'] === T_WHITESPACE &&
69
            $tokens[$next]['line'] !== $tokens[$next + 1]['line']
70
        ) {
71
            $next++;
72
        }
73
74
        $count = $next - $stackPtr - 1;
75
76
        if ($count > 1
77
            && $phpcsFile->addFixableError(
78
                'Multiple empty lines should not exist in a row; found %s consecutive empty lines',
79
                $stackPtr + 1,
80
                'MultipleEmptyLines',
81
                [$count]
82
            )
83
        ) {
84
            $phpcsFile->fixer->beginChangeset();
85
86
            // Remove all newlines except the first two, i.e. keep one empty line
87
            for ($i = $stackPtr + 2; $i < $next; $i++) {
88
                $phpcsFile->fixer->replaceToken($i, '');
89
            }
90
91
            $phpcsFile->fixer->endChangeset();
92
        }
93
94
        // Don't check the current sequence a second time
95
        return $next;
96
    }
97
}
98