diff --git a/lib/WorseReflection/Core/Inference/Walker/FunctionLikeWalker.php b/lib/WorseReflection/Core/Inference/Walker/FunctionLikeWalker.php index 06b400229..a618bdb16 100644 --- a/lib/WorseReflection/Core/Inference/Walker/FunctionLikeWalker.php +++ b/lib/WorseReflection/Core/Inference/Walker/FunctionLikeWalker.php @@ -68,13 +68,16 @@ public function exit(FrameResolver $resolver, Frame $frame, Node $node): Frame private function walkFunctionLike(FrameResolver $resolver, Frame $frame, FunctionLike $node): void { $namespace = $node->getNamespaceDefinition(); - $classNode = $node->getFirstAncestor( - ClassDeclaration::class, - InterfaceDeclaration::class, - TraitDeclaration::class, - EnumDeclaration::class, - ObjectCreationExpression::class, // For Inline classes - ); + do { + // If we are here we found a normal ObjectCreationExpression like: new A(); and this is not useful and we continue traversing + $classNode = ($classNode ?? $node)->getFirstAncestor( + ClassDeclaration::class, + InterfaceDeclaration::class, + TraitDeclaration::class, + EnumDeclaration::class, + ObjectCreationExpression::class, // For Inline classes + ); + } while ($classNode instanceof ObjectCreationExpression && $classNode->classTypeDesignator instanceof Node); if ($node instanceof AnonymousFunctionCreationExpression) { $this->addAnonymousImports($frame, $node); @@ -87,7 +90,7 @@ private function walkFunctionLike(FrameResolver $resolver, Frame $frame, Functio } // works for both closure and class method (we currently ignore binding) - if ($classNode) { + if ($classNode !== null) { $classType = $resolver->resolveNode($frame, $classNode)->type(); $this->addClassContext($node, $classType, $frame); } diff --git a/lib/WorseReflection/Tests/Integration/Core/Inference/FrameWalker/FunctionLikeWalkerTest.php b/lib/WorseReflection/Tests/Integration/Core/Inference/FrameWalker/FunctionLikeWalkerTest.php index c46f5bf80..b1750e48b 100644 --- a/lib/WorseReflection/Tests/Integration/Core/Inference/FrameWalker/FunctionLikeWalkerTest.php +++ b/lib/WorseReflection/Tests/Integration/Core/Inference/FrameWalker/FunctionLikeWalkerTest.php @@ -34,6 +34,29 @@ public function hello() $this->assertEquals(false, $frame->locals()->byName('this')->first()->isProperty()); }]; + yield 'It returns this with correct type in an anonymous function' => [ + <<<'EOT' + }); + } + } + + EOT + , function (Frame $frame): void { + $this->assertCount(1, $frame->locals()->byName('this')); + $this->assertEquals('Foobar\Barfoo\Foobar', $frame->locals()->byName('this')->first()->type()->__toString()); + $this->assertEquals(false, $frame->locals()->byName('this')->first()->isProperty()); + }]; + yield 'It returns method arguments' => [ <<<'EOT'