From 1d0e2b8078757eef0fe260fdae5e534a1d2f21f2 Mon Sep 17 00:00:00 2001 From: IAmRGroot Date: Mon, 14 Jun 2021 13:44:16 +0200 Subject: [PATCH 1/7] Recursively get traits --- src/Reflection/ClassReflection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Reflection/ClassReflection.php b/src/Reflection/ClassReflection.php index 9f4148ae85..3aa737d354 100644 --- a/src/Reflection/ClassReflection.php +++ b/src/Reflection/ClassReflection.php @@ -676,7 +676,7 @@ public function getTraits(): array { return array_map(function (\ReflectionClass $trait): ClassReflection { return $this->reflectionProvider->getClass($trait->getName()); - }, $this->getNativeReflection()->getTraits()); + }, $this->collectTraits($this->getNativeReflection())); } /** From e533841b5933ded92a96a36d9c76a0d9c0b6943d Mon Sep 17 00:00:00 2001 From: RobertGroot Date: Tue, 15 Jun 2021 17:31:10 +0200 Subject: [PATCH 2/7] Changed collectTraits to nested traits --- src/Reflection/ClassReflection.php | 5 +++ .../Reflection/ClassReflectionTest.php | 37 +++++++++++++++++ .../PHPStan/Reflection/data/NestedTraits.php | 40 +++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 tests/PHPStan/Reflection/data/NestedTraits.php diff --git a/src/Reflection/ClassReflection.php b/src/Reflection/ClassReflection.php index 3aa737d354..dee1e93e62 100644 --- a/src/Reflection/ClassReflection.php +++ b/src/Reflection/ClassReflection.php @@ -344,6 +344,11 @@ private function collectTraits(\ReflectionClass $class): array $traits = []; $traitsLeftToAnalyze = $class->getTraits(); + // TOOD is this desired? + // if ($parentClass = $class->getParentClass()) { + // $traits = $this->collectTraits($parentClass); + // } + while (count($traitsLeftToAnalyze) !== 0) { $trait = reset($traitsLeftToAnalyze); $traits[] = $trait; diff --git a/tests/PHPStan/Reflection/ClassReflectionTest.php b/tests/PHPStan/Reflection/ClassReflectionTest.php index 25251fc4cf..5fbf568fb2 100644 --- a/tests/PHPStan/Reflection/ClassReflectionTest.php +++ b/tests/PHPStan/Reflection/ClassReflectionTest.php @@ -220,4 +220,41 @@ public function testDeprecatedConstantFromAnotherFile(): void $this->assertTrue($constant->isDeprecated()->yes()); } + public function testGetTraits(): void + { + $reflectionProvider = $this->createBroker(); + + $classes = [ + \NestedTraits\NoTrait::class => [], + \NestedTraits\Foo::class => [ + \NestedTraits\FooTrait::class, + ], + \NestedTraits\Bar::class => [ + \NestedTraits\BarTrait::class, + \NestedTraits\FooTrait::class, + ], + \NestedTraits\Baz::class => [ + \NestedTraits\BazTrait::class, + \NestedTraits\BarTrait::class, + \NestedTraits\FooTrait::class, + ], + \NestedTraits\BazChild::class => [ + // TOOD is this expected? + // \NestedTraits\BazTrait::class, + // \NestedTraits\BarTrait::class, + // \NestedTraits\FooTrait::class, + ], + ]; + + foreach ($classes as $class => $expectedTraits) { + $this->assertSame( + array_map( + static fn(ClassReflection $classReflection) => $classReflection->getNativeReflection()->getName(), + $reflectionProvider->getClass($class)->getTraits() + ), + $expectedTraits + ); + } + } + } diff --git a/tests/PHPStan/Reflection/data/NestedTraits.php b/tests/PHPStan/Reflection/data/NestedTraits.php new file mode 100644 index 0000000000..8b16cd676f --- /dev/null +++ b/tests/PHPStan/Reflection/data/NestedTraits.php @@ -0,0 +1,40 @@ + Date: Wed, 16 Jun 2021 08:46:50 +0200 Subject: [PATCH 3/7] Added recursive parameter to getTraits --- src/Reflection/ClassReflection.php | 22 ++-- .../Reflection/ClassReflectionTest.php | 109 +++++++++++++----- 2 files changed, 97 insertions(+), 34 deletions(-) diff --git a/src/Reflection/ClassReflection.php b/src/Reflection/ClassReflection.php index dee1e93e62..906ee79605 100644 --- a/src/Reflection/ClassReflection.php +++ b/src/Reflection/ClassReflection.php @@ -344,11 +344,6 @@ private function collectTraits(\ReflectionClass $class): array $traits = []; $traitsLeftToAnalyze = $class->getTraits(); - // TOOD is this desired? - // if ($parentClass = $class->getParentClass()) { - // $traits = $this->collectTraits($parentClass); - // } - while (count($traitsLeftToAnalyze) !== 0) { $trait = reset($traitsLeftToAnalyze); $traits[] = $trait; @@ -677,11 +672,24 @@ public function getInterfaces(): array /** * @return \PHPStan\Reflection\ClassReflection[] */ - public function getTraits(): array + public function getTraits(bool $recursive = false): array { - return array_map(function (\ReflectionClass $trait): ClassReflection { + $traits = array_map(function (\ReflectionClass $trait): ClassReflection { return $this->reflectionProvider->getClass($trait->getName()); }, $this->collectTraits($this->getNativeReflection())); + + if ($recursive) { + $parentClass = $this->getNativeReflection()->getParentClass(); + + if ($parentClass !== false) { + return array_merge( + $traits, + $this->reflectionProvider->getClass($parentClass->getName())->getTraits(true) + ); + } + } + + return $traits; } /** diff --git a/tests/PHPStan/Reflection/ClassReflectionTest.php b/tests/PHPStan/Reflection/ClassReflectionTest.php index 5fbf568fb2..65fea11cc1 100644 --- a/tests/PHPStan/Reflection/ClassReflectionTest.php +++ b/tests/PHPStan/Reflection/ClassReflectionTest.php @@ -220,41 +220,96 @@ public function testDeprecatedConstantFromAnotherFile(): void $this->assertTrue($constant->isDeprecated()->yes()); } - public function testGetTraits(): void + /** + * @dataProvider dataNestedRecursiveTraits + * @param class-string $className + * @param class-string[] $expected + * @param bool $recursive + */ + public function testGetTraits(string $className, array $expected, bool $recursive = false): void { $reflectionProvider = $this->createBroker(); - $classes = [ - \NestedTraits\NoTrait::class => [], - \NestedTraits\Foo::class => [ - \NestedTraits\FooTrait::class, + $this->assertSame( + array_map( + static fn(ClassReflection $classReflection) => $classReflection->getNativeReflection()->getName(), + $reflectionProvider->getClass($className)->getTraits($recursive) + ), + $expected + ); + } + + public function dataNestedRecursiveTraits(): array + { + return [ + [ + \NestedTraits\NoTrait::class, + [], + ], + [ + \NestedTraits\NoTrait::class, + [], + true, + ], + [ + \NestedTraits\Foo::class, + [ + \NestedTraits\FooTrait::class, + ], + ], + [ + \NestedTraits\Foo::class, + [ + \NestedTraits\FooTrait::class, + ], + true, + ], + [ + \NestedTraits\Bar::class, + [ + \NestedTraits\BarTrait::class, + \NestedTraits\FooTrait::class, + ], ], - \NestedTraits\Bar::class => [ - \NestedTraits\BarTrait::class, - \NestedTraits\FooTrait::class, + [ + \NestedTraits\Bar::class, + [ + \NestedTraits\BarTrait::class, + \NestedTraits\FooTrait::class, + ], + true, ], - \NestedTraits\Baz::class => [ - \NestedTraits\BazTrait::class, - \NestedTraits\BarTrait::class, - \NestedTraits\FooTrait::class, + [ + \NestedTraits\Baz::class, + [ + \NestedTraits\BazTrait::class, + \NestedTraits\BarTrait::class, + \NestedTraits\FooTrait::class, + ], ], - \NestedTraits\BazChild::class => [ - // TOOD is this expected? - // \NestedTraits\BazTrait::class, - // \NestedTraits\BarTrait::class, - // \NestedTraits\FooTrait::class, + [ + \NestedTraits\Baz::class, + [ + \NestedTraits\BazTrait::class, + \NestedTraits\BarTrait::class, + \NestedTraits\FooTrait::class, + ], + true, + ], + [ + \NestedTraits\BazChild::class, + [], + ], + [ + \NestedTraits\BazChild::class, + [ + \NestedTraits\BazTrait::class, + \NestedTraits\BarTrait::class, + \NestedTraits\FooTrait::class, + ], + true, ], ]; - - foreach ($classes as $class => $expectedTraits) { - $this->assertSame( - array_map( - static fn(ClassReflection $classReflection) => $classReflection->getNativeReflection()->getName(), - $reflectionProvider->getClass($class)->getTraits() - ), - $expectedTraits - ); - } } } From 3aafbc61cac64a9100951387eedcad2e6a5d1ae6 Mon Sep 17 00:00:00 2001 From: RobertGroot Date: Wed, 16 Jun 2021 13:10:34 +0200 Subject: [PATCH 4/7] PHP 7.1 safe function and non-optional parameter --- tests/PHPStan/Reflection/ClassReflectionTest.php | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/PHPStan/Reflection/ClassReflectionTest.php b/tests/PHPStan/Reflection/ClassReflectionTest.php index 65fea11cc1..963a0a1e90 100644 --- a/tests/PHPStan/Reflection/ClassReflectionTest.php +++ b/tests/PHPStan/Reflection/ClassReflectionTest.php @@ -226,13 +226,15 @@ public function testDeprecatedConstantFromAnotherFile(): void * @param class-string[] $expected * @param bool $recursive */ - public function testGetTraits(string $className, array $expected, bool $recursive = false): void + public function testGetTraits(string $className, array $expected, bool $recursive): void { $reflectionProvider = $this->createBroker(); $this->assertSame( array_map( - static fn(ClassReflection $classReflection) => $classReflection->getNativeReflection()->getName(), + static function (ClassReflection $classReflection): string { + return $classReflection->getNativeReflection()->getName(); + }, $reflectionProvider->getClass($className)->getTraits($recursive) ), $expected @@ -245,6 +247,7 @@ public function dataNestedRecursiveTraits(): array [ \NestedTraits\NoTrait::class, [], + false, ], [ \NestedTraits\NoTrait::class, @@ -256,6 +259,7 @@ public function dataNestedRecursiveTraits(): array [ \NestedTraits\FooTrait::class, ], + false, ], [ \NestedTraits\Foo::class, @@ -270,6 +274,7 @@ public function dataNestedRecursiveTraits(): array \NestedTraits\BarTrait::class, \NestedTraits\FooTrait::class, ], + false, ], [ \NestedTraits\Bar::class, @@ -286,6 +291,7 @@ public function dataNestedRecursiveTraits(): array \NestedTraits\BarTrait::class, \NestedTraits\FooTrait::class, ], + false, ], [ \NestedTraits\Baz::class, @@ -299,6 +305,7 @@ public function dataNestedRecursiveTraits(): array [ \NestedTraits\BazChild::class, [], + false, ], [ \NestedTraits\BazChild::class, From a39ac01990fe0d1cb23582405e06dca6c91e6a06 Mon Sep 17 00:00:00 2001 From: RobertGroot Date: Thu, 17 Jun 2021 08:07:56 +0200 Subject: [PATCH 5/7] No nested traits when not recursive --- src/Reflection/ClassReflection.php | 6 +++++- tests/PHPStan/Reflection/ClassReflectionTest.php | 3 --- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Reflection/ClassReflection.php b/src/Reflection/ClassReflection.php index 906ee79605..87d3fd5c67 100644 --- a/src/Reflection/ClassReflection.php +++ b/src/Reflection/ClassReflection.php @@ -674,9 +674,13 @@ public function getInterfaces(): array */ public function getTraits(bool $recursive = false): array { + $traits = $recursive ? + $this->collectTraits($this->getNativeReflection()) : + array_values($this->getNativeReflection()->getTraits()); + $traits = array_map(function (\ReflectionClass $trait): ClassReflection { return $this->reflectionProvider->getClass($trait->getName()); - }, $this->collectTraits($this->getNativeReflection())); + }, $traits); if ($recursive) { $parentClass = $this->getNativeReflection()->getParentClass(); diff --git a/tests/PHPStan/Reflection/ClassReflectionTest.php b/tests/PHPStan/Reflection/ClassReflectionTest.php index 963a0a1e90..339c72c964 100644 --- a/tests/PHPStan/Reflection/ClassReflectionTest.php +++ b/tests/PHPStan/Reflection/ClassReflectionTest.php @@ -272,7 +272,6 @@ public function dataNestedRecursiveTraits(): array \NestedTraits\Bar::class, [ \NestedTraits\BarTrait::class, - \NestedTraits\FooTrait::class, ], false, ], @@ -288,8 +287,6 @@ public function dataNestedRecursiveTraits(): array \NestedTraits\Baz::class, [ \NestedTraits\BazTrait::class, - \NestedTraits\BarTrait::class, - \NestedTraits\FooTrait::class, ], false, ], From 26ca22aa452c9c703fab8acb406a78c8973afb22 Mon Sep 17 00:00:00 2001 From: RobertGroot Date: Thu, 17 Jun 2021 08:35:44 +0200 Subject: [PATCH 6/7] Added keys to collectTrait results to match native getTraits --- src/Reflection/ClassReflection.php | 14 +++++++---- .../Reflection/ClassReflectionTest.php | 24 +++++++++---------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/Reflection/ClassReflection.php b/src/Reflection/ClassReflection.php index 87d3fd5c67..2415737b5e 100644 --- a/src/Reflection/ClassReflection.php +++ b/src/Reflection/ClassReflection.php @@ -670,13 +670,19 @@ public function getInterfaces(): array } /** - * @return \PHPStan\Reflection\ClassReflection[] + * @return array */ public function getTraits(bool $recursive = false): array { - $traits = $recursive ? - $this->collectTraits($this->getNativeReflection()) : - array_values($this->getNativeReflection()->getTraits()); + $traits = []; + + if ($recursive) { + foreach ($this->collectTraits($this->getNativeReflection()) as $trait) { + $traits[$trait->getName()] = $trait; + } + } else { + $traits = $this->getNativeReflection()->getTraits(); + } $traits = array_map(function (\ReflectionClass $trait): ClassReflection { return $this->reflectionProvider->getClass($trait->getName()); diff --git a/tests/PHPStan/Reflection/ClassReflectionTest.php b/tests/PHPStan/Reflection/ClassReflectionTest.php index 339c72c964..695ff987ac 100644 --- a/tests/PHPStan/Reflection/ClassReflectionTest.php +++ b/tests/PHPStan/Reflection/ClassReflectionTest.php @@ -257,45 +257,45 @@ public function dataNestedRecursiveTraits(): array [ \NestedTraits\Foo::class, [ - \NestedTraits\FooTrait::class, + \NestedTraits\FooTrait::class => \NestedTraits\FooTrait::class, ], false, ], [ \NestedTraits\Foo::class, [ - \NestedTraits\FooTrait::class, + \NestedTraits\FooTrait::class => \NestedTraits\FooTrait::class, ], true, ], [ \NestedTraits\Bar::class, [ - \NestedTraits\BarTrait::class, + \NestedTraits\BarTrait::class => \NestedTraits\BarTrait::class, ], false, ], [ \NestedTraits\Bar::class, [ - \NestedTraits\BarTrait::class, - \NestedTraits\FooTrait::class, + \NestedTraits\BarTrait::class => \NestedTraits\BarTrait::class, + \NestedTraits\FooTrait::class => \NestedTraits\FooTrait::class, ], true, ], [ \NestedTraits\Baz::class, [ - \NestedTraits\BazTrait::class, + \NestedTraits\BazTrait::class => \NestedTraits\BazTrait::class, ], false, ], [ \NestedTraits\Baz::class, [ - \NestedTraits\BazTrait::class, - \NestedTraits\BarTrait::class, - \NestedTraits\FooTrait::class, + \NestedTraits\BazTrait::class => \NestedTraits\BazTrait::class, + \NestedTraits\BarTrait::class => \NestedTraits\BarTrait::class, + \NestedTraits\FooTrait::class => \NestedTraits\FooTrait::class, ], true, ], @@ -307,9 +307,9 @@ public function dataNestedRecursiveTraits(): array [ \NestedTraits\BazChild::class, [ - \NestedTraits\BazTrait::class, - \NestedTraits\BarTrait::class, - \NestedTraits\FooTrait::class, + \NestedTraits\BazTrait::class => \NestedTraits\BazTrait::class, + \NestedTraits\BarTrait::class => \NestedTraits\BarTrait::class, + \NestedTraits\FooTrait::class => \NestedTraits\FooTrait::class, ], true, ], From 045784c787a983da73797d338ea0926da0f0025f Mon Sep 17 00:00:00 2001 From: RobertGroot Date: Thu, 17 Jun 2021 08:38:51 +0200 Subject: [PATCH 7/7] Better docs --- tests/PHPStan/Reflection/ClassReflectionTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PHPStan/Reflection/ClassReflectionTest.php b/tests/PHPStan/Reflection/ClassReflectionTest.php index 695ff987ac..86a016db66 100644 --- a/tests/PHPStan/Reflection/ClassReflectionTest.php +++ b/tests/PHPStan/Reflection/ClassReflectionTest.php @@ -223,7 +223,7 @@ public function testDeprecatedConstantFromAnotherFile(): void /** * @dataProvider dataNestedRecursiveTraits * @param class-string $className - * @param class-string[] $expected + * @param array $expected * @param bool $recursive */ public function testGetTraits(string $className, array $expected, bool $recursive): void