[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

This commit is contained in:
Hugo Sales 2021-09-07 20:16:47 +00:00
parent 4e30e5aad9
commit ddb9702b1c
No known key found for this signature in database
GPG Key ID: 7D0C7EAFC9D835A0
5 changed files with 93 additions and 1 deletions

View File

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/usr/bin/env sh
root="$(git rev-parse --show-toplevel)"

View File

@ -0,0 +1,10 @@
<?php
require_once 'bootstrap.php';
use App\Kernel;
use Symfony\Component\Dotenv\Dotenv;
$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
$kernel->boot();
return $kernel->getContainer()->get('doctrine')->getManager();

View File

@ -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

View File

@ -0,0 +1,53 @@
<?php
namespace App\PHPStan;
use App\Core\DB\DB;
use App\Util\Formatting;
use Doctrine\Persistence\ObjectManager;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Name;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Type\DynamicStaticMethodReturnTypeExtension;
use PHPStan\Type\Constant\ConstantStringType;
class ClassFromTableNameDynamicStaticMethodReturnTypeExtension implements DynamicStaticMethodReturnTypeExtension
{
private ?ObjectManager $manager = null;
public function __construct(ObjectManagerResolver $resolver)
{
$this->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();
}
}
}

View File

@ -0,0 +1,20 @@
<?php
namespace App\PHPStan;
use Doctrine\Persistence\ObjectManager;
class ObjectManagerResolver
{
private ?ObjectManager $objectManager = null;
public function getManager(): ObjectManager
{
if ($this->objectManager !== null) {
return $this->objectManager;
} else {
$this->objectManager = require __DIR__ . '/../../config/phpstan-bootstrap.php';
return $this->objectManager;
}
}
}