add few php-parser patches; use MethodReflector to avoid class_exist code running

This commit is contained in:
TomasVotruba 2017-09-21 11:44:04 +02:00
parent 2c53ce3f8e
commit d83b4e6e3e
7 changed files with 95 additions and 34 deletions

View File

@ -53,7 +53,9 @@
"extra": {
"patches": {
"roave/better-reflection": {
"parser type miss-match with dev version": "patches/better-reflection-php-parser.patch"
"parser type miss-match with dev-version 1": "patches/better-reflection-php-parser-memoizing-parser.patch",
"parser type miss-match with dev-version 2": "patches/better-reflection-php-parser-reflection-function-abstract.patch",
"parser type miss-match with dev-version 3": "patches/better-reflection-php-parser-reflection-parameter.patch"
}
}
}

View File

@ -0,0 +1,33 @@
<?php declare(strict_types=1);
namespace Rector\BetterReflection\Reflector;
use Rector\BetterReflection\SourceLocator\SourceLocatorFactory;
use Roave\BetterReflection\Reflection\ReflectionMethod;
use Roave\BetterReflection\Reflector\ClassReflector;
use Roave\BetterReflection\Reflector\Exception\IdentifierNotFound;
final class MethodReflector
{
/**
* @var ClassReflector
*/
private $classReflector;
public function __construct(ClassReflector $classReflector)
{
$this->classReflector = $classReflector;
}
public function reflectClassMethod(string $class, string $method): ?ReflectionMethod
{
try {
$classReflection = $this->classReflector->reflect($class);
} catch (IdentifierNotFound $identifierNotFoundException) {
// class doesn't exist
return null;
}
return $classReflection->getImmediateMethods()[$method] ?? null;
}
}

View File

@ -6,9 +6,12 @@ use PhpParser\Node\Expr\Closure;
use PhpParser\Node\FunctionLike;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassLike;
use Rector\BetterReflection\Reflector\MethodReflector;
use Rector\NodeTypeResolver\TypesExtractor\ConstructorPropertyTypesExtractor;
use ReflectionFunction;
use ReflectionMethod;
use Roave\BetterReflection\Reflection\ReflectionMethod;
use Roave\BetterReflection\Reflector\ClassReflector;
use Roave\BetterReflection\Reflector\Exception\IdentifierNotFound;
/**
* Inspired by https://github.com/nikic/PHP-Parser/blob/9373a8e9f551516bc8e42aedeacd1b4f635d27fc/lib/PhpParser/NameContext.php.
@ -35,9 +38,23 @@ final class TypeContext
*/
private $constructorPropertyTypesExtractor;
public function __construct(ConstructorPropertyTypesExtractor $constructorPropertyTypesExtractor)
{
/**
* @var ClassReflector
*/
private $classReflector;
/**
* @var MethodReflector
*/
private $methodReflector;
public function __construct(
ConstructorPropertyTypesExtractor $constructorPropertyTypesExtractor,
ClassReflector $classReflector,
MethodReflector $methodReflector
) {
$this->constructorPropertyTypesExtractor = $constructorPropertyTypesExtractor;
$this->classReflector = $classReflector;
$this->methodReflector = $methodReflector;
}
public function startFile(): void
@ -91,25 +108,22 @@ final class TypeContext
}
/**
* @return ReflectionFunction|ReflectionMethod|null
* @return \Roave\BetterReflection\Reflection\ReflectionFunction|ReflectionMethod|null
*/
private function getFunctionReflection(FunctionLike $functionLikeNode)
{
if ($this->classLikeNode) {
$className = $this->classLikeNode->namespacedName->toString();
if (! class_exists($className)) {
return null;
}
if ($functionLikeNode instanceof Closure) {
return null;
}
$className = $this->classLikeNode->namespacedName->toString();
$methodName = (string) $functionLikeNode->name;
return new ReflectionMethod($className, $methodName);
return $this->methodReflector->reflectClassMethod($className, $methodName);
}
// todo: use BetterReflection\FunctionReflector?
return new ReflectionFunction((string) $functionLikeNode->name);
}
}

View File

@ -9,8 +9,9 @@ use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use ReflectionClass;
use Roave\BetterReflection\BetterReflection;
use PHPStan\Reflection\MethodsClassReflectionExtension;
use Rector\BetterReflection\Reflector\MethodReflector;
use Roave\BetterReflection\Reflection\ReflectionMethod;
use Roave\BetterReflection\Reflector\ClassReflector;
use Roave\BetterReflection\Reflector\Exception\IdentifierNotFound;
@ -20,10 +21,15 @@ final class ConstructorPropertyTypesExtractor
* @var ClassReflector
*/
private $classReflector;
/**
* @var MethodReflector
*/
private $methodReflector;
public function __construct(ClassReflector $classReflector)
public function __construct(ClassReflector $classReflector, MethodReflector $methodReflector)
{
$this->classReflector = $classReflector;
$this->methodReflector = $methodReflector;
}
/**
@ -54,31 +60,15 @@ final class ConstructorPropertyTypesExtractor
{
$className = $classNode->namespacedName->toString();
try {
$classReflection = $this->classReflector->reflect($className);
} catch (IdentifierNotFound $identifierNotFoundException) {
// class doesn't exist
$constructorMethodReflection = $this->methodReflector->reflectClassMethod($className, '__construct');
if ($constructorMethodReflection === null) {
return [];
}
// use DI
dump($classReflection);
die;
// todo: add check for nonexisting classes when it comes
if (! class_exists($className)) {
return [];
}
dump($classReflection);
die;
$constructorMethod = (new ReflectionClass($className))->getConstructor();
$parametersWithTypes = [];
if ($constructorMethod) {
foreach ($constructorMethod->getParameters() as $parameterReflection) {
if ($constructorMethodReflection) {
foreach ($constructorMethodReflection->getParameters() as $parameterReflection) {
$parameterName = $parameterReflection->getName();
$parameterType = (string) $parameterReflection->getType();

View File

@ -0,0 +1,11 @@
--- /dev/null
+++ roave/better-reflection/src/Reflection/ReflectionFunctionAbstract.php
@@ -149,7 +149,7 @@
return self::CLOSURE_NAME;
}
- return $this->node->name;
+ return (string) $this->node->name;
}
/**

View File

@ -0,0 +1,11 @@
--- /dev/null
+++ roave/better-reflection/src/Reflection/ReflectionParameter.php
@@ -262,7 +262,7 @@
*/
public function getName() : string
{
- return $this->node->name;
+ return (string) $this->node->type;
}
/**