From 0d982b2bc00bf2ba394d702cbf0ae1a7a81a8139 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Wed, 14 Oct 2026 11:31:17 +0200 Subject: [PATCH] Keep blank line between different import groups in NoBlankLineBetweenImports --- .../rules/no_blank_line_between_imports.go | 18 ++++++++ .../no_blank_line_between_imports_test.go | 11 +++++ .../NoBlankLineBetweenImportsFixer.php | 29 ++++++++++++- ...p_blank_line_between_import_groups.php.inc | 41 +++++++++++++++++++ 4 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 packages/coding-standard/tests/Fixer/Spacing/NoBlankLineBetweenImportsFixer/Fixture/keep_blank_line_between_import_groups.php.inc diff --git a/blink/internal/fixer/rules/no_blank_line_between_imports.go b/blink/internal/fixer/rules/no_blank_line_between_imports.go index 445da079ad..97562991ce 100644 --- a/blink/internal/fixer/rules/no_blank_line_between_imports.go +++ b/blink/internal/fixer/rules/no_blank_line_between_imports.go @@ -46,6 +46,10 @@ func (NoBlankLineBetweenImports) Fix(s *tokens.Stream) bool { if prev < 0 || s.At(prev).Kind != token.Punct || s.At(prev).Value != ";" { continue } + // keep the blank line between different import groups, e.g. class and "use function" + if importType(s, useIndex) != importType(s, uses[k-1]) { + continue + } ws := useIndex - 1 if ws < 0 || s.At(ws).Kind != token.Whitespace { continue @@ -58,3 +62,17 @@ func (NoBlankLineBetweenImports) Fix(s *tokens.Stream) bool { } return changed } + +// importType classifies an import "use" as "function", "const" or "class". +func importType(s *tokens.Stream, useIndex int) string { + j := skipWhitespace(s, useIndex+1) + if j < s.Len() { + switch strings.ToLower(s.At(j).Value) { + case "function": + return "function" + case "const": + return "const" + } + } + return "class" +} diff --git a/blink/internal/fixer/rules/no_blank_line_between_imports_test.go b/blink/internal/fixer/rules/no_blank_line_between_imports_test.go index 95a7e9f412..d2da4d0148 100644 --- a/blink/internal/fixer/rules/no_blank_line_between_imports_test.go +++ b/blink/internal/fixer/rules/no_blank_line_between_imports_test.go @@ -21,4 +21,15 @@ func TestNoBlankLineBetweenImports(t *testing.T) { if _, changed := apply(t, f, "resolveImportType($tokens, $useIndex) !== $this->resolveImportType($tokens, $useIndexes[$i - 1])) { + continue; + } + $whitespaceIndex = $useIndex - 1; if (! $tokens[$whitespaceIndex]->isWhitespace()) { continue; @@ -79,4 +85,25 @@ public function fix(SplFileInfo $fileInfo, Tokens $tokens): void $tokens[$whitespaceIndex] = new Token([T_WHITESPACE, $lineEnding]); } } + + /** + * @param Tokens $tokens + */ + private function resolveImportType(Tokens $tokens, int $useIndex): string + { + $nextIndex = $tokens->getNextMeaningfulToken($useIndex); + if ($nextIndex === null) { + return 'class'; + } + + if ($tokens[$nextIndex]->isGivenKind(CT::T_FUNCTION_IMPORT)) { + return 'function'; + } + + if ($tokens[$nextIndex]->isGivenKind(CT::T_CONST_IMPORT)) { + return 'const'; + } + + return 'class'; + } } diff --git a/packages/coding-standard/tests/Fixer/Spacing/NoBlankLineBetweenImportsFixer/Fixture/keep_blank_line_between_import_groups.php.inc b/packages/coding-standard/tests/Fixer/Spacing/NoBlankLineBetweenImportsFixer/Fixture/keep_blank_line_between_import_groups.php.inc new file mode 100644 index 0000000000..f36f2f33a2 --- /dev/null +++ b/packages/coding-standard/tests/Fixer/Spacing/NoBlankLineBetweenImportsFixer/Fixture/keep_blank_line_between_import_groups.php.inc @@ -0,0 +1,41 @@ + +----- +