From 64a4f535c0b17c8c68287c88c9f7d0d2e17ac91a Mon Sep 17 00:00:00 2001 From: Andrey Kotelnik Date: Thu, 15 Feb 2018 10:45:57 +0200 Subject: [PATCH 01/11] Added support of @mixin annotation to the BuilderMethodExtension --- src/BuilderMethodExtension.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/BuilderMethodExtension.php b/src/BuilderMethodExtension.php index da6ffef..eade1ec 100644 --- a/src/BuilderMethodExtension.php +++ b/src/BuilderMethodExtension.php @@ -51,7 +51,13 @@ public function setBroker(Broker $broker) */ public function hasMethod(ClassReflection $classReflection, string $methodName): bool { - if ($classReflection->isSubclassOf(Model::class) && !isset($this->methods[$classReflection->getName()])) { + if (!isset($this->methods[$classReflection->getName()]) && ( + $classReflection->isSubclassOf(Model::class) + || preg_match( + '/@mixin\s+' . preg_quote('\\' . Builder::class) . '/', + (string) $classReflection->getNativeReflection()->getDocComment() + ) + )) { $builder = $this->broker->getClass(Builder::class); $this->methods[$classReflection->getName()] = $this->createWrappedMethods($classReflection, $builder); From 6d0e01d7b1f81765a9a36dccabef2cfce45a3fd2 Mon Sep 17 00:00:00 2001 From: Andrey Kotelnik Date: Thu, 15 Feb 2018 10:48:33 +0200 Subject: [PATCH 02/11] Added tests for BuilderMethodExtension --- tests/BuilderMethodExtensionTest.php | 104 +++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 tests/BuilderMethodExtensionTest.php diff --git a/tests/BuilderMethodExtensionTest.php b/tests/BuilderMethodExtensionTest.php new file mode 100644 index 0000000..09e8d9b --- /dev/null +++ b/tests/BuilderMethodExtensionTest.php @@ -0,0 +1,104 @@ +assertFalse($this->hasMethod(stdClass::class, 'find')); + $this->assertTrue($this->hasMethod(ChildOfModel::class, 'find')); + $this->assertFalse($this->hasMethod(stdClass::class, 'select')); + $this->assertTrue($this->hasMethod(ChildOfModel::class, 'select')); + } + + public function testHasMethodInClassWithMixinAnnotation() + { + $this->assertFalse($this->hasMethod(stdClass::class, 'find')); + $this->assertTrue($this->hasMethod(HasAMixinAnnotation::class, 'find')); + $this->assertFalse($this->hasMethod(stdClass::class, 'select')); + $this->assertTrue($this->hasMethod(HasAMixinAnnotation::class, 'select')); + } + + public function testHasMethodInBuilder() + { + $this->assertFalse($this->hasMethod(stdClass::class, 'find')); + $this->assertTrue($this->hasMethod(Builder::class, 'find')); + $this->assertFalse($this->hasMethod(stdClass::class, 'select')); + $this->assertTrue($this->hasMethod(Builder::class, 'select')); + } + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + $this->broker = $this->createBroker(); + } + + /** + * @return MethodReflectionFactory + */ + private function makeMethodReflectionFactoryMock() + { + /** @var MockObject|PhpMethodReflectionFactory $phpMethodReflectionFactory */ + $phpMethodReflectionFactory = $this + ->getMockBuilder(PhpMethodReflectionFactory::class) + ->getMockForAbstractClass(); + $methodReflectionMock = $this + ->getMockBuilder(PhpMethodReflection::class) + ->disableOriginalConstructor() + ->getMock(); + $phpMethodReflectionFactory->method('create')->willReturn($methodReflectionMock); + /** @var FileTypeMapper $fileTypeMapper */ + $fileTypeMapper = $this->getContainer()->createInstance(FileTypeMapper::class); + + return new MethodReflectionFactory($phpMethodReflectionFactory, $fileTypeMapper); + } + + /** + * Check existence of the method in given class + * + * @param string $className + * @param string $methodName + * @return bool + */ + private function hasMethod(string $className, string $methodName): bool + { + $extension = new BuilderMethodExtension($this->makeMethodReflectionFactoryMock()); + $extension->setBroker($this->broker); + + return $extension->hasMethod($this->broker->getClass($className), $methodName); + } +} + +class ChildOfModel extends Model {} + +/** + * Some description + * + * @mixin \Illuminate\Database\Eloquent\Builder + * @method string getString() + */ +class HasAMixinAnnotation {} From 52b0925f34c6df89ab4e6a5227e9b469c608b9e7 Mon Sep 17 00:00:00 2001 From: Andrey Kotelnik Date: Tue, 20 Feb 2018 16:27:33 +0200 Subject: [PATCH 03/11] Added support of @mixin annotation to the FacadeMethodExtension --- src/FacadeMethodExtension.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/FacadeMethodExtension.php b/src/FacadeMethodExtension.php index 457c343..252823f 100644 --- a/src/FacadeMethodExtension.php +++ b/src/FacadeMethodExtension.php @@ -69,6 +69,17 @@ public function hasMethod(ClassReflection $classReflection, string $methodName): $instanceReflection = $this->broker->getClass(get_class($instance)); $this->methods[$classReflection->getName()] = $this->createMethods($classReflection, $instanceReflection); + if (preg_match_all( + '/@mixin\s+([\w\\\\]+)/', + (string) $instanceReflection->getNativeReflection()->getDocComment(), + $mixins + )) { + foreach ($mixins[1] as $mixin) { + $mixinInstanceReflection = $this->broker->getClass($mixin); + $this->methods[$classReflection->getName()] += $this->createMethods($classReflection, $mixinInstanceReflection); + } + } + if (isset($this->extensions[$instanceReflection->getName()])) { $extensionMethod = $this->extensions[$instanceReflection->getName()]; $extensionReflection = $this->broker->getClass(get_class($instance->$extensionMethod())); From 8a051fbcf6ee7bf76a0ffc0142bc597ae3afbea6 Mon Sep 17 00:00:00 2001 From: Andrey Kotelnik Date: Tue, 20 Feb 2018 16:28:33 +0200 Subject: [PATCH 04/11] Added tests for FacadeMethodExtension --- tests/FacadeMethodExtensionTest.php | 98 +++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 tests/FacadeMethodExtensionTest.php diff --git a/tests/FacadeMethodExtensionTest.php b/tests/FacadeMethodExtensionTest.php new file mode 100644 index 0000000..26200b0 --- /dev/null +++ b/tests/FacadeMethodExtensionTest.php @@ -0,0 +1,98 @@ +assertTrue($this->hasMethod(TestFacade::class, 'someMethod')); + $this->assertFalse($this->hasMethod(TestFacade::class, 'fakeMethod')); + // Method from accessor mixin + $this->assertTrue($this->hasMethod(TestFacade::class, 'table')); + $this->assertTrue($this->hasMethod(TestFacade::class, 'shouldUse')); + } + + /** + * @inheritdoc + */ + protected function setUp() + { + parent::setUp(); + $this->broker = $this->createBroker(); + } + + /** + * @return MethodReflectionFactory + */ + private function makeMethodReflectionFactoryMock() + { + /** @var MockObject|PhpMethodReflectionFactory $phpMethodReflectionFactory */ + $phpMethodReflectionFactory = $this + ->getMockBuilder(PhpMethodReflectionFactory::class) + ->getMockForAbstractClass(); + $methodReflectionMock = $this + ->getMockBuilder(PhpMethodReflection::class) + ->disableOriginalConstructor() + ->getMock(); + $phpMethodReflectionFactory->method('create')->willReturn($methodReflectionMock); + /** @var FileTypeMapper $fileTypeMapper */ + $fileTypeMapper = $this->getContainer()->createInstance(FileTypeMapper::class); + + return new MethodReflectionFactory($phpMethodReflectionFactory, $fileTypeMapper); + } + + /** + * Check existence of the method in given class + * + * @param string $className + * @param string $methodName + * @return bool + */ + private function hasMethod(string $className, string $methodName): bool + { + $extension = new FacadeMethodExtension($this->makeMethodReflectionFactoryMock()); + $extension->setBroker($this->broker); + + return $extension->hasMethod($this->broker->getClass($className), $methodName); + } +} + +/** + * @mixin \Illuminate\Database\Connection + * @mixin \Illuminate\Auth\AuthManager + */ +class TestFacadeAccessor { + function someMethod() { + return true; + } +} + +class TestFacade extends Facade { + /** + * @inheritdoc + */ + protected static function getFacadeAccessor() + { + return new TestFacadeAccessor(); + } +} From ebb723c8348b95d2ea65e77d6d449ca8dc7499a7 Mon Sep 17 00:00:00 2001 From: Feek Date: Sat, 31 Mar 2018 14:07:58 -0700 Subject: [PATCH 05/11] add support for helper function --- src/HelpersReturnTypeExtension.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/HelpersReturnTypeExtension.php b/src/HelpersReturnTypeExtension.php index d4cf2bc..5fb9bd7 100644 --- a/src/HelpersReturnTypeExtension.php +++ b/src/HelpersReturnTypeExtension.php @@ -20,6 +20,7 @@ final class HelpersReturnTypeExtension implements DynamicFunctionReturnTypeExten */ private $helpers = [ 'app', + 'response', 'validator', 'view', ]; @@ -54,7 +55,12 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, } return new MixedType(); + case 'response': + if (empty($functionCall->args)) { + return new ObjectType(\Illuminate\Contracts\Routing\ResponseFactory::class); + } + return new ObjectType(\Illuminate\Http\Response::class); case 'validator': if (empty($functionCall->args)) { return new ObjectType(\Illuminate\Contracts\Validation\Factory::class); From 844ade029292955cd2e871f7b69f0b0a8439d8a4 Mon Sep 17 00:00:00 2001 From: Feek Date: Sat, 31 Mar 2018 14:18:32 -0700 Subject: [PATCH 06/11] add support for redirect --- src/HelpersReturnTypeExtension.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/HelpersReturnTypeExtension.php b/src/HelpersReturnTypeExtension.php index 5fb9bd7..81819f9 100644 --- a/src/HelpersReturnTypeExtension.php +++ b/src/HelpersReturnTypeExtension.php @@ -20,6 +20,7 @@ final class HelpersReturnTypeExtension implements DynamicFunctionReturnTypeExten */ private $helpers = [ 'app', + 'redirect', 'response', 'validator', 'view', @@ -55,6 +56,12 @@ public function getTypeFromFunctionCall(FunctionReflection $functionReflection, } return new MixedType(); + case 'redirect': + if (empty($functionCall->args)) { + return new ObjectType(\Illuminate\Routing\Redirector::class); + } + + return new ObjectType(\Illuminate\Http\RedirectResponse::class); case 'response': if (empty($functionCall->args)) { return new ObjectType(\Illuminate\Contracts\Routing\ResponseFactory::class); From 5f518798bc4a70c722a5d2c9327c4e84c6ed5911 Mon Sep 17 00:00:00 2001 From: Andrey Kotelnik Date: Wed, 11 Apr 2018 23:09:51 +0300 Subject: [PATCH 07/11] Added annotations helper --- src/BuilderMethodExtension.php | 15 ++++-- src/FacadeMethodExtension.php | 23 +++++--- src/Utils/AnnotationsHelper.php | 27 ++++++++++ tests/BuilderMethodExtensionTest.php | 75 +++++++++++++++++++-------- tests/FacadeMethodExtensionTest.php | 73 ++++++++++++++++---------- tests/Utils/AnnotationsHelperTest.php | 56 ++++++++++++++++++++ 6 files changed, 206 insertions(+), 63 deletions(-) create mode 100644 src/Utils/AnnotationsHelper.php create mode 100644 tests/Utils/AnnotationsHelperTest.php diff --git a/src/BuilderMethodExtension.php b/src/BuilderMethodExtension.php index eade1ec..8b137fa 100644 --- a/src/BuilderMethodExtension.php +++ b/src/BuilderMethodExtension.php @@ -10,6 +10,7 @@ use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\MethodsClassReflectionExtension; use PHPStan\Reflection\MethodReflection; +use Weebly\PHPStan\Laravel\Utils\AnnotationsHelper; final class BuilderMethodExtension implements MethodsClassReflectionExtension, BrokerAwareExtension { @@ -28,14 +29,21 @@ final class BuilderMethodExtension implements MethodsClassReflectionExtension, B */ private $methodReflectionFactory; + /** + * @var AnnotationsHelper + */ + private $annotationsHelper; + /** * BuilderMethodExtension constructor. * * @param \Weebly\PHPStan\Laravel\MethodReflectionFactory $methodReflectionFactory + * @param AnnotationsHelper $annotationsHelper */ - public function __construct(MethodReflectionFactory $methodReflectionFactory) + public function __construct(MethodReflectionFactory $methodReflectionFactory, AnnotationsHelper $annotationsHelper) { $this->methodReflectionFactory = $methodReflectionFactory; + $this->annotationsHelper = $annotationsHelper; } /** @@ -53,10 +61,7 @@ public function hasMethod(ClassReflection $classReflection, string $methodName): { if (!isset($this->methods[$classReflection->getName()]) && ( $classReflection->isSubclassOf(Model::class) - || preg_match( - '/@mixin\s+' . preg_quote('\\' . Builder::class) . '/', - (string) $classReflection->getNativeReflection()->getDocComment() - ) + || in_array(Builder::class, $this->annotationsHelper->getMixins($classReflection)) )) { $builder = $this->broker->getClass(Builder::class); $this->methods[$classReflection->getName()] = $this->createWrappedMethods($classReflection, $builder); diff --git a/src/FacadeMethodExtension.php b/src/FacadeMethodExtension.php index 252823f..5397a9d 100644 --- a/src/FacadeMethodExtension.php +++ b/src/FacadeMethodExtension.php @@ -10,6 +10,8 @@ use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\MethodsClassReflectionExtension; use PHPStan\Reflection\MethodReflection; +use Weebly\PHPStan\Laravel\Utils\AnnotationsHelper; +use PHPStan\Broker\ClassNotFoundException; final class FacadeMethodExtension implements MethodsClassReflectionExtension, BrokerAwareExtension { @@ -36,14 +38,21 @@ final class FacadeMethodExtension implements MethodsClassReflectionExtension, Br */ private $methodReflectionFactory; + /** + * @var AnnotationsHelper + */ + private $annotationsHelper; + /** * FacadeMethodExtension constructor. * * @param \Weebly\PHPStan\Laravel\MethodReflectionFactory $methodReflectionFactory + * @param AnnotationsHelper $annotationsHelper */ - public function __construct(MethodReflectionFactory $methodReflectionFactory) + public function __construct(MethodReflectionFactory $methodReflectionFactory, AnnotationsHelper $annotationsHelper) { $this->methodReflectionFactory = $methodReflectionFactory; + $this->annotationsHelper = $annotationsHelper; } /** @@ -69,15 +78,13 @@ public function hasMethod(ClassReflection $classReflection, string $methodName): $instanceReflection = $this->broker->getClass(get_class($instance)); $this->methods[$classReflection->getName()] = $this->createMethods($classReflection, $instanceReflection); - if (preg_match_all( - '/@mixin\s+([\w\\\\]+)/', - (string) $instanceReflection->getNativeReflection()->getDocComment(), - $mixins - )) { - foreach ($mixins[1] as $mixin) { + foreach ($this->annotationsHelper->getMixins($instanceReflection) as $mixin) { + try { $mixinInstanceReflection = $this->broker->getClass($mixin); - $this->methods[$classReflection->getName()] += $this->createMethods($classReflection, $mixinInstanceReflection); + } catch (ClassNotFoundException $e) { + continue; } + $this->methods[$classReflection->getName()] += $this->createMethods($classReflection, $mixinInstanceReflection); } if (isset($this->extensions[$instanceReflection->getName()])) { diff --git a/src/Utils/AnnotationsHelper.php b/src/Utils/AnnotationsHelper.php new file mode 100644 index 0000000..bfa7b96 --- /dev/null +++ b/src/Utils/AnnotationsHelper.php @@ -0,0 +1,27 @@ +getNativeReflection()->getDocComment(), + $mixins + ); + + return array_map(function ($mixin) { + return preg_replace('#^\\\\#', '', $mixin); + }, $mixins[1]); + } +} diff --git a/tests/BuilderMethodExtensionTest.php b/tests/BuilderMethodExtensionTest.php index 09e8d9b..7b04617 100644 --- a/tests/BuilderMethodExtensionTest.php +++ b/tests/BuilderMethodExtensionTest.php @@ -13,6 +13,8 @@ use Weebly\PHPStan\Laravel\BuilderMethodExtension; use stdClass; use Illuminate\Database\Eloquent\Builder; +use Weebly\PHPStan\Laravel\Utils\AnnotationsHelper; +use PHPStan\Broker\ClassNotFoundException; /** * @package Tests\Weebly\PHPStan\Laravel @@ -24,28 +26,45 @@ class BuilderMethodExtensionTest extends TestCase */ private $broker; + /** + * @var string + */ + private $childOfModelClassName; + public function testHasMethodInSubclassOfModel() { - $this->assertFalse($this->hasMethod(stdClass::class, 'find')); - $this->assertTrue($this->hasMethod(ChildOfModel::class, 'find')); - $this->assertFalse($this->hasMethod(stdClass::class, 'select')); - $this->assertTrue($this->hasMethod(ChildOfModel::class, 'select')); + try { + $this->assertFalse($this->hasMethod(stdClass::class, 'find')); + $this->assertTrue($this->hasMethod($this->childOfModelClassName, 'find')); + $this->assertFalse($this->hasMethod(stdClass::class, 'select')); + $this->assertTrue($this->hasMethod($this->childOfModelClassName, 'select')); + } catch (ClassNotFoundException $e) { + $this->markTestIncomplete($e->getMessage()); + } } public function testHasMethodInClassWithMixinAnnotation() { - $this->assertFalse($this->hasMethod(stdClass::class, 'find')); - $this->assertTrue($this->hasMethod(HasAMixinAnnotation::class, 'find')); - $this->assertFalse($this->hasMethod(stdClass::class, 'select')); - $this->assertTrue($this->hasMethod(HasAMixinAnnotation::class, 'select')); + try { + $this->assertFalse($this->hasMethod(stdClass::class, 'find')); + $this->assertTrue($this->hasMethod(stdClass::class, 'find', true)); + $this->assertFalse($this->hasMethod(stdClass::class, 'select')); + $this->assertTrue($this->hasMethod(stdClass::class, 'select', true)); + } catch (ClassNotFoundException $e) { + $this->markTestIncomplete($e->getMessage()); + } } public function testHasMethodInBuilder() { - $this->assertFalse($this->hasMethod(stdClass::class, 'find')); - $this->assertTrue($this->hasMethod(Builder::class, 'find')); - $this->assertFalse($this->hasMethod(stdClass::class, 'select')); - $this->assertTrue($this->hasMethod(Builder::class, 'select')); + try { + $this->assertFalse($this->hasMethod(stdClass::class, 'find')); + $this->assertTrue($this->hasMethod(Builder::class, 'find')); + $this->assertFalse($this->hasMethod(stdClass::class, 'select')); + $this->assertTrue($this->hasMethod(Builder::class, 'select')); + } catch (ClassNotFoundException $e) { + $this->markTestIncomplete($e->getMessage()); + } } /** @@ -55,6 +74,7 @@ protected function setUp() { parent::setUp(); $this->broker = $this->createBroker(); + $this->childOfModelClassName = get_class(new class() extends Model {}); } /** @@ -82,23 +102,32 @@ private function makeMethodReflectionFactoryMock() * * @param string $className * @param string $methodName + * @param bool $addBuilderMixin * @return bool + * @throws ClassNotFoundException */ - private function hasMethod(string $className, string $methodName): bool + private function hasMethod(string $className, string $methodName, bool $addBuilderMixin = false): bool { - $extension = new BuilderMethodExtension($this->makeMethodReflectionFactoryMock()); + $extension = new BuilderMethodExtension( + $this->makeMethodReflectionFactoryMock(), + $this->makeAnnotationsHelperMock($addBuilderMixin) + ); $extension->setBroker($this->broker); return $extension->hasMethod($this->broker->getClass($className), $methodName); } -} -class ChildOfModel extends Model {} + /** + * @param bool $withBuilder + * @return AnnotationsHelper|MockObject + */ + private function makeAnnotationsHelperMock(bool $withBuilder = false) + { + $annotationsHelper = $this + ->getMockBuilder(AnnotationsHelper::class) + ->getMock(); + $annotationsHelper->method('getMixins')->willReturn($withBuilder ? [Builder::class] : []); -/** - * Some description - * - * @mixin \Illuminate\Database\Eloquent\Builder - * @method string getString() - */ -class HasAMixinAnnotation {} + return $annotationsHelper; + } +} diff --git a/tests/FacadeMethodExtensionTest.php b/tests/FacadeMethodExtensionTest.php index 26200b0..68ea3d4 100644 --- a/tests/FacadeMethodExtensionTest.php +++ b/tests/FacadeMethodExtensionTest.php @@ -10,6 +10,10 @@ use PHPStan\Reflection\Php\PhpMethodReflection; use PHPStan\Type\FileTypeMapper; use Weebly\PHPStan\Laravel\FacadeMethodExtension; +use Weebly\PHPStan\Laravel\Utils\AnnotationsHelper; +use PHPStan\Broker\ClassNotFoundException; +use Illuminate\Database\Connection; +use Illuminate\Auth\AuthManager; use Illuminate\Support\Facades\Facade; /** @@ -24,12 +28,30 @@ class FacadeMethodExtensionTest extends TestCase public function testHasMethod() { - // Native accessor method - $this->assertTrue($this->hasMethod(TestFacade::class, 'someMethod')); - $this->assertFalse($this->hasMethod(TestFacade::class, 'fakeMethod')); - // Method from accessor mixin - $this->assertTrue($this->hasMethod(TestFacade::class, 'table')); - $this->assertTrue($this->hasMethod(TestFacade::class, 'shouldUse')); + $testFacade = new class() extends Facade{ + /** + * @inheritdoc + */ + protected static function getFacadeAccessor() + { + return new class() { + public function someMethod() { + return true; + } + }; + } + }; + + try { + // Native accessor method + $this->assertTrue($this->hasMethod(get_class($testFacade), 'someMethod')); + $this->assertFalse($this->hasMethod(get_class($testFacade), 'fakeMethod')); + // Method from accessor mixin + $this->assertTrue($this->hasMethod(get_class($testFacade), 'table')); + $this->assertTrue($this->hasMethod(get_class($testFacade), 'shouldUse')); + } catch (ClassNotFoundException $e) { + $this->markTestIncomplete($e->getMessage()); + } } /** @@ -61,38 +83,35 @@ private function makeMethodReflectionFactoryMock() return new MethodReflectionFactory($phpMethodReflectionFactory, $fileTypeMapper); } + /** + * @return AnnotationsHelper|MockObject + */ + private function makeAnnotationsHelperMock() + { + $annotationsHelper = $this + ->getMockBuilder(AnnotationsHelper::class) + ->getMock(); + $annotationsHelper->method('getMixins')->willReturn([Connection::class, AuthManager::class, 'Fake']); + + return $annotationsHelper; + } + /** * Check existence of the method in given class * * @param string $className * @param string $methodName * @return bool + * @throws ClassNotFoundException */ private function hasMethod(string $className, string $methodName): bool { - $extension = new FacadeMethodExtension($this->makeMethodReflectionFactoryMock()); + $extension = new FacadeMethodExtension( + $this->makeMethodReflectionFactoryMock(), + $this->makeAnnotationsHelperMock() + ); $extension->setBroker($this->broker); return $extension->hasMethod($this->broker->getClass($className), $methodName); } } - -/** - * @mixin \Illuminate\Database\Connection - * @mixin \Illuminate\Auth\AuthManager - */ -class TestFacadeAccessor { - function someMethod() { - return true; - } -} - -class TestFacade extends Facade { - /** - * @inheritdoc - */ - protected static function getFacadeAccessor() - { - return new TestFacadeAccessor(); - } -} diff --git a/tests/Utils/AnnotationsHelperTest.php b/tests/Utils/AnnotationsHelperTest.php new file mode 100644 index 0000000..603a6ab --- /dev/null +++ b/tests/Utils/AnnotationsHelperTest.php @@ -0,0 +1,56 @@ +makeClassReflectionMock(<<assertEquals( + [TestCase::class, ClassReflection::class], + $annotationHelper->getMixins($reflection) + ); + $this->assertEquals( + [], + $annotationHelper->getMixins($this->makeClassReflectionMock('')) + ); + } + + /** + * @param string $docBlock + * @return ClassReflection|MockObject + */ + private function makeClassReflectionMock(string $docBlock) + { + $reflectionClass = $this + ->getMockBuilder(ReflectionClass::class) + ->disableOriginalConstructor() + ->getMock(); + $reflectionClass->method('getDocComment')->willReturn($docBlock); + + $classReflection = $this + ->getMockBuilder(ClassReflection::class) + ->disableOriginalConstructor() + ->getMock(); + $classReflection->method('getNativeReflection')->willReturn($reflectionClass); + + return $classReflection; + } +} From ce2811ffe09103a7b37fc3de8d012e30d435ce1f Mon Sep 17 00:00:00 2001 From: Chris Leppanen Date: Fri, 13 Apr 2018 16:27:17 -0700 Subject: [PATCH 08/11] Add annotations helper to container. --- extension.neon | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extension.neon b/extension.neon index 0c0f500..a8cb534 100644 --- a/extension.neon +++ b/extension.neon @@ -18,5 +18,7 @@ services: tags: - phpstan.broker.dynamicFunctionReturnTypeExtension + - class: Weebly\PHPStan\Laravel\Utils\AnnotationsHelper + parameters: bootstrap: %rootDir%/../../weebly/phpstan-laravel/bootstrap.php From ee1569acab2224512bac59af1f2cb8de1708f60f Mon Sep 17 00:00:00 2001 From: 3onyc <3onyc@x3tech.com> Date: Thu, 10 May 2018 15:08:48 +0200 Subject: [PATCH 09/11] Fix typo $macorable -> $macroable --- src/MacroMethodExtension.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/MacroMethodExtension.php b/src/MacroMethodExtension.php index 1c01162..4ec45a6 100644 --- a/src/MacroMethodExtension.php +++ b/src/MacroMethodExtension.php @@ -61,11 +61,11 @@ public function setBroker(Broker $broker) public function hasMethod(ClassReflection $classReflection, string $methodName): bool { if ($classReflection->hasTraitUse(Macroable::class)) { - /** @var \Illuminate\Support\Traits\Macroable $macorable */ - $macorable = $classReflection->getName(); + /** @var \Illuminate\Support\Traits\Macroable $macroable */ + $macroable = $classReflection->getName(); - if ($macorable::hasMacro($methodName) && !isset($this->methods[$classReflection->getName()])) { - $refObject = new \ReflectionClass($macorable); + if ($macroable::hasMacro($methodName) && !isset($this->methods[$classReflection->getName()])) { + $refObject = new \ReflectionClass($macroable); $refProperty = $refObject->getProperty('macros'); $refProperty->setAccessible(true); From 1d59481d24d07cc1681b1eb43f96fa40db621fb4 Mon Sep 17 00:00:00 2001 From: Pablo Reyes Date: Sat, 19 May 2018 14:41:17 -0300 Subject: [PATCH 10/11] problem when core LARAVEL_START is used --- bootstrap.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bootstrap.php b/bootstrap.php index 6d17458..04d9f90 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -1,5 +1,7 @@ make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap(); From 4a109ab1c3d58ce5e48b2f01aa2010abfba14f33 Mon Sep 17 00:00:00 2001 From: Zain Mehdi Date: Wed, 18 Sep 2019 18:06:56 -0400 Subject: [PATCH 11/11] Update README to highlight that this project is no longer maintained. --- README.md | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index f6e7711..a4c8740 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,3 @@ -# phpstan-laravel -Laravel plugins for [PHPStan](https://github.com/phpstan/phpstan) +# This package is no longer maintained. -[![Build Status](https://img.shields.io/travis/Weebly/phpstan-laravel/master.svg?style=flat-square)](https://travis-ci.org/Weebly/phpstan-laravel) - -## Usage - -To use this extension, require it in [Composer](https://getcomposer.org/): - -``` -composer require --dev weebly/phpstan-laravel -``` - -And include extension.neon in your project's PHPStan config: - -``` -includes: - - vendor/weebly/phpstan-laravel/extension.neon -``` +Instead, we recommend using https://github.com/nunomaduro/larastan