Skip to content

Commit b770ed3

Browse files
committed
Added PSR12.Classes.AnonClassDeclaration sniff to enforce formatting of anon classes
Includes refactoring and some message wording changes to other sniffs as the anon class sniff makes use of several others
1 parent 7a46d7b commit b770ed3

File tree

10 files changed

+665
-108
lines changed

10 files changed

+665
-108
lines changed

package.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
7474
-- Thanks to Mponos George for the contribution
7575
- Added Generic.PHP.RequireStrictTypes sniff
7676
-- Enforce the use of a strict types declaration in PHP files
77+
- Added PSR12.Classes.AnonClassDeclaration sniff
78+
-- Enforces the formatting of anonymous classes
7779
- Added PSR12.Classes.ClosingBrace sniff
7880
-- Enforces that closing braces of classes/interfaces/traits/functions are not followed by a comment or statement
7981
- Added PSR12.ControlStructures.BooleanOperatorPlacement sniff
@@ -1133,6 +1135,7 @@ http://pear.php.net/dtd/package-2.0.xsd">
11331135
</dir>
11341136
<dir name="Sniffs">
11351137
<dir name="Classes">
1138+
<file baseinstalldir="PHP/CodeSniffer" name="AnonClassDeclarationSniff.php" role="php" />
11361139
<file baseinstalldir="PHP/CodeSniffer" name="ClassInstantiationSniff.php" role="php" />
11371140
<file baseinstalldir="PHP/CodeSniffer" name="ClosingBraceSniff.php" role="php" />
11381141
</dir>
@@ -1168,6 +1171,9 @@ http://pear.php.net/dtd/package-2.0.xsd">
11681171
</dir>
11691172
<dir name="Tests">
11701173
<dir name="Classes">
1174+
<file baseinstalldir="PHP/CodeSniffer" name="AnonClassDeclarationUnitTest.inc" role="test" />
1175+
<file baseinstalldir="PHP/CodeSniffer" name="AnonClassDeclarationUnitTest.inc.fixed" role="test" />
1176+
<file baseinstalldir="PHP/CodeSniffer" name="AnonClassDeclarationUnitTest.php" role="test" />
11711177
<file baseinstalldir="PHP/CodeSniffer" name="ClassInstantiationUnitTest.inc" role="test" />
11721178
<file baseinstalldir="PHP/CodeSniffer" name="ClassInstantiationUnitTest.inc.fixed" role="test" />
11731179
<file baseinstalldir="PHP/CodeSniffer" name="ClassInstantiationUnitTest.php" role="test" />

src/Standards/Generic/Sniffs/Functions/FunctionCallArgumentSpacingSniff.php

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,26 @@ public function process(File $phpcsFile, $stackPtr)
8282
return;
8383
}
8484

85+
$this->checkSpacing($phpcsFile, $stackPtr, $openBracket);
86+
87+
}//end process()
88+
89+
90+
/**
91+
* Checks the spacing around commas.
92+
*
93+
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
94+
* @param int $stackPtr The position of the current token in the
95+
* stack passed in $tokens.
96+
* @param int $openBracket The position of the opening bracket
97+
* in the stack passed in $tokens.
98+
*
99+
* @return void
100+
*/
101+
public function checkSpacing(File $phpcsFile, $stackPtr, $openBracket)
102+
{
103+
$tokens = $phpcsFile->getTokens();
104+
85105
$closeBracket = $tokens[$openBracket]['parenthesis_closer'];
86106
$nextSeparator = $openBracket;
87107

@@ -117,7 +137,7 @@ public function process(File $phpcsFile, $stackPtr)
117137
if ($tokens[($nextSeparator - 1)]['code'] === T_WHITESPACE) {
118138
$prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($nextSeparator - 2), null, true);
119139
if (isset(Tokens::$heredocTokens[$tokens[$prev]['code']]) === false) {
120-
$error = 'Space found before comma in function call';
140+
$error = 'Space found before comma in argument list';
121141
$fix = $phpcsFile->addFixableError($error, $nextSeparator, 'SpaceBeforeComma');
122142
if ($fix === true) {
123143
$phpcsFile->fixer->beginChangeset();
@@ -135,7 +155,7 @@ public function process(File $phpcsFile, $stackPtr)
135155
}//end if
136156

137157
if ($tokens[($nextSeparator + 1)]['code'] !== T_WHITESPACE) {
138-
$error = 'No space found after comma in function call';
158+
$error = 'No space found after comma in argument list';
139159
$fix = $phpcsFile->addFixableError($error, $nextSeparator, 'NoSpaceAfterComma');
140160
if ($fix === true) {
141161
$phpcsFile->fixer->addContent($nextSeparator, ' ');
@@ -147,7 +167,7 @@ public function process(File $phpcsFile, $stackPtr)
147167
if ($tokens[$next]['line'] === $tokens[$nextSeparator]['line']) {
148168
$space = $tokens[($nextSeparator + 1)]['length'];
149169
if ($space > 1) {
150-
$error = 'Expected 1 space after comma in function call; %s found';
170+
$error = 'Expected 1 space after comma in argument list; %s found';
151171
$data = [$space];
152172
$fix = $phpcsFile->addFixableError($error, $nextSeparator, 'TooMuchSpaceAfterComma', $data);
153173
if ($fix === true) {
@@ -159,7 +179,7 @@ public function process(File $phpcsFile, $stackPtr)
159179
}//end if
160180
}//end while
161181

162-
}//end process()
182+
}//end checkSpacing()
163183

164184

165185
}//end class

src/Standards/PEAR/Sniffs/Functions/FunctionCallSignatureSniff.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,12 +205,12 @@ public function isMultiLineCall(File $phpcsFile, $stackPtr, $openBracket, $token
205205
*/
206206
public function processSingleLineCall(File $phpcsFile, $stackPtr, $openBracket, $tokens)
207207
{
208-
// If the function call has no arguments or comments, enforce 0 spaces.
209208
$closer = $tokens[$openBracket]['parenthesis_closer'];
210209
if ($openBracket === ($closer - 1)) {
211210
return;
212211
}
213212

213+
// If the function call has no arguments or comments, enforce 0 spaces.
214214
$next = $phpcsFile->findNext(T_WHITESPACE, ($openBracket + 1), $closer, true);
215215
if ($next === false) {
216216
$requiredSpacesAfterOpen = 0;

src/Standards/PEAR/Sniffs/Functions/FunctionDeclarationSniff.php

Lines changed: 109 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,97 @@ public function processSingleLineDeclaration($phpcsFile, $stackPtr, $tokens)
282282
*/
283283
public function processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens)
284284
{
285+
$this->processArgumentList($phpcsFile, $stackPtr, $this->indent);
286+
287+
$closeBracket = $tokens[$stackPtr]['parenthesis_closer'];
288+
if ($tokens[$stackPtr]['code'] === T_CLOSURE) {
289+
$use = $phpcsFile->findNext(T_USE, ($closeBracket + 1), $tokens[$stackPtr]['scope_opener']);
290+
if ($use !== false) {
291+
$open = $phpcsFile->findNext(T_OPEN_PARENTHESIS, ($use + 1));
292+
$closeBracket = $tokens[$open]['parenthesis_closer'];
293+
}
294+
}
295+
296+
if (isset($tokens[$stackPtr]['scope_opener']) === false) {
297+
return;
298+
}
299+
300+
// The opening brace needs to be one space away from the closing parenthesis.
301+
$opener = $tokens[$stackPtr]['scope_opener'];
302+
if ($tokens[$opener]['line'] !== $tokens[$closeBracket]['line']) {
303+
$error = 'The closing parenthesis and the opening brace of a multi-line function declaration must be on the same line';
304+
$fix = $phpcsFile->addFixableError($error, $opener, 'NewlineBeforeOpenBrace');
305+
if ($fix === true) {
306+
$prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($opener - 1), $closeBracket, true);
307+
$phpcsFile->fixer->beginChangeset();
308+
$phpcsFile->fixer->addContent($prev, ' {');
309+
310+
// If the opener is on a line by itself, removing it will create
311+
// an empty line, so just remove the entire line instead.
312+
$prev = $phpcsFile->findPrevious(T_WHITESPACE, ($opener - 1), $closeBracket, true);
313+
$next = $phpcsFile->findNext(T_WHITESPACE, ($opener + 1), null, true);
314+
315+
if ($tokens[$prev]['line'] < $tokens[$opener]['line']
316+
&& $tokens[$next]['line'] > $tokens[$opener]['line']
317+
) {
318+
// Clear the whole line.
319+
for ($i = ($prev + 1); $i < $next; $i++) {
320+
if ($tokens[$i]['line'] === $tokens[$opener]['line']) {
321+
$phpcsFile->fixer->replaceToken($i, '');
322+
}
323+
}
324+
} else {
325+
// Just remove the opener.
326+
$phpcsFile->fixer->replaceToken($opener, '');
327+
if ($tokens[$next]['line'] === $tokens[$opener]['line']) {
328+
$phpcsFile->fixer->replaceToken(($opener + 1), '');
329+
}
330+
}
331+
332+
$phpcsFile->fixer->endChangeset();
333+
}//end if
334+
} else {
335+
$prev = $tokens[($opener - 1)];
336+
if ($prev['code'] !== T_WHITESPACE) {
337+
$length = 0;
338+
} else {
339+
$length = strlen($prev['content']);
340+
}
341+
342+
if ($length !== 1) {
343+
$error = 'There must be a single space between the closing parenthesis and the opening brace of a multi-line function declaration; found %s spaces';
344+
$fix = $phpcsFile->addFixableError($error, ($opener - 1), 'SpaceBeforeOpenBrace', [$length]);
345+
if ($fix === true) {
346+
if ($length === 0) {
347+
$phpcsFile->fixer->addContentBefore($opener, ' ');
348+
} else {
349+
$phpcsFile->fixer->replaceToken(($opener - 1), ' ');
350+
}
351+
}
352+
353+
return;
354+
}//end if
355+
}//end if
356+
357+
}//end processMultiLineDeclaration()
358+
359+
360+
/**
361+
* Processes multi-line argument list declarations.
362+
*
363+
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
364+
* @param int $stackPtr The position of the current token
365+
* in the stack passed in $tokens.
366+
* @param int $indent The number of spaces code should be indented.
367+
* @param string $type The type of the token the brackets
368+
* belong to.
369+
*
370+
* @return void
371+
*/
372+
public function processArgumentList($phpcsFile, $stackPtr, $indent, $type='function')
373+
{
374+
$tokens = $phpcsFile->getTokens();
375+
285376
// We need to work out how far indented the function
286377
// declaration itself is, so we can work out how far to
287378
// indent parameters.
@@ -309,13 +400,13 @@ public function processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens)
309400
true
310401
);
311402

312-
if ($tokens[$closeBracket]['line'] !== $tokens[$tokens[$closeBracket]['parenthesis_opener']]['line']) {
313-
if ($tokens[$prev]['line'] === $tokens[$closeBracket]['line']) {
314-
$error = 'The closing parenthesis of a multi-line function declaration must be on a new line';
315-
$fix = $phpcsFile->addFixableError($error, $closeBracket, 'CloseBracketLine');
316-
if ($fix === true) {
317-
$phpcsFile->fixer->addNewlineBefore($closeBracket);
318-
}
403+
if ($tokens[$closeBracket]['line'] !== $tokens[$tokens[$closeBracket]['parenthesis_opener']]['line']
404+
&& $tokens[$prev]['line'] === $tokens[$closeBracket]['line']
405+
) {
406+
$error = 'The closing parenthesis of a multi-line '.$type.' declaration must be on a new line';
407+
$fix = $phpcsFile->addFixableError($error, $closeBracket, 'CloseBracketLine');
408+
if ($fix === true) {
409+
$phpcsFile->fixer->addNewlineBefore($closeBracket);
319410
}
320411
}
321412

@@ -335,13 +426,13 @@ public function processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens)
335426
true
336427
);
337428

338-
if ($tokens[$closeBracket]['line'] !== $tokens[$tokens[$closeBracket]['parenthesis_opener']]['line']) {
339-
if ($tokens[$prev]['line'] === $tokens[$closeBracket]['line']) {
340-
$error = 'The closing parenthesis of a multi-line use declaration must be on a new line';
341-
$fix = $phpcsFile->addFixableError($error, $closeBracket, 'UseCloseBracketLine');
342-
if ($fix === true) {
343-
$phpcsFile->fixer->addNewlineBefore($closeBracket);
344-
}
429+
if ($tokens[$closeBracket]['line'] !== $tokens[$tokens[$closeBracket]['parenthesis_opener']]['line']
430+
&& $tokens[$prev]['line'] === $tokens[$closeBracket]['line']
431+
) {
432+
$error = 'The closing parenthesis of a multi-line use declaration must be on a new line';
433+
$fix = $phpcsFile->addFixableError($error, $closeBracket, 'UseCloseBracketLine');
434+
if ($fix === true) {
435+
$phpcsFile->fixer->addNewlineBefore($closeBracket);
345436
}
346437
}
347438
}//end if
@@ -361,7 +452,7 @@ public function processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens)
361452
// as the function.
362453
$expectedIndent = $functionIndent;
363454
} else {
364-
$expectedIndent = ($functionIndent + $this->indent);
455+
$expectedIndent = ($functionIndent + $indent);
365456
}
366457

367458
// We changed lines, so this should be a whitespace indent token.
@@ -371,7 +462,7 @@ public function processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens)
371462
// This is an empty line, so don't check the indent.
372463
$foundIndent = $expectedIndent;
373464

374-
$error = 'Blank lines are not allowed in a multi-line function declaration';
465+
$error = 'Blank lines are not allowed in a multi-line '.$type.' declaration';
375466
$fix = $phpcsFile->addFixableError($error, $i, 'EmptyLine');
376467
if ($fix === true) {
377468
$phpcsFile->fixer->replaceToken($i, '');
@@ -381,7 +472,7 @@ public function processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens)
381472
}
382473

383474
if ($expectedIndent !== $foundIndent) {
384-
$error = 'Multi-line function declaration not indented correctly; expected %s spaces but found %s';
475+
$error = 'Multi-line '.$type.' declaration not indented correctly; expected %s spaces but found %s';
385476
$data = [
386477
$expectedIndent,
387478
$foundIndent,
@@ -414,68 +505,7 @@ public function processMultiLineDeclaration($phpcsFile, $stackPtr, $tokens)
414505
}
415506
}//end for
416507

417-
if (isset($tokens[$stackPtr]['scope_opener']) === false) {
418-
return;
419-
}
420-
421-
// The opening brace needs to be one space away from the closing parenthesis.
422-
$opener = $tokens[$stackPtr]['scope_opener'];
423-
if ($tokens[$opener]['line'] !== $tokens[$closeBracket]['line']) {
424-
$error = 'The closing parenthesis and the opening brace of a multi-line function declaration must be on the same line';
425-
$fix = $phpcsFile->addFixableError($error, $opener, 'NewlineBeforeOpenBrace');
426-
if ($fix === true) {
427-
$prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($opener - 1), $closeBracket, true);
428-
$phpcsFile->fixer->beginChangeset();
429-
$phpcsFile->fixer->addContent($prev, ' {');
430-
431-
// If the opener is on a line by itself, removing it will create
432-
// an empty line, so just remove the entire line instead.
433-
$prev = $phpcsFile->findPrevious(T_WHITESPACE, ($opener - 1), $closeBracket, true);
434-
$next = $phpcsFile->findNext(T_WHITESPACE, ($opener + 1), null, true);
435-
436-
if ($tokens[$prev]['line'] < $tokens[$opener]['line']
437-
&& $tokens[$next]['line'] > $tokens[$opener]['line']
438-
) {
439-
// Clear the whole line.
440-
for ($i = ($prev + 1); $i < $next; $i++) {
441-
if ($tokens[$i]['line'] === $tokens[$opener]['line']) {
442-
$phpcsFile->fixer->replaceToken($i, '');
443-
}
444-
}
445-
} else {
446-
// Just remove the opener.
447-
$phpcsFile->fixer->replaceToken($opener, '');
448-
if ($tokens[$next]['line'] === $tokens[$opener]['line']) {
449-
$phpcsFile->fixer->replaceToken(($opener + 1), '');
450-
}
451-
}
452-
453-
$phpcsFile->fixer->endChangeset();
454-
}//end if
455-
} else {
456-
$prev = $tokens[($opener - 1)];
457-
if ($prev['code'] !== T_WHITESPACE) {
458-
$length = 0;
459-
} else {
460-
$length = strlen($prev['content']);
461-
}
462-
463-
if ($length !== 1) {
464-
$error = 'There must be a single space between the closing parenthesis and the opening brace of a multi-line function declaration; found %s spaces';
465-
$fix = $phpcsFile->addFixableError($error, ($opener - 1), 'SpaceBeforeOpenBrace', [$length]);
466-
if ($fix === true) {
467-
if ($length === 0) {
468-
$phpcsFile->fixer->addContentBefore($opener, ' ');
469-
} else {
470-
$phpcsFile->fixer->replaceToken(($opener - 1), ' ');
471-
}
472-
}
473-
474-
return;
475-
}//end if
476-
}//end if
477-
478-
}//end processMultiLineDeclaration()
508+
}//end processArgumentList()
479509

480510

481511
}//end class

0 commit comments

Comments
 (0)