From 658f9fa29262edd27c77d4c5725eadeb134a8c53 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Sun, 6 Sep 2026 23:30:38 +0200 Subject: [PATCH] Add NoBlankLineBetweenImportsFixer to spaces set Removes blank lines between consecutive import use statements, keeping the blank line after the namespace intact. Claude-Session: https://claude.ai/code/session_01HW65cppPCzg5wp2aMgEqKC --- .../NoBlankLineBetweenImportsFixer.php | 82 +++++++++++++++++++ .../blank_line_between_imports.php.inc | 26 ++++++ .../Fixture/skip_namespace_blank_line.php.inc | 12 +++ .../NoBlankLineBetweenImportsFixerTest.php | 28 +++++++ .../config/configured_rule.php | 10 +++ scoper.php | 1 - src/Config/Level/SpacesLevel.php | 2 + 7 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 packages/coding-standard/src/Fixer/Spacing/NoBlankLineBetweenImportsFixer.php create mode 100644 packages/coding-standard/tests/Fixer/Spacing/NoBlankLineBetweenImportsFixer/Fixture/blank_line_between_imports.php.inc create mode 100644 packages/coding-standard/tests/Fixer/Spacing/NoBlankLineBetweenImportsFixer/Fixture/skip_namespace_blank_line.php.inc create mode 100644 packages/coding-standard/tests/Fixer/Spacing/NoBlankLineBetweenImportsFixer/NoBlankLineBetweenImportsFixerTest.php create mode 100644 packages/coding-standard/tests/Fixer/Spacing/NoBlankLineBetweenImportsFixer/config/configured_rule.php diff --git a/packages/coding-standard/src/Fixer/Spacing/NoBlankLineBetweenImportsFixer.php b/packages/coding-standard/src/Fixer/Spacing/NoBlankLineBetweenImportsFixer.php new file mode 100644 index 0000000000..a250aa2ece --- /dev/null +++ b/packages/coding-standard/src/Fixer/Spacing/NoBlankLineBetweenImportsFixer.php @@ -0,0 +1,82 @@ + $tokens + */ + public function isCandidate(Tokens $tokens): bool + { + return $tokens->isTokenKindFound(T_USE); + } + + public function setWhitespacesConfig(WhitespacesFixerConfig $whitespacesFixerConfig): void + { + $this->whitespacesFixerConfig = $whitespacesFixerConfig; + } + + /** + * @param Tokens $tokens + */ + public function fix(SplFileInfo $fileInfo, Tokens $tokens): void + { + $tokensAnalyzer = new TokensAnalyzer($tokens); + $useIndexes = $tokensAnalyzer->getImportUseIndexes(); + + $lineEnding = $this->whitespacesFixerConfig->getLineEnding(); + + // start at the 2nd use, so the blank line after the namespace stays untouched + for ($i = 1, $count = count($useIndexes); $i < $count; ++$i) { + $useIndex = $useIndexes[$i]; + + $previousIndex = $tokens->getPrevMeaningfulToken($useIndex); + if ($previousIndex === null || ! $tokens[$previousIndex]->equals(';')) { + continue; + } + + $whitespaceIndex = $useIndex - 1; + if (! $tokens[$whitespaceIndex]->isWhitespace()) { + continue; + } + + if (substr_count($tokens[$whitespaceIndex]->getContent(), "\n") < 2) { + continue; + } + + $tokens[$whitespaceIndex] = new Token([T_WHITESPACE, $lineEnding]); + } + } +} diff --git a/packages/coding-standard/tests/Fixer/Spacing/NoBlankLineBetweenImportsFixer/Fixture/blank_line_between_imports.php.inc b/packages/coding-standard/tests/Fixer/Spacing/NoBlankLineBetweenImportsFixer/Fixture/blank_line_between_imports.php.inc new file mode 100644 index 0000000000..b7055aaef6 --- /dev/null +++ b/packages/coding-standard/tests/Fixer/Spacing/NoBlankLineBetweenImportsFixer/Fixture/blank_line_between_imports.php.inc @@ -0,0 +1,26 @@ + +----- + diff --git a/packages/coding-standard/tests/Fixer/Spacing/NoBlankLineBetweenImportsFixer/Fixture/skip_namespace_blank_line.php.inc b/packages/coding-standard/tests/Fixer/Spacing/NoBlankLineBetweenImportsFixer/Fixture/skip_namespace_blank_line.php.inc new file mode 100644 index 0000000000..c47933963e --- /dev/null +++ b/packages/coding-standard/tests/Fixer/Spacing/NoBlankLineBetweenImportsFixer/Fixture/skip_namespace_blank_line.php.inc @@ -0,0 +1,12 @@ + diff --git a/packages/coding-standard/tests/Fixer/Spacing/NoBlankLineBetweenImportsFixer/NoBlankLineBetweenImportsFixerTest.php b/packages/coding-standard/tests/Fixer/Spacing/NoBlankLineBetweenImportsFixer/NoBlankLineBetweenImportsFixerTest.php new file mode 100644 index 0000000000..16e8184c2f --- /dev/null +++ b/packages/coding-standard/tests/Fixer/Spacing/NoBlankLineBetweenImportsFixer/NoBlankLineBetweenImportsFixerTest.php @@ -0,0 +1,28 @@ +doTestFile($filePath); + } + + public static function provideData(): Iterator + { + return self::yieldFiles(__DIR__ . '/Fixture'); + } + + public function provideConfig(): string + { + return __DIR__ . '/config/configured_rule.php'; + } +} diff --git a/packages/coding-standard/tests/Fixer/Spacing/NoBlankLineBetweenImportsFixer/config/configured_rule.php b/packages/coding-standard/tests/Fixer/Spacing/NoBlankLineBetweenImportsFixer/config/configured_rule.php new file mode 100644 index 0000000000..5fa9d84227 --- /dev/null +++ b/packages/coding-standard/tests/Fixer/Spacing/NoBlankLineBetweenImportsFixer/config/configured_rule.php @@ -0,0 +1,10 @@ +rule(NoBlankLineBetweenImportsFixer::class); +}; diff --git a/scoper.php b/scoper.php index 6981cf8fb7..37bd793e19 100644 --- a/scoper.php +++ b/scoper.php @@ -8,7 +8,6 @@ require __DIR__ . '/vendor/autoload.php'; $timestamp = (new DateTime('now'))->format('Ym'); - use Symplify\EasyCodingStandard\Application\Version\StaticVersionResolver; // excluding polyfills in generic way diff --git a/src/Config/Level/SpacesLevel.php b/src/Config/Level/SpacesLevel.php index 6fa48e8b62..47265abbb1 100644 --- a/src/Config/Level/SpacesLevel.php +++ b/src/Config/Level/SpacesLevel.php @@ -30,6 +30,7 @@ use PhpCsFixer\Fixer\Whitespace\TypeDeclarationSpacesFixer; use PhpCsFixer\Fixer\Whitespace\TypesSpacesFixer; use Symplify\CodingStandard\Fixer\Spacing\MethodChainingNewlineFixer; +use Symplify\CodingStandard\Fixer\Spacing\NoBlankLineBetweenImportsFixer; use Symplify\CodingStandard\Fixer\Spacing\SpaceAfterCommaHereNowDocFixer; use Symplify\CodingStandard\Fixer\Spacing\StandaloneLinePromotedPropertyFixer; use Symplify\CodingStandard\Fixer\Spacing\StandaloneLineRequiredParamFixer; @@ -63,6 +64,7 @@ final class SpacesLevel SingleTraitInsertPerStatementFixer::class, PhpdocSingleLineVarSpacingFixer::class, LanguageConstructSpacingSniff::class, + NoBlankLineBetweenImportsFixer::class, // operator and type spacing CastSpacesFixer::class,