Skip to content

Commit

Permalink
[PHPStan 1.0] use selectFromArgs() for function reflectoin to get pas…
Browse files Browse the repository at this point in the history
…sed by reference positoins (#1113)
  • Loading branch information
TomasVotruba committed Oct 30, 2021
1 parent cfcd16a commit 95ad690
Showing 1 changed file with 22 additions and 25 deletions.
47 changes: 22 additions & 25 deletions packages/ReadWrite/Guard/VariableToConstantGuard.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Name;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\FunctionReflection;
use PHPStan\Reflection\Native\NativeFunctionReflection;
use PHPStan\Reflection\ParameterReflection;
use PHPStan\Reflection\ParametersAcceptorSelector;
use PHPStan\Reflection\ReflectionProvider;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\Node\AttributeKey;
use ReflectionFunction;
use Symplify\PackageBuilder\Reflection\PrivatesAccessor;

final class VariableToConstantGuard
{
Expand All @@ -26,7 +26,6 @@ final class VariableToConstantGuard
public function __construct(
private NodeNameResolver $nodeNameResolver,
private ReflectionProvider $reflectionProvider,
private PrivatesAccessor $privatesAccessor
) {
}

Expand All @@ -52,7 +51,11 @@ public function isReadArg(Arg $arg): bool

$functionReflection = $this->reflectionProvider->getFunction($functionName, $argScope);

$referenceParametersPositions = $this->resolveFunctionReferencePositions($functionReflection);
$referenceParametersPositions = $this->resolveFunctionReferencePositions(
$functionReflection,
[$arg],
$argScope
);
if ($referenceParametersPositions === []) {
// no reference always only write
return true;
Expand All @@ -63,37 +66,31 @@ public function isReadArg(Arg $arg): bool
}

/**
* @param Arg[] $args
* @return int[]
*/
private function resolveFunctionReferencePositions(FunctionReflection $functionReflection): array
{
private function resolveFunctionReferencePositions(
FunctionReflection $functionReflection,
array $args,
Scope $scope
): array {
if (isset($this->referencePositionsByFunctionName[$functionReflection->getName()])) {
return $this->referencePositionsByFunctionName[$functionReflection->getName()];
}

// this is needed, as native function reflection does not have access to referenced parameters
if ($functionReflection instanceof NativeFunctionReflection) {
$functionName = $functionReflection->getName();
if (! function_exists($functionName)) {
return [];
}

$nativeFunctionReflection = new ReflectionFunction($functionName);
} else {
$nativeFunctionReflection = $this->privatesAccessor->getPrivateProperty($functionReflection, 'reflection');
}

$referencePositions = [];

foreach ($nativeFunctionReflection->getParameters() as $position => $reflectionParameter) {
if (! $reflectionParameter->isPassedByReference()) {
$parametersAcceptor = ParametersAcceptorSelector::selectFromArgs(
$scope,
$args,
$functionReflection->getVariants()
);
foreach ($parametersAcceptor->getParameters() as $position => $parameterReflection) {
/** @var ParameterReflection $parameterReflection */
if (! $parameterReflection->passedByReference()->yes()) {
continue;
}

if (! is_int($position)) {
throw new ShouldNotHappenException();
}

$referencePositions[] = $position;
}

Expand Down

0 comments on commit 95ad690

Please sign in to comment.