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

Issue:
PHP Attributes should not be treated as comments
## Bug report

<!--
  Before reporting a bug, make sure PHP CS Fixer is up-to-date.

  Check that the issue is NOT regarded to an applied rule by using the `-vvv` option (will list applied rules) on a minimal code snippet.

  Please describe the problem and provide technical details such as:
   * PHP CS Fixer version and PHP runtime: php-cs-fixer -V
   * the command used to run PHP CS Fixer (run with `-vvv`)
   * the configuration (file) you used
-->

The `@return` declared by phpdoc is not considered to be the return value of the function.

```shell
# ./vendor/bin/php-cs-fixer -V
PHP CS Fixer 3.13.0 Oliva by Fabien Potencier and Dariusz Ruminski.
PHP runtime: 8.0.23
```

**config:**

```php
<?php

declare(strict_types=1);

return (new PhpCsFixer\Config())
    ->setRules([
        '@PHP74Migration'            => true,
        '@PHP74Migration:risky'      => true,
        '@Symfony'                   => true,
        '@Symfony:risky'             => true,
        '@DoctrineAnnotation'        => true,
    ])
    ->setRiskyAllowed(true)
;
```

### Code snippet that reproduces the problem

**code:**

```php
<?php

declare(strict_types=1);

/**
 * @return mixed|false
 */
#[\ReturnTypeWillChange]
function test()
{
    throw new \RuntimeException('gg');
}
```

**result:**

```shell
# ./vendor/bin/php-cs-fixer fix --dry-run --diff test.php 
Loaded config default from "/mnt/d/projects/test/.php-cs-fixer.php".
Using cache file ".php-cs-fixer.cache".
   1) test.php
      ---------- begin diff ----------
--- /mnt/d/projects/test/test.php
+++ /mnt/d/projects/test/test.php
@@ -6,7 +6,7 @@
  * @return mixed|false
  */
 #[\ReturnTypeWillChange]
-function test()
+function test(): void
 {
     throw new \RuntimeException('gg');
 }

      ----------- end diff -----------


Checked all files in 0.021 seconds, 14.000 MB memory used
```

<!--
  Provide a minimal code snippet before running PHP CS Fixer. If relevant,
  also provide the expected output, the actual output and/or the error that
  occurred, if any.

  Please use markdown syntax for each code snippet, e.g.:

  ```php
  <?php
  $var = 'foo';
  ```
-->



Discussion:

Patch:
diff --git a/src/Fixer/FunctionNotation/VoidReturnFixer.php b/src/Fixer/FunctionNotation/VoidReturnFixer.php
index 61d4a8ea534..5c2b2944fc1 100644
--- a/src/Fixer/FunctionNotation/VoidReturnFixer.php
+++ b/src/Fixer/FunctionNotation/VoidReturnFixer.php
@@ -236,16 +236,26 @@ private function fixFunctionDefinition(Tokens $tokens, int $index): void
      */
     private function findReturnAnnotations(Tokens $tokens, int $index): array
     {
-        do {
-            $index = $tokens->getPrevNonWhitespace($index);
-        } while ($tokens[$index]->isGivenKind([
+        $previousTokens = [
             T_ABSTRACT,
             T_FINAL,
             T_PRIVATE,
             T_PROTECTED,
             T_PUBLIC,
             T_STATIC,
-        ]));
+        ];
+
+        if (\defined('T_ATTRIBUTE')) { // @TODO: drop condition when PHP 8.0+ is required
+            $previousTokens[] = T_ATTRIBUTE;
+        }
+
+        do {
+            $index = $tokens->getPrevNonWhitespace($index);
+
+            if ($tokens[$index]->isGivenKind(CT::T_ATTRIBUTE_CLOSE)) {
+                $index = $tokens->getPrevTokenOfKind($index, [[T_ATTRIBUTE]]);
+            }
+        } while ($tokens[$index]->isGivenKind($previousTokens));
 
         if (!$tokens[$index]->isGivenKind(T_DOC_COMMENT)) {
             return [];


Test patch:
diff --git a/tests/Fixer/FunctionNotation/VoidReturnFixerTest.php b/tests/Fixer/FunctionNotation/VoidReturnFixerTest.php
index 61cf83667dd..f35384a9446 100644
--- a/tests/Fixer/FunctionNotation/VoidReturnFixerTest.php
+++ b/tests/Fixer/FunctionNotation/VoidReturnFixerTest.php
@@ -225,6 +225,55 @@ abstract protected function foo($param);
         ];
     }
 
+    /**
+     * @dataProvider provideFix80Cases
+     *
+     * @requires PHP 8.0
+     */
+    public function testFix80(string $expected, ?string $input = null): void
+    {
+        $this->doTest($expected, $input);
+    }
+
+    /**
+     * @return iterable<array<string>>
+     */
+    public static function provideFix80Cases(): iterable
+    {
+        yield [
+            '<?php
+
+            class Foo
+            {
+                /**
+                 * @return int|false
+                 */
+                #[\ReturnTypeWillChange]
+                public function test() {}
+            }
+            ',
+        ];
+
+        yield [
+            '<?php
+
+            /**
+             * @return void
+             */
+            #[\Deprecated]
+            function test(): void {};
+            ',
+            '<?php
+
+            /**
+             * @return void
+             */
+            #[\Deprecated]
+            function test() {};
+            ',
+        ];
+    }
+
     /**
      * Test if magic method is handled without causing syntax error.
      *