From ee3d48c828b9ea40b6babe8f41652b1ff80a985a Mon Sep 17 00:00:00 2001 From: 3onyc <3onyc@x3tech.com> Date: Thu, 10 May 2018 17:04:34 +0200 Subject: [PATCH 01/16] [WIP] Very rudimentary starting point for Model::where*() methods --- src/BuilderMethodExtension.php | 29 +++++++++++++ src/CustomMethod.php | 78 ++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 src/CustomMethod.php diff --git a/src/BuilderMethodExtension.php b/src/BuilderMethodExtension.php index 8b137fa..4e0dbde 100644 --- a/src/BuilderMethodExtension.php +++ b/src/BuilderMethodExtension.php @@ -70,6 +70,10 @@ public function hasMethod(ClassReflection $classReflection, string $methodName): $this->methods[$classReflection->getName()] += $this->createMethods($classReflection, $queryBuilder); } + if ($classReflection->isSubclassOf(Model::class)) { + $this->methods[$classReflection->getName()] += $this->createModelMethod($classReflection, $methodName); + } + if ($classReflection->getName() === Builder::class && !isset($this->methods[Builder::class])) { $queryBuilder = $this->broker->getClass(QueryBuilder::class); $this->methods[Builder::class] = $this->createMethods($classReflection, $queryBuilder); @@ -127,4 +131,29 @@ private function createWrappedMethods(ClassReflection $classReflection, ClassRef return $methods; } + + /** + * @param ClassReflection $classReflection + * + * @return \PHPStan\Reflection\MethodReflection + */ + private function createModelMethod(ClassReflection $classReflection, string $methodName): array + { + if (strpos($methodName, 'where') !== 0) { + return []; + } + + $propertyName = strtolower(substr($methodName, 5, 1)) . substr($methodName, 6); + if (!$classReflection->hasProperty($propertyName)) { + return []; + } + + return [ + $methodName => new CustomMethod( + $classReflection, + $methodName, + $classReflection->getName() + ) + ]; + } } diff --git a/src/CustomMethod.php b/src/CustomMethod.php new file mode 100644 index 0000000..3461675 --- /dev/null +++ b/src/CustomMethod.php @@ -0,0 +1,78 @@ +class = $class; + $this->name = $name; + $this->returnType = $returnType; + } + + public function getDeclaringClass(): ClassReflection + { + return $this->class; + } + + public function getPrototype(): MethodReflection + { + return $this; + } + + public function isStatic(): bool + { + return true; + } + + public function isPrivate(): bool + { + return false; + } + + public function isPublic(): bool + { + return true; + } + + public function getName(): string + { + return $this->name; + } + + /** + * @return \PHPStan\Reflection\ParameterReflection[] + */ + public function getParameters(): array + { + return []; + } + + public function isVariadic(): bool + { + return true; + } + + public function getReturnType(): Type + { + if (is_array($this->returnType)) { + return new UnionType($this->returnType); + } + + return new ObjectType($this->returnType); + } +} From bb7a44d2fb3de389ba5acf6c611343cfdffcf608 Mon Sep 17 00:00:00 2001 From: Tlapi Date: Mon, 16 Jul 2018 10:46:29 +0200 Subject: [PATCH 02/16] Update composer.json --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index b381106..3e5e470 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ ], "require": { "laravel/framework": "5.5.* || 5.6.*", - "phpstan/phpstan": "^0.9" + "phpstan/phpstan": "^0.10" }, "require-dev": { "phpunit/phpunit": "^6.5.2" From ec01a71bc57f9d1bdfbd7a3e318b1aca6aca0f6d Mon Sep 17 00:00:00 2001 From: Tlapi Date: Mon, 16 Jul 2018 10:54:22 +0200 Subject: [PATCH 03/16] Update composer.json --- composer.json | 5 ----- 1 file changed, 5 deletions(-) diff --git a/composer.json b/composer.json index 3e5e470..28c044a 100644 --- a/composer.json +++ b/composer.json @@ -25,10 +25,5 @@ "psr-4": { "Tests\\Weebly\\PHPStan\\Laravel\\": "tests/" } - }, - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } } } From 74f2cd6f8ee77c9a73047fd05a135a684c453941 Mon Sep 17 00:00:00 2001 From: Tlapi Date: Mon, 16 Jul 2018 11:18:33 +0200 Subject: [PATCH 04/16] Update BuilderMethodExtension.php --- src/BuilderMethodExtension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/BuilderMethodExtension.php b/src/BuilderMethodExtension.php index 8b137fa..bfef299 100644 --- a/src/BuilderMethodExtension.php +++ b/src/BuilderMethodExtension.php @@ -49,7 +49,7 @@ public function __construct(MethodReflectionFactory $methodReflectionFactory, An /** * @inheritdoc */ - public function setBroker(Broker $broker) + public function setBroker(Broker $broker): void { $this->broker = $broker; } From 2fbd50c25904cbb1aad4cb8713c4a73245abf4b6 Mon Sep 17 00:00:00 2001 From: Tlapi Date: Mon, 16 Jul 2018 11:20:29 +0200 Subject: [PATCH 05/16] Update FacadeMethodExtension.php --- src/FacadeMethodExtension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FacadeMethodExtension.php b/src/FacadeMethodExtension.php index 5397a9d..0e36d37 100644 --- a/src/FacadeMethodExtension.php +++ b/src/FacadeMethodExtension.php @@ -58,7 +58,7 @@ public function __construct(MethodReflectionFactory $methodReflectionFactory, An /** * @inheritdoc */ - public function setBroker(Broker $broker) + public function setBroker(Broker $broker): void { $this->broker = $broker; } From 2eaefe7ee9e72ece2fb9b57d39a46422ab268d3c Mon Sep 17 00:00:00 2001 From: Tlapi Date: Mon, 16 Jul 2018 11:23:56 +0200 Subject: [PATCH 06/16] Update MacroMethodExtension.php --- src/MacroMethodExtension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MacroMethodExtension.php b/src/MacroMethodExtension.php index 4ec45a6..4e8b007 100644 --- a/src/MacroMethodExtension.php +++ b/src/MacroMethodExtension.php @@ -50,7 +50,7 @@ public function __construct(PhpMethodReflectionFactory $methodReflectionFactory, /** * @inheritdoc */ - public function setBroker(Broker $broker) + public function setBroker(Broker $broker): void { $this->broker = $broker; } From 8deb3321602cbb06f9b6dec74b8b0ae434abbd03 Mon Sep 17 00:00:00 2001 From: Tlapi Date: Mon, 16 Jul 2018 11:28:37 +0200 Subject: [PATCH 07/16] Update MethodReflectionFactory.php --- src/MethodReflectionFactory.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/MethodReflectionFactory.php b/src/MethodReflectionFactory.php index f946b67..24bebaa 100644 --- a/src/MethodReflectionFactory.php +++ b/src/MethodReflectionFactory.php @@ -60,6 +60,7 @@ public function create(ClassReflection $classReflection, \ReflectionMethod $meth $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc( $phpDocBlock->getFile(), $phpDocBlock->getClass(), + null, $phpDocBlock->getDocComment() ); $phpDocParameterTypes = array_map(function (ParamTag $tag): Type { From ab973a9b3162cd4b4b1ed345da7a6cb93a293a96 Mon Sep 17 00:00:00 2001 From: Tlapi Date: Mon, 16 Jul 2018 11:46:12 +0200 Subject: [PATCH 08/16] Update composer.json --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 28c044a..dce53ca 100644 --- a/composer.json +++ b/composer.json @@ -10,6 +10,7 @@ } ], "require": { + "php": "~7.1", "laravel/framework": "5.5.* || 5.6.*", "phpstan/phpstan": "^0.10" }, From f68b09116b5cd84652bab297d8a515934fd95c68 Mon Sep 17 00:00:00 2001 From: Tlapi Date: Mon, 16 Jul 2018 11:50:50 +0200 Subject: [PATCH 09/16] Update .travis.yml --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1e403bf..8d7f0fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: php php: - - 7.0 - 7.1 - 7.2 From 309e77c138c920b65df037a6fbccdd467311e4eb Mon Sep 17 00:00:00 2001 From: Tlapi Date: Tue, 17 Jul 2018 16:50:22 +0200 Subject: [PATCH 10/16] Update MethodReflectionFactory.php --- src/MethodReflectionFactory.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/MethodReflectionFactory.php b/src/MethodReflectionFactory.php index 24bebaa..2e8c817 100644 --- a/src/MethodReflectionFactory.php +++ b/src/MethodReflectionFactory.php @@ -75,6 +75,7 @@ public function create(ClassReflection $classReflection, \ReflectionMethod $meth return $this->methodReflectionFactory->create( $classReflection, + null, $methodReflection, $phpDocParameterTypes, $phpDocReturnType From 8d5f459826e8dfcdc14455dde67756872d0e3064 Mon Sep 17 00:00:00 2001 From: Tlapi Date: Tue, 17 Jul 2018 17:04:15 +0200 Subject: [PATCH 11/16] fix src/MethodReflectionFactory.php --- src/MethodReflectionFactory.php | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/MethodReflectionFactory.php b/src/MethodReflectionFactory.php index 2e8c817..6081f46 100644 --- a/src/MethodReflectionFactory.php +++ b/src/MethodReflectionFactory.php @@ -48,6 +48,10 @@ public function create(ClassReflection $classReflection, \ReflectionMethod $meth { $phpDocParameterTypes = []; $phpDocReturnType = null; + $phpDocThrowType = null; + $phpDocIsDeprecated = false; + $phpDocIsInternal = false; + $phpDocIsFinal = false; if ($methodReflection->getDocComment() !== false) { $phpDocBlock = PhpDocBlock::resolvePhpDocBlockForMethod( Broker::getInstance(), @@ -63,10 +67,15 @@ public function create(ClassReflection $classReflection, \ReflectionMethod $meth null, $phpDocBlock->getDocComment() ); + $phpDocParameterTypes = array_map(function (ParamTag $tag): Type { return $tag->getType(); }, $resolvedPhpDoc->getParamTags()); $phpDocReturnType = $resolvedPhpDoc->getReturnTag() !== null ? $resolvedPhpDoc->getReturnTag()->getType() : null; + $phpDocThrowType = $resolvedPhpDoc->getThrowsTag() !== null ? $resolvedPhpDoc->getThrowsTag()->getType() : null; + $phpDocIsDeprecated = $resolvedPhpDoc->isDeprecated(); + $phpDocIsInternal = $resolvedPhpDoc->isInternal(); + $phpDocIsFinal = $resolvedPhpDoc->isFinal(); } if ($methodWrapper) { @@ -78,7 +87,11 @@ public function create(ClassReflection $classReflection, \ReflectionMethod $meth null, $methodReflection, $phpDocParameterTypes, - $phpDocReturnType + $phpDocReturnType, + $phpDocThrowType, + $phpDocIsDeprecated, + $phpDocIsInternal, + $phpDocIsFinal ); } } From 5f334b1c3fb8d1fe3140198e0f288b244e9c0b89 Mon Sep 17 00:00:00 2001 From: Tlapi Date: Tue, 17 Jul 2018 17:08:32 +0200 Subject: [PATCH 12/16] add constraint for phpstan ^0.10.1 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index dce53ca..faa6a62 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ "require": { "php": "~7.1", "laravel/framework": "5.5.* || 5.6.*", - "phpstan/phpstan": "^0.10" + "phpstan/phpstan": "^0.10.1" }, "require-dev": { "phpunit/phpunit": "^6.5.2" From 17f626f3e49f31160fd25711454d2021b221c669 Mon Sep 17 00:00:00 2001 From: Johannes Hertenstein Date: Thu, 6 Sep 2018 11:58:04 +0200 Subject: [PATCH 13/16] TASK | Bump laravel requirement to 5.7 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index b381106..4ec9ef6 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ } ], "require": { - "laravel/framework": "5.5.* || 5.6.*", + "laravel/framework": "5.5.* || 5.6.* || 5.7.*", "phpstan/phpstan": "^0.9" }, "require-dev": { From 7b69c25be4f76ceab79d000ea3836322be1f2b71 Mon Sep 17 00:00:00 2001 From: Johannes Hertenstein Date: Thu, 6 Sep 2018 12:09:10 +0200 Subject: [PATCH 14/16] BUGFIX | Fix constant LARAVEL_START already being defined --- bootstrap.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bootstrap.php b/bootstrap.php index 04d9f90..aa96b75 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -1,6 +1,8 @@ Date: Wed, 21 Nov 2018 18:57:48 +0200 Subject: [PATCH 15/16] Fix type error for facades because of wrong implementation. --- src/ReflectionMethodAlwaysStatic.php | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/ReflectionMethodAlwaysStatic.php b/src/ReflectionMethodAlwaysStatic.php index ab05f2d..98a33a9 100644 --- a/src/ReflectionMethodAlwaysStatic.php +++ b/src/ReflectionMethodAlwaysStatic.php @@ -2,19 +2,11 @@ namespace Weebly\PHPStan\Laravel; -final class ReflectionMethodAlwaysStatic extends \ReflectionMethod -{ - /** - * @param \ReflectionMethod $reflectionMethod - * - * @throws \ReflectionException - */ - public function __construct(\ReflectionMethod $reflectionMethod) - { - parent::__construct($reflectionMethod->getDeclaringClass()->getName(), $reflectionMethod->getName()); - } +use PHPStan\Reflection\Php\NativeBuiltinMethodReflection; - public function isStatic() +final class ReflectionMethodAlwaysStatic extends NativeBuiltinMethodReflection +{ + public function isStatic(): bool { return true; } From 61c00d7a610f19ab842bf012a7467c6f0115b4f3 Mon Sep 17 00:00:00 2001 From: Martin Stefanov Date: Wed, 21 Nov 2018 18:58:56 +0200 Subject: [PATCH 16/16] Fix type error for static create of model. --- src/MethodReflectionFactory.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/MethodReflectionFactory.php b/src/MethodReflectionFactory.php index 6081f46..6fbd143 100644 --- a/src/MethodReflectionFactory.php +++ b/src/MethodReflectionFactory.php @@ -8,6 +8,7 @@ use PHPStan\Reflection\ClassReflection; use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\Php\PhpMethodReflectionFactory; +use PHPStan\Reflection\Php\NativeBuiltinMethodReflection; use PHPStan\Type\FileTypeMapper; use PHPStan\Type\Type; @@ -80,6 +81,8 @@ public function create(ClassReflection $classReflection, \ReflectionMethod $meth if ($methodWrapper) { $methodReflection = new $methodWrapper($methodReflection); + } else { + $methodReflection = new NativeBuiltinMethodReflection($methodReflection); } return $this->methodReflectionFactory->create(