diff --git a/lib/PhpParser/NameContext.php b/lib/PhpParser/NameContext.php index 2265ecce82..cbfe81a572 100644 --- a/lib/PhpParser/NameContext.php +++ b/lib/PhpParser/NameContext.php @@ -122,6 +122,12 @@ public function getResolvedName(Name $name, int $type): ?Name { if ($type !== Stmt\Use_::TYPE_NORMAL && $name->isUnqualified()) { if (null === $this->namespace) { + $relativeName = $this->getNamespaceRelativeName($name->toString(), strtolower($name->toString()), $type, $name->getAttributes()); + + if ($relativeName instanceof Name) { + return $relativeName; + } + // outside of a namespace unaliased unqualified is same as fully qualified return new FullyQualified($name, $name->getAttributes()); } @@ -249,22 +255,25 @@ private function resolveAlias(Name $name, int $type): ?FullyQualified { return null; } - private function getNamespaceRelativeName(string $name, string $lcName, int $type): ?Name { + /** + * @param array $attributes + */ + private function getNamespaceRelativeName(string $name, string $lcName, int $type, array $attributes = []): ?Name { if (null === $this->namespace) { - return new Name($name); + return new Name($name, $attributes); } if ($type === Stmt\Use_::TYPE_CONSTANT) { // The constants true/false/null always resolve to the global symbols, even inside a // namespace, so they may be used without qualification if ($lcName === "true" || $lcName === "false" || $lcName === "null") { - return new Name($name); + return new Name($name, $attributes); } } $namespacePrefix = strtolower($this->namespace . '\\'); if (0 === strpos($lcName, $namespacePrefix)) { - return new Name(substr($name, strlen($namespacePrefix))); + return new Name(substr($name, strlen($namespacePrefix)), $attributes); } return null; diff --git a/test/PhpParser/NodeVisitor/NameResolverTest.php b/test/PhpParser/NodeVisitor/NameResolverTest.php index e2d5c0386a..2aab9f8118 100644 --- a/test/PhpParser/NodeVisitor/NameResolverTest.php +++ b/test/PhpParser/NodeVisitor/NameResolverTest.php @@ -117,8 +117,8 @@ public function testResolveNames(): void { new \Hallo\Bar(); new \Bar(); new \Bar(); - \bar(); - \hi(); + bar(); + hi(); \Hallo\bar(); \foo\bar(); \bar(); @@ -197,7 +197,7 @@ class A extends B implements C, D { #[X] const C = 1; - + public const X A = X::Bar; public const X\Foo B = X\Foo::Bar; public const \X\Foo C = \X\Foo::Bar;