Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 52
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
SpaceBeforeSingleLineCommentSniff
0.00% covered (danger)
0.00%
0 / 52
0.00% covered (danger)
0.00%
0 / 2
462
0.00% covered (danger)
0.00%
0 / 1
 register
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 process
0.00% covered (danger)
0.00%
0 / 49
0.00% covered (danger)
0.00%
0 / 1
420
1<?php
2/**
3 * Verify that comments are preceded by a single space. However, allow it if there are
4 * multiple single-line comments on consecutive lines (also with empty lines in between).
5 */
6
7namespace MediaWiki\Sniffs\WhiteSpace;
8
9use PHP_CodeSniffer\Files\File;
10use PHP_CodeSniffer\Sniffs\Sniff;
11
12class SpaceBeforeSingleLineCommentSniff implements Sniff {
13
14    /**
15     * @inheritDoc
16     */
17    public function register(): array {
18        return [
19            T_COMMENT
20        ];
21    }
22
23    /**
24     * @param File $phpcsFile
25     * @param int $stackPtr The current token index.
26     * @return void
27     */
28    public function process( File $phpcsFile, $stackPtr ) {
29        $tokens = $phpcsFile->getTokens();
30        $currToken = $tokens[$stackPtr];
31        $preToken = $phpcsFile->findPrevious( T_WHITESPACE, $stackPtr - 1, null, true );
32        if ( $preToken !== false &&
33            $tokens[$preToken]['line'] === $tokens[$stackPtr]['line']
34        ) {
35            $phpcsFile->addWarning(
36                'Comments should start on new line.',
37                $stackPtr,
38                'NewLineComment'
39            );
40        }
41        if ( $currToken['code'] === T_COMMENT ) {
42            // Accounting for multiple line comments, as single line comments
43            // use only '//' and '#'
44            // Also ignoring PHPDoc comments starting with '///',
45            // as there are no coding standards documented for these
46            if ( str_starts_with( $currToken['content'], '/*' )
47                || str_starts_with( $currToken['content'], '///' )
48            ) {
49                return;
50            }
51
52            // Checking whether the comment is an empty one
53            if ( ( str_starts_with( $currToken['content'], '//' ) &&
54                rtrim( $currToken['content'] ) === '//' ) ||
55                ( $currToken['content'][0] === '#' &&
56                    rtrim( $currToken['content'] ) === '#' )
57            ) {
58                return;
59            }
60
61            // If the previous token is a comment, assume extra spaces are used for indenting
62            // and thus are OK.
63            if ( $preToken !== false && $tokens[$preToken]['code'] === T_COMMENT ) {
64                return;
65            }
66
67            // Checking whether there is a space between the comment delimiter
68            // and the comment
69            if ( str_starts_with( $currToken['content'], '//' ) ) {
70                $commentContent = substr( $currToken['content'], 2 );
71                $commentTrim = ltrim( $commentContent );
72                if (
73                    strlen( $commentContent ) !== ( strlen( $commentTrim ) + 1 ) ||
74                    $currToken['content'][2] !== ' '
75                ) {
76                    $fix = $phpcsFile->addFixableWarning(
77                        'Single space expected between "//" and comment',
78                        $stackPtr,
79                        'SingleSpaceBeforeSingleLineComment'
80                    );
81                    if ( $fix ) {
82                        $phpcsFile->fixer->replaceToken( $stackPtr, '// ' . $commentTrim );
83                    }
84                }
85            // Finding what the comment delimiter is and checking whether there is a space
86            // between the comment delimiter and the comment.
87            } elseif ( $currToken['content'][0] === '#' ) {
88                // Find number of `#` used.
89                $startComment = 0;
90                while ( $currToken['content'][$startComment] === '#' ) {
91                    $startComment++;
92                }
93                if ( $currToken['content'][$startComment] !== ' ' ) {
94                    $fix = $phpcsFile->addFixableWarning(
95                        'Single space expected between "#" and comment',
96                        $stackPtr,
97                        'SingleSpaceBeforeSingleLineComment'
98                    );
99                    if ( $fix ) {
100                        $content = $currToken['content'];
101                        $newContent = '# ';
102                        $tmpContent = substr( $content, 1 );
103                        $newContent .= ltrim( $tmpContent );
104                        $phpcsFile->fixer->replaceToken( $stackPtr, $newContent );
105                    }
106                }
107            }
108        }
109    }
110}