Repository: phpactor/phpactor (php)

Issue:
UnitEnum methods not recognized as an existing function
### Cases

Hi,

Looks like phpactor does not recognize the existence of `UnitEnum::cases()`.

Here is a reproducer:

```php
<?php

declare(strict_types=1);

enum MyEnum
{
    case A;
    case B;
    case C;
}

var_export(MyEnum::cases());
```

Error message: `Method "cases" does not exist on class "MyEnum"`

Context: branch 'master' of phpactor, used by vscode-phpactor, PHP 8.1.11.

### Other Methods

Hi,

Looks like phpactor does not recognize the existence of BackedEnum::from() or ::tryFrom().

Here is a reproducer:

```php
<?php

declare(strict_types=1);

enum MyEnum: string
{
    case A = 'a';
    case B = 'b';
    case C = 'c';
}

var_export(MyEnum::from('a'));
var_export(MyEnum::tryFrom('d'));
```

Error messages:
* `Method "from" does not exist on class "MyEnum"`
* `Method "tryFrom" does not exist on class "MyEnum"`

Context: branch 'master' of phpactor, used by vscode-phpactor, PHP 8.1.11.

Pull request description:
gh-1967: Fix enum source locator priority
Fixes #1967 

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3e5f013b..60b84232 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,7 @@ Bug fixes:
   - Do not add NULL to type list (fixes search bug) #2009
   - Create a real package for the tolerant-parser fork and use it #2033
   - Also highlight use statements when hovering on class #2039 @mamazu
+  - Fix priotity of "internal" stub locator - facilitating enum completion #2040
 
 Features:
 
diff --git a/lib/WorseReflection/ReflectorBuilder.php b/lib/WorseReflection/ReflectorBuilder.php
index 9c7546f3..16c06f2d 100644
--- a/lib/WorseReflection/ReflectorBuilder.php
+++ b/lib/WorseReflection/ReflectorBuilder.php
@@ -137,7 +137,7 @@ final class ReflectorBuilder
      */
     public function build(): Reflector
     {
-        $this->addLocator(InternalLocator::forInternalStubs(), 100);
+        $this->addLocator(InternalLocator::forInternalStubs(), 255);
         return (new ServiceLocator(
             $this->buildLocator(),
             $this->buildLogger(),


Test patch:
diff --git a/lib/WorseReflection/Tests/Unit/ReflectorBuilderTest.php b/lib/WorseReflection/Tests/Unit/ReflectorBuilderTest.php
index d2a30b60..41c03c04 100644
--- a/lib/WorseReflection/Tests/Unit/ReflectorBuilderTest.php
+++ b/lib/WorseReflection/Tests/Unit/ReflectorBuilderTest.php
@@ -4,6 +4,7 @@ namespace Phpactor\WorseReflection\Tests\Unit;
 
 use PHPUnit\Framework\TestCase;
 use Phpactor\WorseReflection\Core\SourceCode;
+use Phpactor\WorseReflection\Core\SourceCodeLocator\StringSourceLocator;
 use Phpactor\WorseReflection\ReflectorBuilder;
 use Phpactor\WorseReflection\Reflector;
 use Phpactor\WorseReflection\Core\SourceCodeLocator;
@@ -83,6 +84,19 @@ class ReflectorBuilderTest extends TestCase
         $this->assertInstanceOf(Reflector::class, $reflector);
     }
 
+    public function testInternalLocatorGetsHighestPriority(): void
+    {
+        $reflector = ReflectorBuilder::create()
+            ->addLocator(new StringSourceLocator(
+                SourceCode::fromString('<?php interface BackedEnum {}')
+            ), 100)
+            ->build();
+
+        $class = $reflector->reflectInterface('BackedEnum');
+        $this->assertEquals('BackedEnum', $class->name()->__toString());
+        $this->assertStringContainsString('InternalStubs', $class->sourceCode()->path());
+    }
+
     public function testEnableCache(): void
     {
         $reflector = ReflectorBuilder::create()