Repository: FriendsOfPHP/PHP-CS-Fixer (php)

Issue:
'header_comment' contradicts with 'no_blank_lines_after_phpdoc' and 'single_blank_line_before_namespace'
## Bug report

PHP 7.4.9, php-cs-fixer v2.16.4

When setting the `separate` option of `header_comment` to `both`, and configuring `no_blank_lines_after_phpdoc` and `single_blank_line_before_namespace` to both `true`, the latter two shows up when after `header_comment` did its job.

### Code snippet that reproduces the problem
1. First run, create a class with no header.
```php
<?php

namespace Foo;

class Bar
{
}
```
After the first run, the error show will be `header_comment`, which is expected.

2. Next run, create additions that will violate any other rules, e.g. `native_constant_invocation`.
```php
<?php

/**
 * An arbitrary file header
 */

namespace Foo;

class Bar
{
    public $separator = DIRECTORY_SEPARATOR;
}
```
After this run, errors shown would be `native_constant_invocation`, `no_blank_lines_after_phpdoc`, and `single_blank_line_before_namespace`.

Pull request description:
NoBlankLinesAfterPhpdoc - Add T_NAMESPACE in array of forbidden successors
Fixes #5111 

When used, `no_blank_lines_after_phpdoc` removes the whitespace between the file-level doc-block and the namespace declaration. This should not be the case as namespaces are not considered structural elements that can be documented with doc-blocks. Besides, the file-level doc-block belongs to the file and NOT on the namespace.

See more: https://docs.phpdoc.org/3.0/guide/getting-started/what-is-a-docblock.html

Patch:
diff --git a/src/Fixer/NamespaceNotation/SingleBlankLineBeforeNamespaceFixer.php b/src/Fixer/NamespaceNotation/SingleBlankLineBeforeNamespaceFixer.php
index 4b0a9a7a5..b9180f7a0 100644
--- a/src/Fixer/NamespaceNotation/SingleBlankLineBeforeNamespaceFixer.php
+++ b/src/Fixer/NamespaceNotation/SingleBlankLineBeforeNamespaceFixer.php
@@ -46,8 +46,6 @@ public function isCandidate(Tokens $tokens)
 
     /**
      * {@inheritdoc}
-     *
-     * Must run after NoBlankLinesAfterPhpdocFixer.
      */
     public function getPriority()
     {
diff --git a/src/Fixer/Phpdoc/NoBlankLinesAfterPhpdocFixer.php b/src/Fixer/Phpdoc/NoBlankLinesAfterPhpdocFixer.php
index 4bb68efb5..ddb146ff6 100644
--- a/src/Fixer/Phpdoc/NoBlankLinesAfterPhpdocFixer.php
+++ b/src/Fixer/Phpdoc/NoBlankLinesAfterPhpdocFixer.php
@@ -57,7 +57,7 @@ class Bar {}
     /**
      * {@inheritdoc}
      *
-     * Must run before HeaderCommentFixer, PhpdocAlignFixer, SingleBlankLineBeforeNamespaceFixer.
+     * Must run before HeaderCommentFixer, PhpdocAlignFixer.
      * Must run after AlignMultilineCommentFixer, CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer.
      */
     public function getPriority()
@@ -71,16 +71,17 @@ public function getPriority()
     protected function applyFix(\SplFileInfo $file, Tokens $tokens)
     {
         static $forbiddenSuccessors = [
-            T_DOC_COMMENT,
+            T_BREAK,
             T_COMMENT,
-            T_WHITESPACE,
-            T_RETURN,
-            T_THROW,
-            T_GOTO,
             T_CONTINUE,
-            T_BREAK,
             T_DECLARE,
+            T_DOC_COMMENT,
+            T_GOTO,
+            T_NAMESPACE,
+            T_RETURN,
+            T_THROW,
             T_USE,
+            T_WHITESPACE,
         ];
 
         foreach ($tokens as $index => $token) {


Test patch:
diff --git a/tests/AutoReview/FixerFactoryTest.php b/tests/AutoReview/FixerFactoryTest.php
index af24a830a..ceb4c383a 100644
--- a/tests/AutoReview/FixerFactoryTest.php
+++ b/tests/AutoReview/FixerFactoryTest.php
@@ -141,7 +141,6 @@ public function provideFixersPriorityCases()
             [$fixers['no_alternative_syntax'], $fixers['no_useless_else']],
             [$fixers['no_alternative_syntax'], $fixers['switch_continue_to_break']],
             [$fixers['no_blank_lines_after_phpdoc'], $fixers['header_comment']],
-            [$fixers['no_blank_lines_after_phpdoc'], $fixers['single_blank_line_before_namespace']],
             [$fixers['no_empty_comment'], $fixers['no_extra_blank_lines']],
             [$fixers['no_empty_comment'], $fixers['no_trailing_whitespace']],
             [$fixers['no_empty_comment'], $fixers['no_whitespace_in_blank_line']],
diff --git a/tests/Fixer/Phpdoc/NoBlankLinesAfterPhpdocFixerTest.php b/tests/Fixer/Phpdoc/NoBlankLinesAfterPhpdocFixerTest.php
index c73c63c5b..2a52c26f5 100644
--- a/tests/Fixer/Phpdoc/NoBlankLinesAfterPhpdocFixerTest.php
+++ b/tests/Fixer/Phpdoc/NoBlankLinesAfterPhpdocFixerTest.php
@@ -287,6 +287,22 @@ public function testFixesOthers()
         $this->doTest($expected, $input);
     }
 
+    public function testWhitespaceInDocBlockAboveNamespaceIsNotTouched()
+    {
+        $expected = <<<'EOF'
+<?php
+
+/**
+ * This is a file-level docblock.
+ */
+
+namespace Foo\Bar\Baz;
+
+EOF;
+
+        $this->doTest($expected);
+    }
+
     public function testFixesWindowsStyle()
     {
         $expected = "<?php\r\n    /**     * Constant!     */\n    \$foo = 123;";