Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 58 |
|
0.00% |
0 / 3 |
CRAP | |
0.00% |
0 / 1 |
SpaceBeforeClassBraceSniff | |
0.00% |
0 / 58 |
|
0.00% |
0 / 3 |
462 | |
0.00% |
0 / 1 |
register | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
process | |
0.00% |
0 / 47 |
|
0.00% |
0 / 1 |
182 | |||
getStructureKeyword | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
56 |
1 | <?php |
2 | /** |
3 | * make sure a space before class open brace. |
4 | * fail: class TestClass\t{ |
5 | * fail: class TestClass{ |
6 | * fail: class TestClass { |
7 | * pass: class TestClass { |
8 | */ |
9 | |
10 | namespace MediaWiki\Sniffs\WhiteSpace; |
11 | |
12 | use PHP_CodeSniffer\Files\File; |
13 | use PHP_CodeSniffer\Sniffs\Sniff; |
14 | use PHP_CodeSniffer\Util\Tokens; |
15 | use UnexpectedValueException; |
16 | |
17 | class SpaceBeforeClassBraceSniff implements Sniff { |
18 | /** |
19 | * @inheritDoc |
20 | */ |
21 | public function register(): array { |
22 | return Tokens::$ooScopeTokens; |
23 | } |
24 | |
25 | /** |
26 | * @param File $phpcsFile |
27 | * @param int $stackPtr The index of current token. |
28 | * @return void |
29 | */ |
30 | public function process( File $phpcsFile, $stackPtr ) { |
31 | $tokens = $phpcsFile->getTokens(); |
32 | if ( !isset( $tokens[$stackPtr]['scope_opener'] ) ) { |
33 | return; |
34 | } |
35 | $structKeyword = $this->getStructureKeyword( $tokens[$stackPtr]['code'] ); |
36 | $openBrace = $tokens[$stackPtr]['scope_opener']; |
37 | // Find previous non-whitespace token from the opening brace |
38 | $pre = $phpcsFile->findPrevious( T_WHITESPACE, $openBrace - 1, null, true ); |
39 | |
40 | $afterClass = $stackPtr; |
41 | if ( $tokens[$stackPtr]['code'] === T_ANON_CLASS && isset( $tokens[$stackPtr]['parenthesis_closer'] ) ) { |
42 | // The anon class could be multi-line, start after the class definition |
43 | $afterClass = $tokens[$stackPtr]['parenthesis_closer']; |
44 | } |
45 | |
46 | if ( $tokens[$openBrace]['line'] - $tokens[$afterClass]['line'] >= 2 ) { |
47 | // If the class ... { statement is more than two lines, then |
48 | // the { should be on a line by itself. |
49 | if ( $tokens[$pre]['line'] === $tokens[$openBrace]['line'] ) { |
50 | $fix = $phpcsFile->addFixableWarning( |
51 | "Expected $structKeyword open brace to be on a new line", |
52 | $openBrace, |
53 | 'BraceNotOnOwnLine' |
54 | ); |
55 | if ( $fix ) { |
56 | $phpcsFile->fixer->addNewlineBefore( $openBrace ); |
57 | } |
58 | } |
59 | return; |
60 | } |
61 | $spaceCount = 0; |
62 | for ( $start = $pre + 1; $start < $openBrace; $start++ ) { |
63 | $content = $tokens[$start]['content']; |
64 | $contentSize = strlen( $content ); |
65 | $spaceCount += $contentSize; |
66 | } |
67 | |
68 | if ( $spaceCount !== 1 ) { |
69 | $fix = $phpcsFile->addFixableWarning( |
70 | "Expected 1 space before $structKeyword open brace. Found %s.", |
71 | $openBrace, |
72 | 'NoSpaceBeforeBrace', |
73 | [ $spaceCount ] |
74 | ); |
75 | if ( $fix ) { |
76 | $phpcsFile->fixer->beginChangeset(); |
77 | $phpcsFile->fixer->replaceToken( $openBrace, '' ); |
78 | $phpcsFile->fixer->addContent( $pre, ' {' ); |
79 | $phpcsFile->fixer->endChangeset(); |
80 | } |
81 | } |
82 | |
83 | if ( $tokens[$openBrace]['line'] !== $tokens[$pre]['line'] ) { |
84 | $fix = $phpcsFile->addFixableWarning( |
85 | "Expected $structKeyword open brace to be on the same line as the `$structKeyword` keyword.", |
86 | $openBrace, |
87 | 'BraceNotOnSameLine' |
88 | ); |
89 | if ( $fix ) { |
90 | $phpcsFile->fixer->beginChangeset(); |
91 | for ( $i = $pre + 1; $i < $openBrace; $i++ ) { |
92 | $phpcsFile->fixer->replaceToken( $i, '' ); |
93 | } |
94 | $phpcsFile->fixer->endChangeset(); |
95 | } |
96 | } |
97 | } |
98 | |
99 | /** |
100 | * Returns the keyword used to define the OOP structure of the given type. |
101 | * |
102 | * @param int|string $tokenType |
103 | * @return string |
104 | */ |
105 | private function getStructureKeyword( $tokenType ): string { |
106 | switch ( $tokenType ) { |
107 | case T_CLASS: |
108 | case T_ANON_CLASS: |
109 | return 'class'; |
110 | case T_INTERFACE: |
111 | return 'interface'; |
112 | case T_TRAIT: |
113 | return 'trait'; |
114 | case T_ENUM: |
115 | return 'enum'; |
116 | default: |
117 | throw new UnexpectedValueException( "Token $tokenType not handled" ); |
118 | } |
119 | } |
120 | } |