Browse Source

bug: NoUnusedImportsFixer - fix for splat operator (#6836)

Kuba Werłos 2 years ago
parent
commit
0b08635a8a

+ 10 - 4
src/Tokenizer/AbstractTypeTransformer.php

@@ -56,12 +56,18 @@ abstract class AbstractTypeTransformer extends AbstractTransformer
             return true;
         }
 
-        // for parameter there will be variable or reference after type
-        $variableIndex = $tokens->getTokenNotOfKindSibling($index, 1, self::TYPE_TOKENS);
-        if (!$tokens[$variableIndex]->isGivenKind(T_VARIABLE)) {
+        // for parameter there will be splat operator or variable after the type ("&" is ambiguous and can be reference or bitwise and)
+        $afterTypeIndex = $tokens->getTokenNotOfKindSibling($index, 1, self::TYPE_TOKENS);
+
+        if ($tokens[$afterTypeIndex]->isGivenKind(T_ELLIPSIS)) {
+            return true;
+        }
+
+        if (!$tokens[$afterTypeIndex]->isGivenKind(T_VARIABLE)) {
             return false;
         }
-        $beforeVariableIndex = $tokens->getPrevMeaningfulToken($variableIndex);
+
+        $beforeVariableIndex = $tokens->getPrevMeaningfulToken($afterTypeIndex);
         if ($tokens[$beforeVariableIndex]->equals('&')) {
             $prevIndex = $tokens->getPrevTokenOfKind($index, ['{', '}', ';', [T_FN], [T_FUNCTION]]);
 

+ 22 - 0
tests/Fixer/Import/NoUnusedImportsFixerTest.php

@@ -1515,5 +1515,27 @@ const D = new Foo7(1,2);
                 }
             ',
         ];
+
+        yield [
+            '<?php
+                use Foo\Class1;
+                use Foo\Class2;
+                class C
+                {
+                   public function t(Class1 | Class2 $fields) {}
+                }
+            ',
+        ];
+
+        yield [
+            '<?php
+                use Foo\Class1;
+                use Foo\Class2;
+                class C
+                {
+                   public function t(Class1 | Class2 ...$fields) {}
+                }
+            ',
+        ];
     }
 }

+ 13 - 0
tests/Tokenizer/Transformer/TypeAlternationTransformerTest.php

@@ -367,6 +367,19 @@ function f( #[Target(\'a\')] #[Target(\'b\')] #[Target(\'c\')] #[Target(\'d\')]
                 45 => CT::T_TYPE_ALTERNATION,
             ],
         ];
+
+        yield 'splat operator' => [
+            '<?php class Foo {
+                function f1(bool|int ... $x) {}
+                function f2(bool|int $x, TypeA|\Bar\Baz|TypeB ...$y) {}
+            }',
+            [
+                12 => CT::T_TYPE_ALTERNATION,
+                28 => CT::T_TYPE_ALTERNATION,
+                35 => CT::T_TYPE_ALTERNATION,
+                40 => CT::T_TYPE_ALTERNATION,
+            ],
+        ];
     }
 
     /**

+ 13 - 0
tests/Tokenizer/Transformer/TypeIntersectionTransformerTest.php

@@ -368,6 +368,19 @@ function f( #[Target(\'a\')] #[Target(\'b\')] #[Target(\'c\')] #[Target(\'d\')]
                 45 => CT::T_TYPE_INTERSECTION,
             ],
         ];
+
+        yield 'splat operator' => [
+            '<?php class Foo {
+                function f1(bool&int ... $x) {}
+                function f2(bool&int $x, TypeA&\Bar\Baz&TypeB ...$y) {}
+            }',
+            [
+                12 => CT::T_TYPE_INTERSECTION,
+                28 => CT::T_TYPE_INTERSECTION,
+                35 => CT::T_TYPE_INTERSECTION,
+                40 => CT::T_TYPE_INTERSECTION,
+            ],
+        ];
     }
 
     /**