Skip to content

Commit

Permalink
Fix namespace of named type in class constant native type by patching…
Browse files Browse the repository at this point in the history
… PHP-Parser
  • Loading branch information
ondrejmirtes committed Nov 28, 2023
1 parent 6b5c6e4 commit 8234dc0
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 2 deletions.
3 changes: 3 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@
"patches/ReflectionProperty.patch",
"patches/SessionHandler.patch"
],
"nikic/php-parser": [
"patches/NameResolver.patch"
],
"rector/rector": [
"patches/NameNodeMapper.patch"
]
Expand Down
2 changes: 1 addition & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions patches/NameResolver.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
--- lib/PhpParser/NodeVisitor/NameResolver.php 2023-11-28 14:02:15
+++ lib/PhpParser/NodeVisitor/NameResolver.php 2023-11-28 14:03:53
@@ -119,6 +119,9 @@
}
} else if ($node instanceof Stmt\ClassConst) {
$this->resolveAttrGroups($node);
+ if (null !== $node->type) {
+ $node->type = $this->resolveType($node->type);
+ }
} else if ($node instanceof Stmt\EnumCase) {
$this->resolveAttrGroups($node);
} elseif ($node instanceof Expr\StaticCall
2 changes: 1 addition & 1 deletion src/Reflection/ClassReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -993,7 +993,7 @@ public function getConstant(string $name): ConstantReflection

$nativeType = null;
if ($reflectionConstant->getType() !== null) {
$nativeType = TypehintHelper::decideTypeFromReflection($reflectionConstant->getType(), null, $this);
$nativeType = TypehintHelper::decideTypeFromReflection($reflectionConstant->getType(), null, $declaringClass);
} elseif ($this->signatureMapProvider->hasClassConstantMetadata($declaringClass->getName(), $name)) {
$nativeType = $this->signatureMapProvider->getClassConstantMetadata($declaringClass->getName(), $name)['nativeType'];
}
Expand Down
1 change: 1 addition & 0 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,7 @@ public function dataFileAsserts(): iterable

if (PHP_VERSION_ID >= 80300) {
yield from $this->gatherAssertTypes(__DIR__ . '/data/class-constant-native-type.php');
yield from $this->gatherAssertTypes(__DIR__ . '/../Rules/Constants/data/bug-10212.php');
}

if (PHP_VERSION_ID >= 80000) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,18 @@ public function testNativeType(): void
]);
}

public function testBug10212(): void
{
if (PHP_VERSION_ID < 80300) {
$this->markTestSkipped('Test requires PHP 8.3.');
}

$this->analyse([__DIR__ . '/data/bug-10212.php'], [
[
'Constant Bug10212\HelloWorld::B (Bug10212\X\Foo) does not accept value Bug10212\Foo::Bar.',
15,
],
]);
}

}
22 changes: 22 additions & 0 deletions tests/PHPStan/Rules/Constants/data/bug-10212.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php // lint >= 8.3

namespace Bug10212;

use function PHPStan\Testing\assertType;

enum Foo
{
case Bar;
}

class HelloWorld
{
public const string A = 'foo';
public const X\Foo B = Foo::Bar;
public const Foo C = Foo::Bar;
}

function(HelloWorld $hw): void {
assertType(X\Foo::class, $hw::B);
assertType(Foo::class, $hw::C);
};

0 comments on commit 8234dc0

Please sign in to comment.