Skip to content

Commit

Permalink
[DeadCode] Skip RemoveUnusedNonEmptyArrayBeforeForeachRector on array…
Browse files Browse the repository at this point in the history
… param has default null (#433)

Co-authored-by: GitHub Action <action@github.com>
  • Loading branch information
samsonasik and actions-user committed Jul 14, 2021
1 parent b6039d7 commit 4f2d2d1
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 34 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace Rector\Tests\DeadCode\Rector\If_\RemoveUnusedNonEmptyArrayBeforeForeachRector\Fixture;

function run(array $values = null) {
if (!empty($values)) {
foreach ($values as $value) {
echo $value;
}
}
}

?>
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use PHPStan\Type\UnionType;
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\NodeAnalyzer\ParamAnalyzer;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\ValueObject\MethodName;
use Rector\Core\ValueObject\PhpVersionFeature;
Expand All @@ -39,7 +40,8 @@ final class DateTimeToDateTimeInterfaceRector extends AbstractRector
];

public function __construct(
private PhpDocTypeChanger $phpDocTypeChanger
private PhpDocTypeChanger $phpDocTypeChanger,
private ParamAnalyzer $paramAnalyzer
) {
}

Expand Down Expand Up @@ -110,7 +112,7 @@ public function refactor(Node $node): ?Node
private function refactorParamTypeHint(Param $param): void
{
$fullyQualified = new FullyQualified('DateTimeInterface');
if ($param->type instanceof NullableType) {
if ($this->paramAnalyzer->isNullable($param)) {
$param->type = new NullableType($fullyQualified);
return;
}
Expand All @@ -121,7 +123,7 @@ private function refactorParamTypeHint(Param $param): void
private function refactorParamDocBlock(Param $param, ClassMethod $classMethod): void
{
$types = [new ObjectType('DateTime'), new ObjectType('DateTimeImmutable')];
if ($param->type instanceof NullableType) {
if ($this->paramAnalyzer->isNullable($param)) {
$types[] = new NullType();
}

Expand Down
11 changes: 7 additions & 4 deletions rules/DeadCode/UselessIfCondBeforeForeachDetector.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
use PhpParser\Node\Expr\BooleanNot;
use PhpParser\Node\Expr\Empty_;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\NullableType;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\If_;
use PHPStan\Type\ArrayType;
use Rector\Core\NodeAnalyzer\ParamAnalyzer;
use Rector\Core\PhpParser\Comparing\NodeComparator;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\NodeTypeResolver\NodeTypeResolver;
Expand All @@ -25,7 +25,8 @@ final class UselessIfCondBeforeForeachDetector
public function __construct(
private NodeTypeResolver $nodeTypeResolver,
private NodeComparator $nodeComparator,
private BetterNodeFinder $betterNodeFinder
private BetterNodeFinder $betterNodeFinder,
private ParamAnalyzer $paramAnalyzer
) {
}

Expand Down Expand Up @@ -61,8 +62,10 @@ public function isMatchingNotEmpty(If_ $if, Expr $foreachExpr): bool
if (! $previousParam instanceof Param) {
return true;
}

return ! $previousParam->type instanceof NullableType;
if ($this->paramAnalyzer->isNullable($previousParam)) {
return false;
}
return ! $this->paramAnalyzer->hasDefaultNull($previousParam);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use PhpParser\Node\Stmt\Function_;
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\NodeAnalyzer\ParamAnalyzer;
use Rector\Core\Rector\AbstractRector;
use Rector\DowngradePhp71\TypeDeclaration\PhpDocFromTypeDeclarationDecorator;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
Expand All @@ -24,7 +25,8 @@ final class DowngradeNullableTypeDeclarationRector extends AbstractRector
{
public function __construct(
private PhpDocTypeChanger $phpDocTypeChanger,
private PhpDocFromTypeDeclarationDecorator $phpDocFromTypeDeclarationDecorator
private PhpDocFromTypeDeclarationDecorator $phpDocFromTypeDeclarationDecorator,
private ParamAnalyzer $paramAnalyzer
) {
}

Expand Down Expand Up @@ -90,23 +92,9 @@ public function refactor(Node $node): ?Node
return null;
}

private function isNullableParam(Param $param): bool
{
if ($param->variadic) {
return false;
}

if ($param->type === null) {
return false;
}

// Check it is the union type
return $param->type instanceof NullableType;
}

private function refactorParamType(Param $param, ClassMethod | Function_ | Closure $functionLike): bool
{
if (! $this->isNullableParam($param)) {
if (! $this->paramAnalyzer->isNullable($param)) {
return false;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassReflection;
use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger;
use Rector\Core\NodeAnalyzer\ParamAnalyzer;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\ValueObject\MethodName;
use Rector\NodeTypeResolver\Node\AttributeKey;
Expand All @@ -31,7 +32,8 @@
final class DowngradeContravariantArgumentTypeRector extends AbstractRector
{
public function __construct(
private PhpDocTypeChanger $phpDocTypeChanger
private PhpDocTypeChanger $phpDocTypeChanger,
private ParamAnalyzer $paramAnalyzer
) {
}

Expand Down Expand Up @@ -150,7 +152,7 @@ private function getDifferentParamTypeFromAncestorClass(Param $param, FunctionLi
/** @var Node $paramType */
$paramType = $param->type;

if ($param->type instanceof NullableType) {
if ($this->paramAnalyzer->isNullable($param)) {
/** @var NullableType $nullableType */
$nullableType = $paramType;
$paramTypeName = $this->getName($nullableType->type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use PhpParser\Node\Stmt\Property;
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use Rector\BetterPhpDocParser\ValueObject\PhpDocAttributeKey;
use Rector\Core\NodeAnalyzer\ParamAnalyzer;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\ValueObject\MethodName;
use Rector\Core\ValueObject\PhpVersionFeature;
Expand All @@ -34,7 +35,8 @@ final class ClassPropertyAssignToConstructorPromotionRector extends AbstractRect
public function __construct(
private PromotedPropertyCandidateResolver $promotedPropertyCandidateResolver,
private VariableRenamer $variableRenamer,
private VarTagRemover $varTagRemover
private VarTagRemover $varTagRemover,
private ParamAnalyzer $paramAnalyzer
) {
}

Expand Down Expand Up @@ -166,9 +168,13 @@ private function shouldSkipParam(Param $param): bool
return true;
}

$type = $param->type instanceof NullableType
? $param->type->type
: $param->type;
if ($this->paramAnalyzer->isNullable($param)) {
/** @var NullableType $type */
$type = $param->type;
$type = $type->type;
} else {
$type = $param->type;
}

return $type instanceof Identifier && $this->isName($type, 'callable');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use PHPStan\Type\MixedType;
use PHPStan\Type\NullType;
use PHPStan\Type\Type;
use Rector\Core\NodeAnalyzer\ParamAnalyzer;
use Rector\Core\NodeManipulator\ClassMethodPropertyFetchManipulator;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\Core\ValueObject\MethodName;
Expand All @@ -42,7 +43,8 @@ public function __construct(
private TypeFactory $typeFactory,
private StaticTypeMapper $staticTypeMapper,
private NodeTypeResolver $nodeTypeResolver,
private BetterNodeFinder $betterNodeFinder
private BetterNodeFinder $betterNodeFinder,
private ParamAnalyzer $paramAnalyzer
) {
}

Expand Down Expand Up @@ -107,10 +109,13 @@ private function resolveParamTypeToPHPStanType(Param $param): Type
return new MixedType();
}

if ($param->type instanceof NullableType) {
if ($this->paramAnalyzer->isNullable($param)) {
/** @var NullableType $type */
$type = $param->type;

$types = [];
$types[] = new NullType();
$types[] = $this->staticTypeMapper->mapPhpParserNodePHPStanType($param->type->type);
$types[] = $this->staticTypeMapper->mapPhpParserNodePHPStanType($type->type);

return $this->typeFactory->createMixedPassedOrUnionType($types);
}
Expand Down Expand Up @@ -152,7 +157,7 @@ function (Node $node) use ($propertyName, &$paramStaticType): ?int {

private function isParamNullable(Param $param): bool
{
if ($param->type instanceof NullableType) {
if ($this->paramAnalyzer->isNullable($param)) {
return true;
}

Expand Down
24 changes: 23 additions & 1 deletion src/NodeAnalyzer/ParamAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,21 @@
namespace Rector\Core\NodeAnalyzer;

use PhpParser\Node;
use PhpParser\Node\Expr\ConstFetch;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\NullableType;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\Core\PhpParser\Comparing\NodeComparator;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\Core\PhpParser\Node\Value\ValueResolver;

final class ParamAnalyzer
{
public function __construct(
private BetterNodeFinder $betterNodeFinder,
private NodeComparator $nodeComparator
private NodeComparator $nodeComparator,
private ValueResolver $valueResolver
) {
}

Expand Down Expand Up @@ -45,4 +49,22 @@ public function hasPropertyPromotion(array $params): bool

return false;
}

public function isNullable(Param $param): bool
{
if ($param->variadic) {
return false;
}

if ($param->type === null) {
return false;
}

return $param->type instanceof NullableType;
}

public function hasDefaultNull(Param $param): bool
{
return $param->default instanceof ConstFetch && $this->valueResolver->isNull($param->default);
}
}

0 comments on commit 4f2d2d1

Please sign in to comment.