From ddb9702b1ce1bdc3bc974faae099360677fbdb7d Mon Sep 17 00:00:00 2001 From: Hugo Sales Date: Tue, 7 Sep 2021 20:16:47 +0000 Subject: [PATCH] [TOOLS][PHPStan] Add support for deducing the correct entity type from a table name. Needs refactoring and can only run inside container, as it connects to the database itself --- bin/pre-commit | 2 +- config/phpstan-bootstrap.php | 10 ++++ phpstan.neon | 9 ++++ ...DynamicStaticMethodReturnTypeExtension.php | 53 +++++++++++++++++++ src/PHPStan/ObjectManagerResolver.php | 20 +++++++ 5 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 config/phpstan-bootstrap.php create mode 100644 src/PHPStan/ClassFromTableNameDynamicStaticMethodReturnTypeExtension.php create mode 100644 src/PHPStan/ObjectManagerResolver.php diff --git a/bin/pre-commit b/bin/pre-commit index aa75aecd7a..a9d41cd9b1 100755 --- a/bin/pre-commit +++ b/bin/pre-commit @@ -1,4 +1,4 @@ -#!/usr/bin/env bash +#!/usr/bin/env sh root="$(git rev-parse --show-toplevel)" diff --git a/config/phpstan-bootstrap.php b/config/phpstan-bootstrap.php new file mode 100644 index 0000000000..015a7a02bf --- /dev/null +++ b/config/phpstan-bootstrap.php @@ -0,0 +1,10 @@ +boot(); +return $kernel->getContainer()->get('doctrine')->getManager(); diff --git a/phpstan.neon b/phpstan.neon index bfc4afd185..39a64b9b05 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -10,3 +10,12 @@ parameters: message: '/Access to an undefined property App\\Util\\Bitmap::\$\w+/' paths: - * + +services: + - + class: App\PHPStan\ClassFromTableNameDynamicStaticMethodReturnTypeExtension + tags: + - phpstan.broker.dynamicStaticMethodReturnTypeExtension + + - + class: App\PHPStan\ObjectManagerResolver diff --git a/src/PHPStan/ClassFromTableNameDynamicStaticMethodReturnTypeExtension.php b/src/PHPStan/ClassFromTableNameDynamicStaticMethodReturnTypeExtension.php new file mode 100644 index 0000000000..929b44098a --- /dev/null +++ b/src/PHPStan/ClassFromTableNameDynamicStaticMethodReturnTypeExtension.php @@ -0,0 +1,53 @@ +manager = $resolver->getManager(); + } + + public function getClass(): string + { + return \App\Core\DB\DB::class; + } + + public function isStaticMethodSupported(MethodReflection $methodReflection): bool + { + return in_array($methodReflection->getName(), DB::METHODS_ACCEPTING_TABLE_NAME); + } + + public function getTypeFromStaticMethodCall( + MethodReflection $methodReflection, + StaticCall $staticCall, + Scope $scope + ): \PHPStan\Type\Type + { + if (count($staticCall->args) === 0) { + return \PHPStan\Reflection\ParametersAcceptorSelector::selectFromArgs($scope, $staticCall->args, $methodReflection->getVariants())->getReturnType(); + } + $arg = $staticCall->args[0]->value; + if ($arg instanceof String_) { + DB::setManager($this->manager); + DB::initTableMap(); + $class = DB::filterTableName($staticCall->name, [$arg->value]); + return $scope->resolveTypeByName(new Name($class)); + } else { + return \PHPStan\Reflection\ParametersAcceptorSelector::selectFromArgs($scope, $staticCall->args, $methodReflection->getVariants())->getReturnType(); + } + } +} diff --git a/src/PHPStan/ObjectManagerResolver.php b/src/PHPStan/ObjectManagerResolver.php new file mode 100644 index 0000000000..a353b5522c --- /dev/null +++ b/src/PHPStan/ObjectManagerResolver.php @@ -0,0 +1,20 @@ +objectManager !== null) { + return $this->objectManager; + } else { + $this->objectManager = require __DIR__ . '/../../config/phpstan-bootstrap.php'; + return $this->objectManager; + } + } +}