Repository: phpactor/phpactor (php)

Issue:
Regression: name completion (again)
![image](https://github.com/phpactor/phpactor/assets/530801/9ee3ad68-0a11-45cf-a569-4bddfc802aa4)

no names are suggested above, possibly because it's expecting an enum!?

![image](https://github.com/phpactor/phpactor/assets/530801/de648bc9-c984-40aa-b4fa-e229a90b86d3)

no completion for `CancellationToken`

![image](https://github.com/phpactor/phpactor/assets/530801/0a3c256e-a757-4e1a-a784-29922e0b6767)

filtering doesn't work with (static?) method#

## Actually fine

![image](https://github.com/phpactor/phpactor/assets/530801/b73e10a3-71c5-4a67-9037-5a26f12fdd06)

~no completion for `new` ?~ wrong reieving type, so correctly filtered

Pull request description:
Gh 2483 fix context sensitive regressions
- suggest for enums
- suggest on static method calls

fixes #2483 

Patch:
diff --git a/lib/Completion/Bridge/WorseReflection/Completor/ContextSensitiveCompletor.php b/lib/Completion/Bridge/WorseReflection/Completor/ContextSensitiveCompletor.php
index 9868f75b..16ed44a2 100644
--- a/lib/Completion/Bridge/WorseReflection/Completor/ContextSensitiveCompletor.php
+++ b/lib/Completion/Bridge/WorseReflection/Completor/ContextSensitiveCompletor.php
@@ -14,7 +14,7 @@ use Phpactor\Completion\Bridge\TolerantParser\TolerantQualifiable;
 use Phpactor\Completion\Bridge\TolerantParser\TolerantQualifier;
 use Phpactor\TextDocument\ByteOffset;
 use Phpactor\TextDocument\TextDocument;
-use Phpactor\WorseReflection\Bridge\TolerantParser\Reflection\ReflectionMethodCall;
+use Phpactor\WorseReflection\Bridge\TolerantParser\Reflection\AbstractReflectionMethodCall;
 use Phpactor\WorseReflection\Core\Exception\NotFound;
 use Phpactor\WorseReflection\Core\Type\ArrayType;
 use Phpactor\WorseReflection\Core\Type\ClassLikeType;
@@ -31,6 +31,45 @@ class ContextSensitiveCompletor implements TolerantCompletor, TolerantQualifiabl
     {
         $generator = $this->inner->complete($node, $source, $offset);
 
+        $type = $this->resolveFilterableType($node, $source, $offset);
+        if (null === $type) {
+            yield from $generator;
+            return $generator->getReturn();
+        }
+
+        foreach ($generator as $suggestion) {
+            $fqn = $suggestion->fqn();
+            if (!$fqn) {
+                yield $suggestion;
+                continue;
+            }
+
+            try {
+                $refection = $this->reflector->reflectClassLike($fqn);
+            } catch (NotFound $e) {
+                continue;
+            }
+
+            if (!$refection->isInstanceOf($type->name())) {
+                continue;
+            }
+            yield $suggestion;
+        }
+
+        return $generator->getReturn();
+    }
+
+    public function qualifier(): TolerantQualifier
+    {
+        if ($this->inner instanceof TolerantQualifiable) {
+            return $this->inner->qualifier();
+        }
+
+        return new AlwaysQualfifier();
+    }
+
+    private function resolveFilterableType(Node $node, TextDocument $source, ByteOffset $offset): ?ClassLikeType
+    {
         $argumentNb = 0;
         $callExpression = $node;
         if ($node instanceof QualifiedName) {
@@ -39,8 +78,7 @@ class ContextSensitiveCompletor implements TolerantCompletor, TolerantQualifiabl
             if ($argumentExpression instanceof ArgumentExpression) {
                 $list = $argumentExpression->getFirstAncestor(ArgumentExpressionList::class);
                 if (!$list instanceof ArgumentExpressionList) {
-                    yield from $generator;
-                    return $generator->getReturn();
+                    return null;
                 }
                 $argumentNb = NodeUtil::argumentOffset($list, $argumentExpression) ?? 0;
                 $callExpression = $list->parent;
@@ -52,32 +90,27 @@ class ContextSensitiveCompletor implements TolerantCompletor, TolerantQualifiabl
         }
 
         if (!$callExpression instanceof CallExpression) {
-            yield from $generator;
-            return $generator->getReturn();
+            return null;
         }
 
         try {
             $callExpression = $this->reflector->reflectNode($source, $callExpression->openParen->getStartPosition());
         } catch (NotFound $e) {
-            yield from $generator;
-            return $generator->getReturn();
+            return null;
         }
-        if (!$callExpression instanceof ReflectionMethodCall) {
-            yield from $generator;
-            return $generator->getReturn();
+        if (!$callExpression instanceof AbstractReflectionMethodCall) {
+            return null;
         }
 
         try {
             $functionLike = $callExpression->method();
             $parameters = $functionLike->parameters();
         } catch (NotFound) {
-            yield from $generator;
-            return $generator->getReturn();
+            return null;
         }
         $parameter = $parameters->at($argumentNb);
         if (null === $parameter) {
-            yield from $generator;
-            return $generator->getReturn();
+            return null;
         }
 
         $type = $parameter->type();
@@ -87,38 +120,9 @@ class ContextSensitiveCompletor implements TolerantCompletor, TolerantQualifiabl
             }
         }
         if (!$type instanceof ClassLikeType) {
-            yield from $generator;
-            return $generator->getReturn();
+            return null;
         }
 
-        foreach ($generator as $suggestion) {
-            $fqn = $suggestion->fqn();
-            if (!$fqn) {
-                yield $suggestion;
-                continue;
-            }
-
-            try {
-                $refection = $this->reflector->reflectClass($fqn);
-            } catch (NotFound $e) {
-                continue;
-            }
-
-            if (!$refection->isInstanceOf($type->name())) {
-                continue;
-            }
-            yield $suggestion;
-        }
-
-        return $generator->getReturn();
-    }
-
-    public function qualifier(): TolerantQualifier
-    {
-        if ($this->inner instanceof TolerantQualifiable) {
-            return $this->inner->qualifier();
-        }
-
-        return new AlwaysQualfifier();
+        return $type;
     }
 }


Test patch:
diff --git a/lib/Completion/Tests/Unit/Bridge/WorseReflection/Completor/ContextSensitiveCompletorTest.php b/lib/Completion/Tests/Unit/Bridge/WorseReflection/Completor/ContextSensitiveCompletorTest.php
index 0b3d7487..12e4a663 100644
--- a/lib/Completion/Tests/Unit/Bridge/WorseReflection/Completor/ContextSensitiveCompletorTest.php
+++ b/lib/Completion/Tests/Unit/Bridge/WorseReflection/Completor/ContextSensitiveCompletorTest.php
@@ -208,6 +208,41 @@ class ContextSensitiveCompletorTest extends TestCase
                 'Obj',
             ],
         ];
+        yield 'enum' => [
+            [
+                'Obj',
+                'Baz',
+            ],
+            <<<'EOT'
+                <?php
+                enum Obj {}
+                class Baz {}
+                class Foo { public function bar(Obj $obj, Baz ...$baz){}}
+
+                $f = new Foo();
+                $f->bar(new O<>
+                EOT,
+            [
+                'Obj',
+            ],
+        ];
+        yield 'static' => [
+            [
+                'Obj',
+                'Baz',
+            ],
+            <<<'EOT'
+                <?php
+                enum Obj {}
+                class Baz {}
+                class Foo { public static function bar(Obj $obj, Baz ...$baz){}}
+
+                Foo::bar(new O<>
+                EOT,
+            [
+                'Obj',
+            ],
+        ];
         yield 'unresolvable method' => [
             [
                 'Obj',