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

Issue:
Wrong comment style in php 8.1 enums with phpdoc_to_comment rule
## Bug report

   * PHP version: 8.1.1
   * PHP CS Fixer version: 3.4.0
   * the command used to run PHP CS Fixer (run with `-vvv`):  
     * `vendor/bin/php-cs-fixer fix --dry-run --diff --show-progress=dots --allow-risky=yes`
   * the configuration (file)
```php
$finder = PhpCsFixer\Finder::create();
return (new PhpCsFixer\Config())
    ->setRules([
        '@PSR12' => true,
        '@PSR12:risky' => true,
        '@DoctrineAnnotation' => true,
        '@PHP74Migration' => true,
        '@PHP74Migration:risky' => true,
        '@PhpCsFixer' => true,
        '@PhpCsFixer:risky' => true,

        'fopen_flags' => [
            'b_mode' => true,
        ],

        'array_syntax' => [
            'syntax' => 'short',
        ],
        'yoda_style' => [
            'equal' => false,
            'identical' => false,
            'less_and_greater' => false,
        ],
        'increment_style' => [
            'style' => 'post',
        ],

        'cast_spaces' => [
            'space' => 'none',
        ],
        'concat_space' => [
            'spacing' => 'one',
        ],

        'multiline_whitespace_before_semicolons' => [
            'strategy' => 'no_multi_line',
        ],
        'method_chaining_indentation' => false,
        'method_argument_space' => false,
        'no_space_around_double_colon' => false,

        'class_definition' => [
            'multi_line_extends_each_single_line' => true,
        ],

        'single_line_throw' => false,
        'static_lambda' => true,
        'return_assignment' => false,
        'no_unset_on_property' => false,

        'no_superfluous_phpdoc_tags' => [
            'allow_mixed' => true,
            'remove_inheritdoc' => true,
        ],
        'phpdoc_to_comment' => [
            'ignored_tags' => [
                'psalm-suppress',
            ]
        ],
        'phpdoc_no_alias_tag' => [
            'replacements' => [],
        ],
        'phpdoc_add_missing_param_annotation' => false,
        'phpdoc_separation' => false,
        'phpdoc_align' => [
            'align' => 'left',
        ],

        'php_unit_strict' => false,
        'php_unit_test_case_static_method_calls' => [
            'call_type' => 'this',
        ],
    ])
    ->setFinder($finder);
```
-->

### Code snippet that reproduces the problem
Input:
```php
<?php
/**
 * Comment
 */
enum SomeEnum: string
{
    /**
     * Comment
     */
    case Name1 = 'name1';

    /**
     * Comment
     */
    case Name2 = 'name2';

    public function foo(): void
    {
    }
}
```

Output (`phpdoc_to_comment`, `no_extra_blank_lines`, `single_line_comment_style`):
```php
<?php
// Comment
enum SomeEnum: string
{
    // Comment
    case Name1 = 'name1';
    // Comment
    case Name2 = 'name2';
    public function foo(): void
    {
    }
}
```

PhpdocToCommentFixer false positives with enums
## Bug report

### Description

I have an enum type and want to deprecate some of the cases.

PhpdocToCommentFixer however wants to change these docblocks to regular comments.

### Runtime version

v3.16.0

### Used command

I'm using php-cs-fixer through symplify/easy-coding-standard so this is irrelevant.

### Configuration file

I'm using php-cs-fixer through symplify/easy-coding-standard so this is irrelevant.

### Code snippet that reproduces the problem

```php
enum MyEnum: string
{
    case A = 'a';

    case B = 'b';

    /**
     * @deprecated use D instead
     */
    case C = 'c';

    case D = 'd';
}
```



Discussion:
This also happens with code like this
```php
<?php
enum SomeEnum: string
{
    case ONE = 'one';

    /**
     * @return void
     */
    public function foo()
    {
    }
}
```
which (without the _phpdoc to comment_ rule) results in the removal of the newline between the case and the doc block.
It also happens with PHP attributes on enum cases, for which blank lines are removed between cases:


```php
enum Suit implements ReadableEnumInterface
{
    #[EnumCase('suit.hearts')]
    case Hearts = 'H';

    #[EnumCase('suit.diamonds')]
    case Diamonds = 'D';

    #[EnumCase('suit.clubs')]
    case Clubs = 'C';

    #[EnumCase('suit.spades')]
    case Spades = 'S';
}
```

```php
enum Suit implements ReadableEnumInterface
{
    #[EnumCase('suit.hearts')]
    case Hearts = 'H';
    #[EnumCase('suit.diamonds')]
    case Diamonds = 'D';
    #[EnumCase('suit.clubs')]
    case Clubs = 'C';
    #[EnumCase('suit.spades')]
    case Spades = 'S';
}
```
In my case the double asterix is chopped of. Annoying as it means the annotation is not recognized any more :/

From:
```php
/**
 * @OA\Schema
 */
enum StockLevel: int
{
    case AVAILABLE = 1;
    case SOLD_OUT = 2;
    case BACK_ORDER = 3;
}
```

to:
```php
/*
 * @OA\Schema
 */
enum StockLevel: int
{
    case AVAILABLE = 1;
    case SOLD_OUT = 2;
    case BACK_ORDER = 3;
}
```
Hello @SpacePossum  
This rule still change docblock to `//` on case elements in enum
In my case the second asterisk 

```php
enum MembershipStatus: string
{
    /** Example doc summary */
    case Invalid = 'invalid';
}
```

is still removed

```php
enum MembershipStatus: string
{
    /* Example doc summary */
    case Invalid = 'invalid';
}
```

Used rules:

    {
        "@Symfony": true,
        "phpdoc_separation": false,
        "phpdoc_summary": false
    }

Sorry for the noise, I won't use issues' references in commit messages again 😆.



Patch:
diff --git a/src/Tokenizer/Analyzer/CommentsAnalyzer.php b/src/Tokenizer/Analyzer/CommentsAnalyzer.php
index 2228a24ae5e..d00a97d5474 100644
--- a/src/Tokenizer/Analyzer/CommentsAnalyzer.php
+++ b/src/Tokenizer/Analyzer/CommentsAnalyzer.php
@@ -194,6 +194,12 @@ private function isStructuralElement(Tokens $tokens, int $index): bool
             return true;
         }
 
+        if ($token->isGivenKind(T_CASE) && \defined('T_ENUM')) {
+            $caseParent = $tokens->getPrevTokenOfKind($index, [[T_ENUM], [T_SWITCH]]);
+
+            return $tokens[$caseParent]->isGivenKind([T_ENUM]);
+        }
+
         if ($token->isGivenKind(T_STATIC)) {
             return !$tokens[$tokens->getNextMeaningfulToken($index)]->isGivenKind(T_DOUBLE_COLON);
         }


Test patch:
diff --git a/tests/Fixer/Phpdoc/PhpdocToCommentFixerTest.php b/tests/Fixer/Phpdoc/PhpdocToCommentFixerTest.php
index 39b55ccdf84..da736c42c44 100644
--- a/tests/Fixer/Phpdoc/PhpdocToCommentFixerTest.php
+++ b/tests/Fixer/Phpdoc/PhpdocToCommentFixerTest.php
@@ -898,5 +898,17 @@ enum Foo {
     //
 }',
         ];
+
+        yield 'phpDoc over enum case' => [
+            '<?php
+enum Foo: int
+{
+    /**
+     * @deprecated do not convert this
+     */
+    case BAR = 1;
+}
+',
+        ];
     }
 }
diff --git a/tests/Tokenizer/Analyzer/CommentsAnalyzerTest.php b/tests/Tokenizer/Analyzer/CommentsAnalyzerTest.php
index efd1706360a..6e26c815844 100644
--- a/tests/Tokenizer/Analyzer/CommentsAnalyzerTest.php
+++ b/tests/Tokenizer/Analyzer/CommentsAnalyzerTest.php
@@ -310,15 +310,15 @@ public function testPhpdocCandidatePhp80(string $code): void
         self::assertTrue($analyzer->isBeforeStructuralElement($tokens, $index));
     }
 
-    public static function providePhpdocCandidatePhp80Cases(): array
+    public static function providePhpdocCandidatePhp80Cases(): iterable
     {
-        return [
-            ['<?php
+        yield 'attribute between class and phpDoc' => [
+            '<?php
 /**
  * @Annotation
  */
 #[CustomAnnotationA]
-Class MyAnnotation3 {}'],
+Class MyAnnotation3 {}',
         ];
     }
 
@@ -369,6 +369,16 @@ public static function providePhpdocCandidatePhp81Cases(): iterable
         yield 'enum' => [
             '<?php /* Before enum */ enum Foo {}',
         ];
+
+        yield 'enum with deprecated case' => [
+            '<?php
+enum Foo: int {
+    /**
+     * @deprecated Lorem ipsum
+     */
+    case BAR = 1;
+}',
+        ];
     }
 
     /**