Browse Source

Merge branch 'master' into 3.0

* master:
  fix test
  Fix test
  Fix tests
  PHP8.0
  Always lint test cases with the stricter process linter
  Enhancement: Handle new static() in final class
  Corrected linting error messages

# Conflicts:
#	phpunit.xml.dist
#	tests/Test/AbstractFixerTestCase.php
#	tests/Test/AbstractIntegrationTestCase.php
SpacePossum 4 years ago
parent
commit
9d77ec272d

+ 1 - 0
.appveyor.yml

@@ -6,6 +6,7 @@ clone_folder: C:\projects\php-cs-fixer
 environment:
 environment:
     matrix:
     matrix:
         - php_ver: 7.3.1
         - php_ver: 7.3.1
+          FAST_LINT_TEST_CASES: 1
         - php_ver: 5.6.40
         - php_ver: 5.6.40
 
 
 cache:
 cache:

+ 15 - 15
README.rst

@@ -408,7 +408,7 @@ Choose from the list of available rules:
 
 
   Calling ``unset`` on multiple items should be done in one call.
   Calling ``unset`` on multiple items should be done in one call.
 
 
-* **combine_nested_dirname** [@Symfony:risky, @PhpCsFixer:risky, @PHP70Migration:risky, @PHP71Migration:risky, @PHP74Migration:risky, @PHP8Migration:risky]
+* **combine_nested_dirname** [@Symfony:risky, @PhpCsFixer:risky, @PHP70Migration:risky, @PHP71Migration:risky, @PHP74Migration:risky, @PHP80Migration:risky]
 
 
   Replace multiple nested calls of ``dirname`` by only one call with second
   Replace multiple nested calls of ``dirname`` by only one call with second
   ``$level`` parameter. Requires PHP >= 7.0.
   ``$level`` parameter. Requires PHP >= 7.0.
@@ -465,7 +465,7 @@ Choose from the list of available rules:
   - ``space`` (``'none'``, ``'single'``): spacing to apply around the equal sign;
   - ``space`` (``'none'``, ``'single'``): spacing to apply around the equal sign;
     defaults to ``'none'``
     defaults to ``'none'``
 
 
-* **declare_strict_types** [@PHP70Migration:risky, @PHP71Migration:risky, @PHP74Migration:risky, @PHP8Migration:risky]
+* **declare_strict_types** [@PHP70Migration:risky, @PHP71Migration:risky, @PHP74Migration:risky, @PHP80Migration:risky]
 
 
   Force strict types declaration in all files. Requires PHP >= 7.0.
   Force strict types declaration in all files. Requires PHP >= 7.0.
 
 
@@ -821,7 +821,7 @@ Choose from the list of available rules:
   - ``separate`` (``'both'``, ``'bottom'``, ``'none'``, ``'top'``): whether the header should be
   - ``separate`` (``'both'``, ``'bottom'``, ``'none'``, ``'top'``): whether the header should be
     separated from the file content with a new line; defaults to ``'both'``
     separated from the file content with a new line; defaults to ``'both'``
 
 
-* **heredoc_indentation** [@PHP73Migration, @PHP74Migration, @PHP8Migration]
+* **heredoc_indentation** [@PHP73Migration, @PHP74Migration, @PHP80Migration]
 
 
   Heredoc/nowdoc content must be properly indented. Requires PHP >= 7.3.
   Heredoc/nowdoc content must be properly indented. Requires PHP >= 7.3.
 
 
@@ -835,7 +835,7 @@ Choose from the list of available rules:
 
 
   Convert ``heredoc`` to ``nowdoc`` where possible.
   Convert ``heredoc`` to ``nowdoc`` where possible.
 
 
-* **implode_call** [@Symfony:risky, @PhpCsFixer:risky, @PHP74Migration:risky, @PHP8Migration:risky]
+* **implode_call** [@Symfony:risky, @PhpCsFixer:risky, @PHP74Migration:risky, @PHP80Migration:risky]
 
 
   Function ``implode`` must be called with 2 arguments in the documented
   Function ``implode`` must be called with 2 arguments in the documented
   order.
   order.
@@ -1023,7 +1023,7 @@ Choose from the list of available rules:
 
 
   All instances created with new keyword must be followed by braces.
   All instances created with new keyword must be followed by braces.
 
 
-* **no_alias_functions** [@Symfony:risky, @PhpCsFixer:risky, @PHP74Migration:risky, @PHP8Migration:risky]
+* **no_alias_functions** [@Symfony:risky, @PhpCsFixer:risky, @PHP74Migration:risky, @PHP80Migration:risky]
 
 
   Master functions shall be used instead of aliases.
   Master functions shall be used instead of aliases.
 
 
@@ -1224,7 +1224,7 @@ Choose from the list of available rules:
   - ``namespaces`` (``bool``): remove unneeded curly braces from bracketed
   - ``namespaces`` (``bool``): remove unneeded curly braces from bracketed
     namespaces; defaults to ``false``
     namespaces; defaults to ``false``
 
 
-* **no_unneeded_final_method** [@Symfony:risky, @PhpCsFixer:risky, @PHP8Migration:risky]
+* **no_unneeded_final_method** [@Symfony:risky, @PhpCsFixer:risky, @PHP80Migration:risky]
 
 
   A ``final`` class must not have ``final`` methods and ``private`` methods must
   A ``final`` class must not have ``final`` methods and ``private`` methods must
   not be ``final``.
   not be ``final``.
@@ -1243,7 +1243,7 @@ Choose from the list of available rules:
 
 
   *Risky rule: modifies the signature of functions; therefore risky when using systems (such as some Symfony components) that rely on those (for example through reflection).*
   *Risky rule: modifies the signature of functions; therefore risky when using systems (such as some Symfony components) that rely on those (for example through reflection).*
 
 
-* **no_unset_cast** [@Symfony, @PhpCsFixer, @PHP8Migration]
+* **no_unset_cast** [@Symfony, @PhpCsFixer, @PHP80Migration]
 
 
   Variables must be set ``null`` instead of using ``(unset)`` casting.
   Variables must be set ``null`` instead of using ``(unset)`` casting.
 
 
@@ -1279,7 +1279,7 @@ Choose from the list of available rules:
 
 
   Remove trailing whitespace at the end of blank lines.
   Remove trailing whitespace at the end of blank lines.
 
 
-* **non_printable_character** [@Symfony:risky, @PhpCsFixer:risky, @PHP70Migration:risky, @PHP71Migration:risky, @PHP74Migration:risky, @PHP8Migration:risky]
+* **non_printable_character** [@Symfony:risky, @PhpCsFixer:risky, @PHP70Migration:risky, @PHP71Migration:risky, @PHP74Migration:risky, @PHP80Migration:risky]
 
 
   Remove Zero-width space (ZWSP), Non-breaking space (NBSP) and other
   Remove Zero-width space (ZWSP), Non-breaking space (NBSP) and other
   invisible unicode symbols.
   invisible unicode symbols.
@@ -1291,7 +1291,7 @@ Choose from the list of available rules:
   - ``use_escape_sequences_in_strings`` (``bool``): whether characters should be
   - ``use_escape_sequences_in_strings`` (``bool``): whether characters should be
     replaced with escape sequences in strings; defaults to ``false``
     replaced with escape sequences in strings; defaults to ``false``
 
 
-* **normalize_index_brace** [@Symfony, @PhpCsFixer, @PHP74Migration, @PHP8Migration]
+* **normalize_index_brace** [@Symfony, @PhpCsFixer, @PHP74Migration, @PHP80Migration]
 
 
   Array index should always be written by using square braces.
   Array index should always be written by using square braces.
 
 
@@ -1794,7 +1794,7 @@ Choose from the list of available rules:
   ``@var`` and ``@type`` annotations of classy properties should not contain
   ``@var`` and ``@type`` annotations of classy properties should not contain
   the name.
   the name.
 
 
-* **pow_to_exponentiation** [@Symfony:risky, @PhpCsFixer:risky, @PHP56Migration:risky, @PHP70Migration:risky, @PHP71Migration:risky, @PHP74Migration:risky, @PHP8Migration:risky]
+* **pow_to_exponentiation** [@Symfony:risky, @PhpCsFixer:risky, @PHP56Migration:risky, @PHP70Migration:risky, @PHP71Migration:risky, @PHP74Migration:risky, @PHP80Migration:risky]
 
 
   Converts ``pow`` to the ``**`` operator.
   Converts ``pow`` to the ``**`` operator.
 
 
@@ -1836,7 +1836,7 @@ Choose from the list of available rules:
   - ``dir`` (``null``, ``string``): if provided, the directory where the project code is
   - ``dir`` (``null``, ``string``): if provided, the directory where the project code is
     placed; defaults to ``null``
     placed; defaults to ``null``
 
 
-* **random_api_migration** [@PHP70Migration:risky, @PHP71Migration:risky, @PHP74Migration:risky, @PHP8Migration:risky]
+* **random_api_migration** [@PHP70Migration:risky, @PHP71Migration:risky, @PHP74Migration:risky, @PHP80Migration:risky]
 
 
   Replaces ``rand``, ``srand``, ``getrandmax`` functions calls with their ``mt_*``
   Replaces ``rand``, ``srand``, ``getrandmax`` functions calls with their ``mt_*``
   analogs.
   analogs.
@@ -2016,7 +2016,7 @@ Choose from the list of available rules:
 
 
   Removes extra spaces between colon and case value.
   Removes extra spaces between colon and case value.
 
 
-* **switch_continue_to_break** [@Symfony, @PhpCsFixer, @PHP73Migration, @PHP74Migration, @PHP8Migration]
+* **switch_continue_to_break** [@Symfony, @PhpCsFixer, @PHP73Migration, @PHP74Migration, @PHP80Migration]
 
 
   Switch case must not be ended with ``continue`` but with ``break``.
   Switch case must not be ended with ``continue`` but with ``break``.
 
 
@@ -2030,7 +2030,7 @@ Choose from the list of available rules:
 
 
   *Risky rule: risky when relying on functions called on both sides of the ``?`` operator.*
   *Risky rule: risky when relying on functions called on both sides of the ``?`` operator.*
 
 
-* **ternary_to_null_coalescing** [@PHP70Migration, @PHP71Migration, @PHP73Migration, @PHP74Migration, @PHP8Migration]
+* **ternary_to_null_coalescing** [@PHP70Migration, @PHP71Migration, @PHP73Migration, @PHP74Migration, @PHP80Migration]
 
 
   Use ``null`` coalescing operator ``??`` where possible. Requires PHP >= 7.0.
   Use ``null`` coalescing operator ``??`` where possible. Requires PHP >= 7.0.
 
 
@@ -2059,7 +2059,7 @@ Choose from the list of available rules:
 
 
   *Risky rule: risky when using ``isset()`` on outside variables that are not imported with ``use ()``.*
   *Risky rule: risky when using ``isset()`` on outside variables that are not imported with ``use ()``.*
 
 
-* **visibility_required** [@PSR2, @Symfony, @PhpCsFixer, @PHP71Migration, @PHP73Migration, @PHP74Migration, @PHP8Migration]
+* **visibility_required** [@PSR2, @Symfony, @PhpCsFixer, @PHP71Migration, @PHP73Migration, @PHP74Migration, @PHP80Migration]
 
 
   Visibility MUST be declared on all properties and methods; ``abstract``
   Visibility MUST be declared on all properties and methods; ``abstract``
   and ``final`` MUST be declared before the visibility; ``static`` MUST be
   and ``final`` MUST be declared before the visibility; ``static`` MUST be
@@ -2071,7 +2071,7 @@ Choose from the list of available rules:
     elements to fix (PHP >= 7.1 required for ``const``); defaults to
     elements to fix (PHP >= 7.1 required for ``const``); defaults to
     ``['property', 'method']``
     ``['property', 'method']``
 
 
-* **void_return** [@PHP71Migration:risky, @PHP74Migration:risky, @PHP8Migration:risky]
+* **void_return** [@PHP71Migration:risky, @PHP74Migration:risky, @PHP80Migration:risky]
 
 
   Add ``void`` return type to functions with missing or empty return
   Add ``void`` return type to functions with missing or empty return
   statements, but priority is given to ``@return`` annotations. Requires
   statements, but priority is given to ``@return`` annotations. Requires

+ 1 - 0
phpunit.xml.dist

@@ -53,6 +53,7 @@
     <php>
     <php>
         <ini name="zend.enable_gc" value="0"/>
         <ini name="zend.enable_gc" value="0"/>
         <ini name="memory_limit" value="1G"/>
         <ini name="memory_limit" value="1G"/>
+        <env name="FAST_LINT_TEST_CASES" value="0"/>
         <env name="PHP_CS_FIXER_TEST_ALLOW_SKIPPING_SMOKE_TESTS" value="1"/>
         <env name="PHP_CS_FIXER_TEST_ALLOW_SKIPPING_SMOKE_TESTS" value="1"/>
     </php>
     </php>
 </phpunit>
 </phpunit>

+ 15 - 4
src/Fixer/Casing/NativeFunctionTypeDeclarationCasingFixer.php

@@ -40,6 +40,7 @@ final class NativeFunctionTypeDeclarationCasingFixer extends AbstractFixer
      * iterable PHP 7.1.0
      * iterable PHP 7.1.0
      * void     PHP 7.1.0
      * void     PHP 7.1.0
      * object   PHP 7.2.0
      * object   PHP 7.2.0
+     * static   PHP 8.0.0 (return type only)
      *
      *
      * @var array<string, true>
      * @var array<string, true>
      */
      */
@@ -86,6 +87,10 @@ final class NativeFunctionTypeDeclarationCasingFixer extends AbstractFixer
             $this->hints = array_merge($this->hints, ['object' => true]);
             $this->hints = array_merge($this->hints, ['object' => true]);
         }
         }
 
 
+        if (\PHP_VERSION_ID >= 80000) {
+            $this->hints = array_merge($this->hints, ['static' => true]);
+        }
+
         $this->functionsAnalyzer = new FunctionsAnalyzer();
         $this->functionsAnalyzer = new FunctionsAnalyzer();
     }
     }
 
 
@@ -162,16 +167,22 @@ final class NativeFunctionTypeDeclarationCasingFixer extends AbstractFixer
             return;
             return;
         }
         }
 
 
-        $argumentIndex = $type->getStartIndex();
-        if ($argumentIndex !== $type->getEndIndex()) {
-            return; // the type to fix are always unqualified and so are always composed as one token
+        $argumentStartIndex = $type->getStartIndex();
+        $argumentExpectedEndIndex = $type->isNullable()
+            ? $tokens->getNextMeaningfulToken($argumentStartIndex)
+            : $argumentStartIndex
+        ;
+
+        if ($argumentExpectedEndIndex !== $type->getEndIndex()) {
+            return; // the type to fix is always unqualified and so is always composed of one token and possible a nullable '?' one
         }
         }
 
 
         $lowerCasedName = strtolower($type->getName());
         $lowerCasedName = strtolower($type->getName());
+
         if (!isset($this->hints[$lowerCasedName])) {
         if (!isset($this->hints[$lowerCasedName])) {
             return; // check of type is of interest based on name (slower check than previous index based)
             return; // check of type is of interest based on name (slower check than previous index based)
         }
         }
 
 
-        $tokens[$argumentIndex] = new Token([$tokens[$argumentIndex]->getId(), $lowerCasedName]);
+        $tokens[$argumentExpectedEndIndex] = new Token([$tokens[$argumentExpectedEndIndex]->getId(), $lowerCasedName]);
     }
     }
 }
 }

+ 34 - 8
src/Fixer/FunctionNotation/PhpdocToReturnTypeFixer.php

@@ -120,6 +120,19 @@ function bar() {}
                     new VersionSpecification(70100),
                     new VersionSpecification(70100),
                     ['scalar_types' => false]
                     ['scalar_types' => false]
                 ),
                 ),
+                new VersionSpecificCodeSample(
+                    '<?php
+final class Foo {
+    /**
+     * @return static
+     */
+    public function create($prototype) {
+        return new static($prototype);
+    }
+}
+',
+                    new VersionSpecification(80000)
+                ),
             ],
             ],
             null,
             null,
             'This rule is EXPERIMENTAL and [1] is not covered with backward compatibility promise. [2] `@return` annotation is mandatory for the fixer to make changes, signatures of methods without it (no docblock, inheritdocs) will not be fixed. [3] Manual actions are required if inherited signatures are not properly documented. [4] `@inheritdocs` support is under construction.'
             'This rule is EXPERIMENTAL and [1] is not covered with backward compatibility promise. [2] `@return` annotation is mandatory for the fixer to make changes, signatures of methods without it (no docblock, inheritdocs) will not be fixed. [3] Manual actions are required if inherited signatures are not properly documented. [4] `@inheritdocs` support is under construction.'
@@ -184,11 +197,13 @@ function bar() {}
             }
             }
 
 
             $funcName = $tokens->getNextMeaningfulToken($index);
             $funcName = $tokens->getNextMeaningfulToken($index);
+
             if ($tokens[$funcName]->equalsAny($this->excludeFuncNames, false)) {
             if ($tokens[$funcName]->equalsAny($this->excludeFuncNames, false)) {
                 continue;
                 continue;
             }
             }
 
 
             $returnTypeAnnotation = $this->findReturnAnnotations($tokens, $index);
             $returnTypeAnnotation = $this->findReturnAnnotations($tokens, $index);
+
             if (1 !== \count($returnTypeAnnotation)) {
             if (1 !== \count($returnTypeAnnotation)) {
                 continue;
                 continue;
             }
             }
@@ -228,7 +243,7 @@ function bar() {}
             }
             }
 
 
             if ('static' === $returnType) {
             if ('static' === $returnType) {
-                $returnType = 'self';
+                $returnType = \PHP_VERSION_ID < 80000 ? 'self' : 'static';
             }
             }
 
 
             if (isset($this->skippedTypes[$returnType])) {
             if (isset($this->skippedTypes[$returnType])) {
@@ -294,11 +309,14 @@ function bar() {}
         static $specialTypes = [
         static $specialTypes = [
             'array' => [CT::T_ARRAY_TYPEHINT, 'array'],
             'array' => [CT::T_ARRAY_TYPEHINT, 'array'],
             'callable' => [T_CALLABLE, 'callable'],
             'callable' => [T_CALLABLE, 'callable'],
+            'static' => [T_STATIC, 'static'],
         ];
         ];
+
         $newTokens = [
         $newTokens = [
             new Token([CT::T_TYPE_COLON, ':']),
             new Token([CT::T_TYPE_COLON, ':']),
             new Token([T_WHITESPACE, ' ']),
             new Token([T_WHITESPACE, ' ']),
         ];
         ];
+
         if (true === $isNullable) {
         if (true === $isNullable) {
             $newTokens[] = new Token([CT::T_NULLABLE_TYPE, '?']);
             $newTokens[] = new Token([CT::T_NULLABLE_TYPE, '?']);
         }
         }
@@ -306,15 +324,23 @@ function bar() {}
         if (isset($specialTypes[$returnType])) {
         if (isset($specialTypes[$returnType])) {
             $newTokens[] = new Token($specialTypes[$returnType]);
             $newTokens[] = new Token($specialTypes[$returnType]);
         } else {
         } else {
-            foreach (explode('\\', $returnType) as $nsIndex => $value) {
-                if (0 === $nsIndex && '' === $value) {
-                    continue;
-                }
+            $returnTypeUnqualified = ltrim($returnType, '\\');
+
+            if (isset($this->scalarTypes[$returnTypeUnqualified]) || isset($this->versionSpecificTypes[$returnTypeUnqualified])) {
+                // 'scalar's, 'void', 'iterable' and 'object' must be unqualified
+                $newTokens[] = new Token([T_STRING, $returnTypeUnqualified]);
+            } else {
+                foreach (explode('\\', $returnType) as $nsIndex => $value) {
+                    if (0 === $nsIndex && '' === $value) {
+                        continue;
+                    }
+
+                    if (0 < $nsIndex) {
+                        $newTokens[] = new Token([T_NS_SEPARATOR, '\\']);
+                    }
 
 
-                if (0 < $nsIndex) {
-                    $newTokens[] = new Token([T_NS_SEPARATOR, '\\']);
+                    $newTokens[] = new Token([T_STRING, $value]);
                 }
                 }
-                $newTokens[] = new Token([T_STRING, $value]);
             }
             }
         }
         }
 
 

+ 2 - 2
src/Linter/ProcessLinter.php

@@ -96,7 +96,7 @@ final class ProcessLinter implements LinterInterface
      */
      */
     public function lintFile($path)
     public function lintFile($path)
     {
     {
-        return new ProcessLintingResult($this->createProcessForFile($path));
+        return new ProcessLintingResult($this->createProcessForFile($path), $path);
     }
     }
 
 
     /**
     /**
@@ -104,7 +104,7 @@ final class ProcessLinter implements LinterInterface
      */
      */
     public function lintSource($source)
     public function lintSource($source)
     {
     {
-        return new ProcessLintingResult($this->createProcessForSource($source));
+        return new ProcessLintingResult($this->createProcessForSource($source), $this->temporaryFile);
     }
     }
 
 
     /**
     /**

+ 41 - 2
src/Linter/ProcessLintingResult.php

@@ -31,9 +31,18 @@ final class ProcessLintingResult implements LintingResultInterface
      */
      */
     private $process;
     private $process;
 
 
-    public function __construct(Process $process)
+    /**
+     * @var null|string
+     */
+    private $path;
+
+    /**
+     * @param null|string $path
+     */
+    public function __construct(Process $process, $path = null)
     {
     {
         $this->process = $process;
         $this->process = $process;
+        $this->path = $path;
     }
     }
 
 
     /**
     /**
@@ -43,8 +52,38 @@ final class ProcessLintingResult implements LintingResultInterface
     {
     {
         if (!$this->isSuccessful()) {
         if (!$this->isSuccessful()) {
             // on some systems stderr is used, but on others, it's not
             // on some systems stderr is used, but on others, it's not
-            throw new LintingException($this->process->getErrorOutput() ?: $this->process->getOutput(), $this->process->getExitCode());
+            throw new LintingException($this->getProcessErrorMessage(), $this->process->getExitCode());
+        }
+    }
+
+    private function getProcessErrorMessage()
+    {
+        $output = strtok(ltrim($this->process->getErrorOutput() ?: $this->process->getOutput()), "\n");
+
+        if (false === $output) {
+            return 'Fatal error: Unable to lint file.';
         }
         }
+
+        if (null !== $this->path) {
+            $needle = sprintf('in %s ', $this->path);
+            $pos = strrpos($output, $needle);
+
+            if (false !== $pos) {
+                $output = sprintf('%s%s', substr($output, 0, $pos), substr($output, $pos + \strlen($needle)));
+            }
+        }
+
+        $prefix = substr($output, 0, 18);
+
+        if ('PHP Parse error:  ' === $prefix) {
+            return sprintf('Parse error: %s.', substr($output, 18));
+        }
+
+        if ('PHP Fatal error:  ' === $prefix) {
+            return sprintf('Fatal error: %s.', substr($output, 18));
+        }
+
+        return sprintf('%s.', $output);
     }
     }
 
 
     private function isSuccessful()
     private function isSuccessful()

+ 1 - 1
src/Linter/TokenizerLintingResult.php

@@ -45,6 +45,6 @@ final class TokenizerLintingResult implements LintingResultInterface
 
 
     private function getMessagePrefix()
     private function getMessagePrefix()
     {
     {
-        return \get_class($this->error);
+        return $this->error instanceof \ParseError ? 'Parse error' : 'Fatal error';
     }
     }
 }
 }

+ 2 - 2
src/RuleSet.php

@@ -384,12 +384,12 @@ final class RuleSet implements RuleSetInterface
             'no_alias_functions' => true,
             'no_alias_functions' => true,
             'use_arrow_functions' => true,
             'use_arrow_functions' => true,
         ],
         ],
-        '@PHP8Migration' => [
+        '@PHP80Migration' => [
             '@PHP73Migration' => true,
             '@PHP73Migration' => true,
             'no_unset_cast' => true,
             'no_unset_cast' => true,
             'normalize_index_brace' => true,
             'normalize_index_brace' => true,
         ],
         ],
-        '@PHP8Migration:risky' => [
+        '@PHP80Migration:risky' => [
             '@PHP71Migration:risky' => true,
             '@PHP71Migration:risky' => true,
             'implode_call' => true,
             'implode_call' => true,
             'no_alias_functions' => ['sets' => ['@all']],
             'no_alias_functions' => ['sets' => ['@all']],

+ 16 - 5
tests/Fixer/Alias/PowToExponentiationFixerTest.php

@@ -37,7 +37,7 @@ final class PowToExponentiationFixerTest extends AbstractFixerTestCase
 
 
     public function provideFixCases()
     public function provideFixCases()
     {
     {
-        return [
+        $tests = [
             [
             [
                 '<?php 1**2;',
                 '<?php 1**2;',
                 '<?php pow(1,2);',
                 '<?php pow(1,2);',
@@ -134,10 +134,6 @@ final class PowToExponentiationFixerTest extends AbstractFixerTestCase
                 '<?php echo ${$bar}** ${$foo};',
                 '<?php echo ${$bar}** ${$foo};',
                 '<?php echo pow(${$bar}, ${$foo});',
                 '<?php echo pow(${$bar}, ${$foo});',
             ],
             ],
-            [
-                '<?php echo $a{1}** $b{2+5};',
-                '<?php echo pow($a{1}, $b{2+5});',
-            ],
             [
             [
                 '<?php echo $a[2^3+1]->test(1,2)** $b[2+$c];',
                 '<?php echo $a[2^3+1]->test(1,2)** $b[2+$c];',
                 '<?php echo pow($a[2^3+1]->test(1,2), $b[2+$c]);',
                 '<?php echo pow($a[2^3+1]->test(1,2), $b[2+$c]);',
@@ -222,7 +218,22 @@ final class PowToExponentiationFixerTest extends AbstractFixerTestCase
                     public function &pow($a, $b);
                     public function &pow($a, $b);
                 }',
                 }',
             ],
             ],
+            [
+                '<?php echo $a[1]** $b[2+5];',
+                '<?php echo pow($a[1], $b[2+5]);',
+            ],
         ];
         ];
+
+        foreach ($tests as $index => $test) {
+            yield $index => $test;
+        }
+
+        if (\PHP_VERSION_ID < 80000) {
+            yield [
+                '<?php echo $a{1}** $b{2+5};',
+                '<?php echo pow($a{1}, $b{2+5});',
+            ];
+        }
     }
     }
 
 
     /**
     /**

Some files were not shown because too many files changed in this diff