Unite any extra reflection parsing to single ReflectionResolver service (#313)

This commit is contained in:
Tomas Votruba 2021-06-27 19:23:19 +02:00 committed by GitHub
parent 9d4c4ff6ed
commit a435716072
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 89 additions and 243 deletions

View File

@ -2,14 +2,11 @@
namespace Rector\Tests\Php70\Rector\FuncCall\NonVariableToVariableOnFunctionCallRector\Fixture;
class Invokable
{
public function __invoke(&$bar) {}
}
use Rector\Tests\Php70\Rector\FuncCall\NonVariableToVariableOnFunctionCallRector\Source\InvokableConstructorArgument;
function invokable()
{
$invokable = new Invokable();
$invokable = new InvokableConstructorArgument();
$invokable(bar());
}
@ -19,14 +16,11 @@ function invokable()
namespace Rector\Tests\Php70\Rector\FuncCall\NonVariableToVariableOnFunctionCallRector\Fixture;
class Invokable
{
public function __invoke(&$bar) {}
}
use Rector\Tests\Php70\Rector\FuncCall\NonVariableToVariableOnFunctionCallRector\Source\InvokableConstructorArgument;
function invokable()
{
$invokable = new Invokable();
$invokable = new InvokableConstructorArgument();
$bar = bar();
$invokable($bar);
}

View File

@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Rector\Tests\Php70\Rector\FuncCall\NonVariableToVariableOnFunctionCallRector\Source;
final class InvokableConstructorArgument
{
public function __invoke(&$bar)
{
}
}

View File

@ -13,8 +13,8 @@ use PHPStan\Reflection\FunctionReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\Php\PhpFunctionReflection;
use Rector\CodingStyle\NodeAnalyzer\SpreadVariablesCollector;
use Rector\Core\PHPStan\Reflection\CallReflectionResolver;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\Reflection\ReflectionResolver;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
@ -25,7 +25,7 @@ final class UnSpreadOperatorRector extends AbstractRector
{
public function __construct(
private SpreadVariablesCollector $spreadVariablesCollector,
private CallReflectionResolver $callReflectionResolver,
private ReflectionResolver $reflectionResolver
) {
}
@ -101,18 +101,18 @@ CODE_SAMPLE
private function processUnspreadOperatorMethodCallArgs(MethodCall $methodCall): ?MethodCall
{
$functionLikeReflection = $this->callReflectionResolver->resolveCall($methodCall);
if ($functionLikeReflection === null) {
$methodReflection = $this->reflectionResolver->resolveMethodReflectionFromMethodCall($methodCall);
if (! $methodReflection instanceof MethodReflection) {
return null;
}
// skip those in vendor
if ($this->skipForVendor($functionLikeReflection)) {
if ($this->skipForVendor($methodReflection)) {
return null;
}
$spreadParameterReflections = $this->spreadVariablesCollector->resolveFromMethodReflection(
$functionLikeReflection
$methodReflection
);
if ($spreadParameterReflections === []) {
return null;

View File

@ -6,13 +6,14 @@ namespace Rector\Defluent\NodeAnalyzer;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Reflection\MethodReflection;
use Rector\Core\PHPStan\Reflection\CallReflectionResolver;
use PHPStan\Reflection\ReflectionProvider;
use Rector\Core\Reflection\ReflectionResolver;
use Rector\Defluent\Contract\ValueObject\FirstCallFactoryAwareInterface;
final class SameClassMethodCallAnalyzer
{
public function __construct(
private CallReflectionResolver $callReflectionResolver
private ReflectionResolver $reflectionResolver,
) {
}
@ -24,10 +25,10 @@ final class SameClassMethodCallAnalyzer
// are method calls located in the same class?
$classOfClassMethod = [];
foreach ($chainMethodCalls as $chainMethodCall) {
$functionLikeReflection = $this->callReflectionResolver->resolveCall($chainMethodCall);
$methodReflection = $this->reflectionResolver->resolveMethodReflectionFromMethodCall($chainMethodCall);
if ($functionLikeReflection instanceof MethodReflection) {
$declaringClass = $functionLikeReflection->getDeclaringClass();
if ($methodReflection instanceof MethodReflection) {
$declaringClass = $methodReflection->getDeclaringClass();
$classOfClassMethod[] = $declaringClass->getName();
} else {
$classOfClassMethod[] = null;

View File

@ -18,8 +18,8 @@ use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ParameterReflection;
use PHPStan\Type\Type;
use PHPStan\Type\VerbosityLevel;
use Rector\Core\PHPStan\Reflection\CallReflectionResolver;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\Reflection\ReflectionResolver;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
@ -29,7 +29,7 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
final class DowngradeNamedArgumentRector extends AbstractRector
{
public function __construct(
private CallReflectionResolver $callReflectionResolver,
private ReflectionResolver $reflectionResolver
) {
}
@ -99,7 +99,7 @@ CODE_SAMPLE
private function removeNamedArguments(MethodCall | StaticCall | New_ $node, array $args): ?Node
{
if ($node instanceof New_) {
$methodReflection = $this->callReflectionResolver->resolveConstructor($node);
$methodReflection = $this->reflectionResolver->resolveMethodReflectionFromNew($node);
if (! $methodReflection instanceof MethodReflection) {
return null;
}
@ -107,12 +107,12 @@ CODE_SAMPLE
return $this->processRemoveNamedArgument($methodReflection, $node, $args);
}
$callerReflection = $this->callReflectionResolver->resolveCall($node);
if ($callerReflection === null) {
$functionLikeReflection = $this->reflectionResolver->resolveFunctionLikeReflectionFromCall($node);
if ($functionLikeReflection === null) {
return null;
}
return $this->processRemoveNamedArgument($callerReflection, $node, $args);
return $this->processRemoveNamedArgument($functionLikeReflection, $node, $args);
}
/**

View File

@ -22,8 +22,8 @@ use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ParameterReflection;
use PHPStan\Reflection\ParametersAcceptor;
use PHPStan\Type\MixedType;
use Rector\Core\PHPStan\Reflection\CallReflectionResolver;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\Reflection\ReflectionResolver;
use Rector\Naming\Naming\VariableNaming;
use Rector\NodeNestingScope\ParentScopeFinder;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -39,9 +39,9 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
final class NonVariableToVariableOnFunctionCallRector extends AbstractRector
{
public function __construct(
private CallReflectionResolver $callReflectionResolver,
private VariableNaming $variableNaming,
private ParentScopeFinder $parentScopeFinder
private ParentScopeFinder $parentScopeFinder,
private ReflectionResolver $reflectionResolver
) {
}
@ -107,18 +107,19 @@ final class NonVariableToVariableOnFunctionCallRector extends AbstractRector
}
/**
* @param FuncCall|MethodCall|StaticCall $node
*
* @return Expr[]
*/
private function getNonVariableArguments(Node $node): array
private function getNonVariableArguments(FuncCall|MethodCall|StaticCall $call): array
{
$arguments = [];
$parametersAcceptor = $this->callReflectionResolver->resolveParametersAcceptor(
$this->callReflectionResolver->resolveCall($node),
);
$functionLikeReflection = $this->reflectionResolver->resolveFunctionLikeReflectionFromCall($call);
if ($functionLikeReflection === null) {
return [];
}
$parametersAcceptor = $functionLikeReflection->getVariants()[0] ?? null;
if (! $parametersAcceptor instanceof ParametersAcceptor) {
return [];
}
@ -126,7 +127,7 @@ final class NonVariableToVariableOnFunctionCallRector extends AbstractRector
/** @var ParameterReflection $parameterReflection */
foreach ($parametersAcceptor->getParameters() as $key => $parameterReflection) {
// omitted optional parameter
if (! isset($node->args[$key])) {
if (! isset($call->args[$key])) {
continue;
}
@ -134,7 +135,7 @@ final class NonVariableToVariableOnFunctionCallRector extends AbstractRector
continue;
}
$argument = $node->args[$key]->value;
$argument = $call->args[$key]->value;
if ($this->isVariableLikeNode($argument)) {
continue;

View File

@ -14,8 +14,8 @@ use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\Php\PhpMethodReflection;
use PHPStan\Reflection\Type\UnionTypeMethodReflection;
use Rector\Core\NodeAnalyzer\VariadicAnalyzer;
use Rector\Core\PHPStan\Reflection\CallReflectionResolver;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\Reflection\ReflectionResolver;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
@ -28,8 +28,8 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
final class RemoveExtraParametersRector extends AbstractRector
{
public function __construct(
private CallReflectionResolver $callReflectionResolver,
private VariadicAnalyzer $variadicAnalyzer
private VariadicAnalyzer $variadicAnalyzer,
private ReflectionResolver $reflectionResolver
) {
}
@ -58,7 +58,7 @@ final class RemoveExtraParametersRector extends AbstractRector
}
// unreliable count of arguments
$functionLikeReflection = $this->callReflectionResolver->resolveCall($node);
$functionLikeReflection = $this->reflectionResolver->resolveFunctionLikeReflectionFromCall($node);
if ($functionLikeReflection instanceof UnionTypeMethodReflection) {
return null;
}

View File

@ -9,7 +9,6 @@ use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Reflection\MethodReflection;
use Rector\Core\PHPStan\Reflection\CallReflectionResolver;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\Reflection\ReflectionResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -28,7 +27,6 @@ final class OptionalParametersAfterRequiredRector extends AbstractRector
public function __construct(
private RequireOptionalParamResolver $requireOptionalParamResolver,
private ArgumentSorter $argumentSorter,
private CallReflectionResolver $callReflectionResolver,
private ReflectionResolver $reflectionResolver
) {
}
@ -137,7 +135,7 @@ CODE_SAMPLE
private function refactorMethodCall(MethodCall $methodCall): ?MethodCall
{
$methodReflection = $this->callReflectionResolver->resolveCall($methodCall);
$methodReflection = $this->reflectionResolver->resolveFunctionLikeReflectionFromCall($methodCall);
if (! $methodReflection instanceof MethodReflection) {
return null;
}

View File

@ -21,8 +21,8 @@ use PHPStan\Type\MixedType;
use PHPStan\Type\NullType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\UnionType;
use Rector\Core\PHPStan\Reflection\CallReflectionResolver;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\Reflection\ReflectionResolver;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\TypeDeclaration\NodeAnalyzer\TypeNodeUnwrapper;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
@ -35,7 +35,7 @@ final class ReturnTypeFromStrictTypedCallRector extends AbstractRector
{
public function __construct(
private TypeNodeUnwrapper $typeNodeUnwrapper,
private CallReflectionResolver $callReflectionResolver
private ReflectionResolver $reflectionResolver
) {
}
@ -179,7 +179,7 @@ CODE_SAMPLE
private function resolveMethodCallReturnNode(MethodCall | StaticCall | FuncCall $call): ?Node
{
$methodReflection = $this->callReflectionResolver->resolveCall($call);
$methodReflection = $this->reflectionResolver->resolveFunctionLikeReflectionFromCall($call);
if ($methodReflection === null) {
return null;
}

View File

@ -24,7 +24,7 @@ use PHPStan\Type\Type;
use PHPStan\Type\VoidType;
use Rector\Core\PhpParser\AstResolver;
use Rector\Core\PhpParser\Printer\BetterStandardPrinter;
use Rector\Core\PHPStan\Reflection\CallReflectionResolver;
use Rector\Core\Reflection\ReflectionResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\NodeTypeResolver;
use Rector\NodeTypeResolver\PHPStan\Type\TypeFactory;
@ -41,9 +41,9 @@ final class ReturnedNodesReturnTypeInferer implements ReturnTypeInfererInterface
private SimpleCallableNodeTraverser $simpleCallableNodeTraverser,
private TypeFactory $typeFactory,
private SplArrayFixedTypeNarrower $splArrayFixedTypeNarrower,
private CallReflectionResolver $callReflectionResolver,
private AstResolver $reflectionAstResolver,
private BetterStandardPrinter $betterStandardPrinter
private BetterStandardPrinter $betterStandardPrinter,
private ReflectionResolver $reflectionResolver
) {
}
@ -143,20 +143,12 @@ final class ReturnedNodesReturnTypeInferer implements ReturnTypeInfererInterface
return new MixedType();
}
$callReflection = $this->callReflectionResolver->resolveCall($return->expr);
if ($callReflection === null) {
$methodReflection = $this->reflectionResolver->resolveMethodReflectionFromMethodCall($return->expr);
if (! $methodReflection instanceof MethodReflection) {
return new MixedType();
}
if ($callReflection instanceof MethodReflection) {
return $this->resolveClassMethod($callReflection, $originalFunctionLike);
}
if ($callReflection instanceof PhpFunctionReflection) {
return $this->resolveFunction($callReflection, $originalFunctionLike);
}
return new MixedType();
return $this->resolveClassMethod($methodReflection, $originalFunctionLike);
}
private function isArrayTypeMixed(Type $type): bool
@ -202,21 +194,4 @@ final class ReturnedNodesReturnTypeInferer implements ReturnTypeInfererInterface
return $this->inferFunctionLike($classMethod);
}
private function resolveFunction(PhpFunctionReflection $phpFunctionReflection, FunctionLike $functionLike): Type
{
$function = $this->reflectionAstResolver->resolveFunctionFromFunctionReflection($phpFunctionReflection);
if (! $function instanceof Function_) {
return new MixedType();
}
$classMethodCacheKey = $this->betterStandardPrinter->print($function);
$functionLikeCacheKey = $this->betterStandardPrinter->print($functionLike);
if ($classMethodCacheKey === $functionLikeCacheKey) {
return new MixedType();
}
return $this->inferFunctionLike($function);
}
}

View File

@ -26,7 +26,7 @@ use PHPStan\Type\Type;
use Rector\Core\PhpParser\Comparing\NodeComparator;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\Core\PhpParser\Node\NodeFactory;
use Rector\Core\PHPStan\Reflection\CallReflectionResolver;
use Rector\Core\Reflection\ReflectionResolver;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Symplify\Astral\NodeTraverser\SimpleCallableNodeTraverser;
@ -44,8 +44,8 @@ final class ClassMethodAssignManipulator
private NodeFactory $nodeFactory,
private NodeNameResolver $nodeNameResolver,
private VariableManipulator $variableManipulator,
private CallReflectionResolver $callReflectionResolver,
private NodeComparator $nodeComparator
private NodeComparator $nodeComparator,
private ReflectionResolver $reflectionResolver
) {
}
@ -294,13 +294,14 @@ final class ClassMethodAssignManipulator
return false;
}
$methodReflection = $this->callReflectionResolver->resolveCall($node);
$methodReflection = $this->reflectionResolver->resolveMethodReflectionFromMethodCall($node);
if (! $methodReflection instanceof MethodReflection) {
return false;
}
$variableName = $this->nodeNameResolver->getName($variable);
$parametersAcceptor = $this->callReflectionResolver->resolveParametersAcceptor($methodReflection);
$parametersAcceptor = $methodReflection->getVariants()[0] ?? null;
if (! $parametersAcceptor instanceof ParametersAcceptor) {
return false;
}
@ -348,9 +349,12 @@ final class ClassMethodAssignManipulator
private function isParameterReferencedInMethodReflection(New_ $new, int $argumentPosition): bool
{
$methodReflection = $this->callReflectionResolver->resolveConstructor($new);
$parametersAcceptor = $this->callReflectionResolver->resolveParametersAcceptor($methodReflection);
$methodReflection = $this->reflectionResolver->resolveMethodReflectionFromNew($new);
if (! $methodReflection instanceof MethodReflection) {
return false;
}
$parametersAcceptor = $methodReflection->getVariants()[0] ?? null;
if (! $parametersAcceptor instanceof ParametersAcceptor) {
return false;
}

View File

@ -20,7 +20,7 @@ use PhpParser\Node\Stmt\Property;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\Core\PhpParser\NodeFinder\PropertyFetchFinder;
use Rector\Core\PHPStan\Reflection\CallReflectionResolver;
use Rector\Core\Reflection\ReflectionResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\ReadWrite\Guard\VariableToConstantGuard;
use Rector\ReadWrite\NodeAnalyzer\ReadWritePropertyAnalyzer;
@ -39,7 +39,7 @@ final class PropertyManipulator
private PhpDocInfoFactory $phpDocInfoFactory,
private TypeChecker $typeChecker,
private PropertyFetchFinder $propertyFetchFinder,
private CallReflectionResolver $callReflectionResolver,
private ReflectionResolver $reflectionResolver
) {
}
@ -122,7 +122,7 @@ final class PropertyManipulator
private function isFoundByRefParam(MethodCall | StaticCall $node): bool
{
$functionLikeReflection = $this->callReflectionResolver->resolveCall($node);
$functionLikeReflection = $this->reflectionResolver->resolveFunctionLikeReflectionFromCall($node);
if ($functionLikeReflection === null) {
return false;
}

View File

@ -1,144 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\Core\PHPStan\Reflection;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Name;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ParametersAcceptor;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Type\ObjectType;
use PHPStan\Type\ThisType;
use PHPStan\Type\TypeWithClassName;
use PHPStan\Type\UnionType;
use Rector\Core\PHPStan\Reflection\TypeToCallReflectionResolver\TypeToCallReflectionResolverRegistry;
use Rector\Core\ValueObject\MethodName;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\NodeTypeResolver;
final class CallReflectionResolver
{
public function __construct(
private NodeNameResolver $nodeNameResolver,
private NodeTypeResolver $nodeTypeResolver,
private ReflectionProvider $reflectionProvider,
private TypeToCallReflectionResolverRegistry $typeToCallReflectionResolverRegistry
) {
}
public function resolveConstructor(New_ $new): ?MethodReflection
{
$scope = $new->getAttribute(AttributeKey::SCOPE);
if (! $scope instanceof Scope) {
return null;
}
$classType = $this->nodeTypeResolver->resolve($new->class);
if ($classType instanceof UnionType) {
return $this->matchConstructorMethodInUnionType($classType, $scope);
}
if (! $classType->hasMethod(MethodName::CONSTRUCT)->yes()) {
return null;
}
return $classType->getMethod(MethodName::CONSTRUCT, $scope);
}
public function resolveCall(FuncCall | MethodCall | StaticCall $call): MethodReflection | FunctionReflection | null
{
if ($call instanceof FuncCall) {
return $this->resolveFunctionCall($call);
}
return $this->resolveMethodCall($call);
}
public function resolveParametersAcceptor(
FunctionReflection | MethodReflection | null $reflection
): ?ParametersAcceptor {
if ($reflection === null) {
return null;
}
return $reflection->getVariants()[0];
}
private function matchConstructorMethodInUnionType(UnionType $unionType, Scope $scope): ?MethodReflection
{
foreach ($unionType->getTypes() as $unionedType) {
if (! $unionedType instanceof TypeWithClassName) {
continue;
}
if (! $unionedType->hasMethod(MethodName::CONSTRUCT)->yes()) {
continue;
}
return $unionedType->getMethod(MethodName::CONSTRUCT, $scope);
}
return null;
}
private function resolveFunctionCall(FuncCall $funcCall): FunctionReflection | MethodReflection | null
{
/** @var Scope|null $scope */
$scope = $funcCall->getAttribute(AttributeKey::SCOPE);
if ($funcCall->name instanceof Name) {
if ($this->reflectionProvider->hasFunction($funcCall->name, $scope)) {
return $this->reflectionProvider->getFunction($funcCall->name, $scope);
}
return null;
}
if (! $scope instanceof Scope) {
return null;
}
$funcCallNameType = $scope->getType($funcCall->name);
return $this->typeToCallReflectionResolverRegistry->resolve($funcCallNameType, $scope);
}
private function resolveMethodCall(MethodCall | StaticCall $expr): ?MethodReflection
{
$scope = $expr->getAttribute(AttributeKey::SCOPE);
if (! $scope instanceof Scope) {
return null;
}
$methodName = $this->nodeNameResolver->getName($expr->name);
if ($methodName === null) {
return null;
}
$classType = $this->nodeTypeResolver->resolve($expr instanceof MethodCall ? $expr->var : $expr->class);
if ($classType instanceof ThisType) {
$classType = $classType->getStaticObjectType();
}
if ($classType instanceof ObjectType) {
if (! $this->reflectionProvider->hasClass($classType->getClassName())) {
return null;
}
$classReflection = $this->reflectionProvider->getClass($classType->getClassName());
if ($classReflection->hasMethod($methodName)) {
return $classReflection->getMethod($methodName, $scope);
}
}
return null;
}
}

View File

@ -8,6 +8,7 @@ use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Name;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Analyser\Scope;
@ -16,6 +17,7 @@ use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Type\TypeUtils;
use PHPStan\Type\TypeWithClassName;
use Rector\Core\PHPStan\Reflection\TypeToCallReflectionResolver\TypeToCallReflectionResolverRegistry;
use Rector\Core\ValueObject\MethodName;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -27,7 +29,8 @@ final class ReflectionResolver
public function __construct(
private ReflectionProvider $reflectionProvider,
private NodeTypeResolver $nodeTypeResolver,
private NodeNameResolver $nodeNameResolver
private NodeNameResolver $nodeNameResolver,
private TypeToCallReflectionResolverRegistry $typeToCallReflectionResolverRegistry
) {
}
@ -147,18 +150,20 @@ final class ReflectionResolver
return $this->resolveMethodReflection($newClassType->getClassName(), MethodName::CONSTRUCT, $scope);
}
private function resolveFunctionReflectionFromFuncCall(FuncCall $funcCall): ?FunctionReflection
private function resolveFunctionReflectionFromFuncCall(FuncCall $funcCall): FunctionReflection | MethodReflection | null
{
$functionName = $this->nodeNameResolver->getName($funcCall);
if ($functionName === null) {
$scope = $funcCall->getAttribute(AttributeKey::SCOPE);
if ($funcCall->name instanceof Name) {
if ($this->reflectionProvider->hasFunction($funcCall->name, $scope)) {
return $this->reflectionProvider->getFunction($funcCall->name, $scope);
}
return null;
}
$functionNameFullyQualified = new FullyQualified($functionName);
if (! $this->reflectionProvider->hasFunction($functionNameFullyQualified, null)) {
return null;
}
return $this->reflectionProvider->getFunction($functionNameFullyQualified, null);
// fallback to callable
$funcCallNameType = $scope->getType($funcCall->name);
return $this->typeToCallReflectionResolverRegistry->resolve($funcCallNameType, $scope);
}
}