-
Notifications
You must be signed in to change notification settings - Fork 41
New sniff to remove unnecessary white space in small if conditions #2769
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,137 @@ | ||
| <?php | ||
| /** | ||
| * Formidable_Sniffs_WhiteSpace_NoBlankLineInShortIfSniff | ||
| * | ||
| * Removes blank lines inside if blocks that are exactly 3 lines. | ||
| * | ||
| * @package Formidable\Sniffs | ||
| */ | ||
|
|
||
| namespace Formidable\Sniffs\WhiteSpace; | ||
|
|
||
| use PHP_CodeSniffer\Sniffs\Sniff; | ||
| use PHP_CodeSniffer\Files\File; | ||
|
|
||
| /** | ||
| * Removes blank lines inside if blocks that are exactly 3 lines. | ||
| * | ||
| * Bad: | ||
| * if ( $condition ) { | ||
| * do_something(); | ||
| * | ||
| * return; | ||
| * } | ||
| * | ||
| * Good: | ||
| * if ( $condition ) { | ||
| * do_something(); | ||
| * return; | ||
| * } | ||
| */ | ||
| class NoBlankLineInShortIfSniff implements Sniff { | ||
|
|
||
| /** | ||
| * Returns an array of tokens this test wants to listen for. | ||
| * | ||
| * @return array | ||
| */ | ||
| public function register() { | ||
| return array( T_IF, T_ELSEIF, T_ELSE ); | ||
| } | ||
|
|
||
| /** | ||
| * Processes this test, when one of its tokens is encountered. | ||
| * | ||
| * @param File $phpcsFile The file being scanned. | ||
| * @param int $stackPtr The position of the current token in the stack passed in $tokens. | ||
| * | ||
| * @return void | ||
| */ | ||
| public function process( File $phpcsFile, $stackPtr ) { | ||
| $tokens = $phpcsFile->getTokens(); | ||
|
|
||
| // Make sure this if/else has a scope (curly braces). | ||
| if ( ! isset( $tokens[ $stackPtr ]['scope_opener'] ) || ! isset( $tokens[ $stackPtr ]['scope_closer'] ) ) { | ||
| return; | ||
| } | ||
|
|
||
| $scopeOpener = $tokens[ $stackPtr ]['scope_opener']; | ||
| $scopeCloser = $tokens[ $stackPtr ]['scope_closer']; | ||
|
|
||
| // Calculate the number of lines in the block body. | ||
| $openerLine = $tokens[ $scopeOpener ]['line']; | ||
| $closerLine = $tokens[ $scopeCloser ]['line']; | ||
|
|
||
| // Body lines = closerLine - openerLine - 1. | ||
| // We want to trigger when there are exactly 3 body lines (2 code + 1 blank). | ||
| // This means the if block has 2 statements but a blank line between them. | ||
| $bodyLines = $closerLine - $openerLine - 1; | ||
|
|
||
| // Only process if the body is exactly 3 lines (2 code lines + 1 blank line). | ||
| if ( $bodyLines !== 3 ) { | ||
| return; | ||
| } | ||
|
|
||
| // Find if there's a blank line inside the block. | ||
| // A blank line is a whitespace token that contains 2+ consecutive newlines. | ||
| $blankLineToken = null; | ||
|
|
||
| for ( $i = $scopeOpener + 1; $i < $scopeCloser; $i++ ) { | ||
| if ( $tokens[ $i ]['code'] === T_WHITESPACE ) { | ||
| $content = $tokens[ $i ]['content']; | ||
| $newlineCount = substr_count( $content, "\n" ); | ||
|
|
||
| // If this whitespace has 2+ newlines, it contains a blank line. | ||
| if ( $newlineCount >= 2 ) { | ||
| $blankLineToken = $i; | ||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if ( null === $blankLineToken ) { | ||
| // Also check for consecutive newline tokens (PHPCS sometimes splits them). | ||
| $lastWasNewline = false; | ||
|
|
||
| for ( $i = $scopeOpener + 1; $i < $scopeCloser; $i++ ) { | ||
| if ( $tokens[ $i ]['code'] === T_WHITESPACE && $tokens[ $i ]['content'] === "\n" ) { | ||
| if ( $lastWasNewline ) { | ||
| $blankLineToken = $i; | ||
| break; | ||
| } | ||
| $lastWasNewline = true; | ||
| } else { | ||
| $lastWasNewline = false; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if ( null === $blankLineToken ) { | ||
| return; | ||
| } | ||
|
|
||
| $fix = $phpcsFile->addFixableError( | ||
| 'Remove blank line inside short if block (3 lines or less).', | ||
| $blankLineToken, | ||
| 'BlankLineInShortIf' | ||
| ); | ||
|
|
||
| if ( true === $fix ) { | ||
| $phpcsFile->fixer->beginChangeset(); | ||
|
|
||
| $content = $tokens[ $blankLineToken ]['content']; | ||
|
|
||
| // Remove one newline from the whitespace. | ||
| if ( substr_count( $content, "\n" ) >= 2 ) { | ||
| // Replace double newline with single newline, preserving indentation. | ||
| $newContent = preg_replace( "/\n\n/", "\n", $content, 1 ); | ||
| $phpcsFile->fixer->replaceToken( $blankLineToken, $newContent ); | ||
|
Comment on lines
+125
to
+128
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix may fail when newlines aren't consecutive in the token content. The detection at line 85 triggers when a whitespace token contains 2+ newlines anywhere ( 🐛 Proposed fix // Remove one newline from the whitespace.
if ( substr_count( $content, "\n" ) >= 2 ) {
- // Replace double newline with single newline, preserving indentation.
- $newContent = preg_replace( "/\n\n/", "\n", $content, 1 );
+ // Remove the first blank line (newline + any following whitespace up to next newline).
+ $newContent = preg_replace( "/\n[ \t]*\n/", "\n", $content, 1 );
$phpcsFile->fixer->replaceToken( $blankLineToken, $newContent );🤖 Prompt for AI Agents |
||
| } elseif ( $content === "\n" ) { | ||
| // This is a standalone newline token that creates a blank line. | ||
| $phpcsFile->fixer->replaceToken( $blankLineToken, '' ); | ||
| } | ||
|
|
||
| $phpcsFile->fixer->endChangeset(); | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error message inconsistency.
The message says "3 lines or less" but the sniff only triggers for exactly 3-line blocks (line 71 checks
$bodyLines !== 3).📝 Suggested fix
📝 Committable suggestion
🤖 Prompt for AI Agents