Skip to content

Commit

Permalink
Make NullToStrictStringFuncCallArgRector run without scope (#4792)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba authored Aug 14, 2023
1 parent 685fe90 commit 514df0a
Show file tree
Hide file tree
Showing 18 changed files with 74 additions and 82 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

exit();

Expand All @@ -15,7 +15,7 @@ function run2()
-----
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

exit();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

final class CaseInsensitiveFunctionName
{
Expand All @@ -14,7 +14,7 @@ final class CaseInsensitiveFunctionName
-----
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

final class CaseInsensitiveFunctionName
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

/**
* Crypt requires 2 args since php 5.6, when it only fill 1st arg, it will only change 1st arg
Expand All @@ -19,7 +19,7 @@ final class CryptOneArg
-----
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

/**
* Crypt requires 2 args since php 5.6, when it only fill 1st arg, it will only change 1st arg
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

final class NamedArgument
{
Expand All @@ -14,7 +14,7 @@ final class NamedArgument
-----
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

final class NamedArgument
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

final class NonStringParamType
{
Expand All @@ -14,7 +14,7 @@ final class NonStringParamType
-----
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

final class NonStringParamType
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

final class NonStringParamTypeInUseClosure
{
Expand All @@ -16,7 +16,7 @@ final class NonStringParamTypeInUseClosure
-----
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

final class NonStringParamTypeInUseClosure
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

final class PassNull
{
Expand All @@ -14,7 +14,7 @@ final class PassNull
-----
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

final class PassNull
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

final class PassNullMulti
{
Expand All @@ -14,7 +14,7 @@ final class PassNullMulti
-----
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

final class PassNullMulti
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

final class PregMatchCallable
{
public function run($regex)
{
preg_replace_callback($regex, 'value', function (array $match) use (
&$string
): string {
$innerPattern = $match['content'];
$positionDelimiter = strpos($innerPattern, '');
});
}
}

?>
-----
<?php

namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

final class PregMatchCallable
{
public function run($regex)
{
preg_replace_callback($regex, 'value', function (array $match) use (
&$string
): string {
$innerPattern = $match['content'];
$positionDelimiter = strpos((string) $innerPattern, '');
});
}
}

?>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

final class SkipConstantStringParamType
{
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

use PhpParser\Node;
use PhpParser\Node\Scalar\DNumber;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

trait SkipMethodCallOnTrait
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

final class SkipNotRegisteredFuncCallWithNamedArgument
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

use PhpParser\Node;
use PhpParser\Node\Scalar\DNumber;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

final class SkipStrReplacePassArraySubject
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Rector\Tests\Php80\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;
namespace Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\Fixture;

final class SkipStringParamType
{
Expand Down
46 changes: 14 additions & 32 deletions rules/Php81/Rector/FuncCall/NullToStrictStringFuncCallArgRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,25 @@
use PhpParser\Node\Identifier;
use PhpParser\Node\Scalar\Encapsed;
use PhpParser\Node\Scalar\String_;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\Native\NativeFunctionReflection;
use PHPStan\Type\ErrorType;
use PHPStan\Reflection\ParametersAcceptorSelector;
use PHPStan\Type\MixedType;
use PHPStan\Type\NullType;
use PHPStan\Type\Type;
use Rector\Core\NodeAnalyzer\ArgsAnalyzer;
use Rector\Core\NodeAnalyzer\PropertyFetchAnalyzer;
use Rector\Core\Rector\AbstractScopeAwareRector;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\Reflection\ReflectionResolver;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\NodeTypeResolver\PHPStan\ParametersAcceptorSelectorVariantsWrapper;
use Rector\VersionBonding\Contract\MinPhpVersionInterface;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

/**
* @see \Rector\Tests\Php81\Rector\FuncCall\NullToStrictStringFuncCallArgRector\NullToStrictStringFuncCallArgRectorTest
*/
final class NullToStrictStringFuncCallArgRector extends AbstractScopeAwareRector implements MinPhpVersionInterface
final class NullToStrictStringFuncCallArgRector extends AbstractRector implements MinPhpVersionInterface
{
/**
* @var array<string, string[]>
Expand Down Expand Up @@ -377,7 +375,7 @@ public function getNodeTypes(): array
/**
* @param FuncCall $node
*/
public function refactorWithScope(Node $node, Scope $scope): ?Node
public function refactor(Node $node): ?Node
{
if ($this->shouldSkip($node)) {
return null;
Expand All @@ -386,18 +384,18 @@ public function refactorWithScope(Node $node, Scope $scope): ?Node
$args = $node->getArgs();
$positions = $this->argsAnalyzer->hasNamedArg($args)
? $this->resolveNamedPositions($node, $args)
: $this->resolveOriginalPositions($node, $scope);
: $this->resolveOriginalPositions($node);

if ($positions === []) {
return null;
}

$classReflection = $scope->getClassReflection();
$classReflection = $this->reflectionResolver->resolveClassReflection($node);
$isTrait = $classReflection instanceof ClassReflection && $classReflection->isTrait();

$isChanged = false;
foreach ($positions as $position) {
$result = $this->processNullToStrictStringOnNodePosition($node, $args, $position, $isTrait, $scope);
$result = $this->processNullToStrictStringOnNodePosition($node, $args, $position, $isTrait);
if ($result instanceof Node) {
$node = $result;
$isChanged = true;
Expand Down Expand Up @@ -448,8 +446,7 @@ private function processNullToStrictStringOnNodePosition(
FuncCall $funcCall,
array $args,
int|string $position,
bool $isTrait,
Scope $scope
bool $isTrait
): ?FuncCall {
if (! isset($args[$position])) {
return null;
Expand Down Expand Up @@ -477,10 +474,6 @@ private function processNullToStrictStringOnNodePosition(
return null;
}

if ($this->isAnErrorTypeFromParentScope($argValue, $scope)) {
return null;
}

if ($this->shouldSkipTrait($argValue, $type, $isTrait)) {
return null;
}
Expand Down Expand Up @@ -512,37 +505,26 @@ private function shouldSkipTrait(Expr $expr, Type $type, bool $isTrait): bool
return true;
}

private function isAnErrorTypeFromParentScope(Expr $expr, Scope $scope): bool
{
$parentScope = $scope->getParentScope();
if ($parentScope instanceof Scope) {
return $parentScope->getType($expr) instanceof ErrorType;
}

return false;
}

/**
* @return int[]|string[]
*/
private function resolveOriginalPositions(FuncCall $funcCall, Scope $scope): array
private function resolveOriginalPositions(FuncCall $funcCall): array
{
$functionReflection = $this->reflectionResolver->resolveFunctionLikeReflectionFromCall($funcCall);
if (! $functionReflection instanceof NativeFunctionReflection) {
return [];
}

$parametersAcceptor = ParametersAcceptorSelectorVariantsWrapper::select(
$functionReflection,
$funcCall,
$scope
$parametersAcceptorWithPhpDocs = ParametersAcceptorSelector::combineAcceptors(
$functionReflection->getVariants()
);

$functionName = $functionReflection->getName();
$argNames = self::ARG_POSITION_NAME_NULL_TO_STRICT_STRING[$functionName];
$positions = [];

foreach ($parametersAcceptor->getParameters() as $position => $parameterReflection) {
if (in_array($parameterReflection->getName(), $argNames, true)) {
foreach ($parametersAcceptorWithPhpDocs->getParameters() as $position => $parameterReflectionWithPhpDoc) {
if (in_array($parameterReflectionWithPhpDoc->getName(), $argNames, true)) {
$positions[] = $position;
}
}
Expand Down

0 comments on commit 514df0a

Please sign in to comment.