Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

declare(strict_types=1);

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\AddMethodCallBasedStrictParamTypeRector\FixtureIntersection;

final class CoverIntersection
{
public function run(array $values): void
{
$items = [];

foreach ($values as $value) {
$items[] = 10;
}

$this->nextItems($items);
}

private function nextItems($items): void
{
}
}

?>
-----
<?php

declare(strict_types=1);

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\AddMethodCallBasedStrictParamTypeRector\FixtureIntersection;

final class CoverIntersection
{
public function run(array $values): void
{
$items = [];

foreach ($values as $value) {
$items[] = 10;
}

$this->nextItems($items);
}

private function nextItems(array $items): void
{
}
}

?>
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,9 @@ private function resolveExceptionArgumentPosition(Name $exceptionName): ?int
$extendedMethodReflection->getVariants()
);

foreach ($extendedParametersAcceptor->getParameters() as $position => $parameterReflectionWithPhpDoc) {
$parameterType = $parameterReflectionWithPhpDoc->getType();
$className = ClassNameFromObjectTypeResolver::resolve($parameterReflectionWithPhpDoc->getType());
foreach ($extendedParametersAcceptor->getParameters() as $position => $extendedParameterReflection) {
$parameterType = $extendedParameterReflection->getType();
$className = ClassNameFromObjectTypeResolver::resolve($extendedParameterReflection->getType());

if ($className === null) {
continue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ public function refactor(Node $node): ?Node
}

$hasChanged = false;
foreach ($node->getConstants() as $constant) {
if (! $constant->isFinal()) {
foreach ($node->getConstants() as $classConst) {
if (! $classConst->isFinal()) {
continue;
}

$this->visibilityManipulator->removeFinal($constant);
$this->visibilityManipulator->removeFinal($classConst);
$hasChanged = true;
}

Expand Down
4 changes: 2 additions & 2 deletions rules/Php71/Rector/FuncCall/RemoveExtraParametersRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,8 @@ private function resolveMaximumAllowedParameterCount(
MethodReflection | FunctionReflection $functionLikeReflection
): int {
$parameterCounts = [0];
foreach ($functionLikeReflection->getVariants() as $variant) {
$parameterCounts[] = count($variant->getParameters());
foreach ($functionLikeReflection->getVariants() as $parametersAcceptor) {
$parameterCounts[] = count($parametersAcceptor->getParameters());
}

return max($parameterCounts);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,8 @@ private function isNativeBooleanReturnTypeFuncCall(FuncCall $funcCall): bool
return false;
}

foreach ($functionReflection->getVariants() as $variant) {
if (! $variant->getNativeReturnType()->isBoolean()->yes()) {
foreach ($functionReflection->getVariants() as $extendedParametersAcceptor) {
if (! $extendedParametersAcceptor->getNativeReturnType()->isBoolean()->yes()) {
return false;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@
use PhpParser\Node\Stmt\Function_;
use PhpParser\Node\Stmt\Return_;
use PhpParser\NodeVisitor;
use PHPStan\Type\Accessory\AccessoryArrayListType;
use PHPStan\Type\ArrayType;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\MixedType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
Expand Down Expand Up @@ -151,23 +149,17 @@ public function refactor(Node $node): ?Node
return $node;
}

private function matchArrayObjectType(Type $returnedType): ?Type
private function matchArrayObjectType(Type $type): ?Type
{
if ($returnedType instanceof IntersectionType) {
foreach ($returnedType->getTypes() as $intersectionedType) {
if ($intersectionedType instanceof AccessoryArrayListType) {
continue;
}

if ($intersectionedType instanceof ArrayType && $intersectionedType->getItemType() instanceof ObjectType) {
return $intersectionedType->getItemType();
}
if (! $type instanceof ArrayType) {
return null;
}

return null;
}
if (! $type->getItemType() instanceof ObjectType) {
return null;
}

return null;
return $type->getItemType();
}

private function isVariableExclusivelyArrayDimAssigned(
Expand Down
4 changes: 2 additions & 2 deletions src/NodeAnalyzer/VariadicAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ public function hasVariadicParameters(FuncCall | StaticCall | MethodCall $call):

private function hasVariadicVariant(MethodReflection | FunctionReflection $functionLikeReflection): bool
{
foreach ($functionLikeReflection->getVariants() as $variant) {
foreach ($functionLikeReflection->getVariants() as $parametersAcceptor) {
// can be any number of arguments → nothing to limit here
if ($variant->isVariadic()) {
if ($parametersAcceptor->isVariadic()) {
return true;
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/NodeCollector/NodeAnalyzer/ArrayCallableMethodMatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,8 +178,8 @@ private function resolveClassContextType(
$extendedMethodReflection->getVariants()
);

foreach ($extendedParametersAcceptor->getParameters() as $parameterReflectionWithPhpDoc) {
if (! $parameterReflectionWithPhpDoc->getDefaultValue() instanceof Type) {
foreach ($extendedParametersAcceptor->getParameters() as $extendedParameterReflection) {
if (! $extendedParameterReflection->getDefaultValue() instanceof Type) {
return new MixedType();
}
}
Expand Down
62 changes: 62 additions & 0 deletions src/NodeTypeResolver/NodeTypeCorrector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

declare(strict_types=1);

namespace Rector\NodeTypeResolver;

use PHPStan\Type\Accessory\AccessoryArrayListType;
use PHPStan\Type\IntersectionType;
use PHPStan\Type\Type;
use Rector\NodeTypeResolver\NodeTypeCorrector\AccessoryNonEmptyArrayTypeCorrector;
use Rector\NodeTypeResolver\NodeTypeCorrector\AccessoryNonEmptyStringTypeCorrector;
use Rector\NodeTypeResolver\NodeTypeCorrector\GenericClassStringTypeCorrector;

/**
* This service correct unnecessary intersection/union types that do not bring any value.
* We focus on scalar types like "array", "string", "int" etc.,
* to print them as valid type declarations.
*/
final readonly class NodeTypeCorrector
{
public function __construct(
private AccessoryNonEmptyStringTypeCorrector $accessoryNonEmptyStringTypeCorrector,
private GenericClassStringTypeCorrector $genericClassStringTypeCorrector,
private AccessoryNonEmptyArrayTypeCorrector $accessoryNonEmptyArrayTypeCorrector,
) {
}

public function correctType(Type $type): Type
{
$type = $this->accessoryNonEmptyStringTypeCorrector->correct($type);
$type = $this->genericClassStringTypeCorrector->correct($type);

$type = $this->removeAccessoryArrayListType($type);

return $this->accessoryNonEmptyArrayTypeCorrector->correct($type);
}

private function removeAccessoryArrayListType(Type $type): Type
{
if (! $type instanceof IntersectionType) {
return $type;
}

$cleanTypes = [];
foreach ($type->getTypes() as $intersectionType) {
if ($intersectionType instanceof AccessoryArrayListType) {
continue;
}

$cleanTypes[] = $intersectionType;
}

// dump($cleanTypes);
// die;

if (count($cleanTypes) === 1) {
return $cleanTypes[0];
}

return new IntersectionType($cleanTypes);
}
}
21 changes: 4 additions & 17 deletions src/NodeTypeResolver/NodeTypeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,6 @@
use Rector\NodeTypeResolver\Contract\NodeTypeResolverAwareInterface;
use Rector\NodeTypeResolver\Contract\NodeTypeResolverInterface;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\NodeTypeCorrector\AccessoryNonEmptyArrayTypeCorrector;
use Rector\NodeTypeResolver\NodeTypeCorrector\AccessoryNonEmptyStringTypeCorrector;
use Rector\NodeTypeResolver\NodeTypeCorrector\GenericClassStringTypeCorrector;
use Rector\NodeTypeResolver\PHPStan\ObjectWithoutClassTypeWithParentTypes;
use Rector\Php\PhpVersionProvider;
use Rector\StaticTypeMapper\ValueObject\Type\AliasedObjectType;
Expand All @@ -80,10 +77,8 @@ final class NodeTypeResolver
public function __construct(
private readonly ObjectTypeSpecifier $objectTypeSpecifier,
private readonly ClassAnalyzer $classAnalyzer,
private readonly GenericClassStringTypeCorrector $genericClassStringTypeCorrector,
private readonly NodeTypeCorrector $nodeTypeCorrector,
private readonly ReflectionProvider $reflectionProvider,
private readonly AccessoryNonEmptyStringTypeCorrector $accessoryNonEmptyStringTypeCorrector,
private readonly AccessoryNonEmptyArrayTypeCorrector $accessoryNonEmptyArrayTypeCorrector,
private readonly RenamedClassesDataCollector $renamedClassesDataCollector,
private readonly NodeNameResolver $nodeNameResolver,
private readonly PhpVersionProvider $phpVersionProvider,
Expand Down Expand Up @@ -201,7 +196,7 @@ public function getType(Node $node): Type
$type = $this->resolveByNodeTypeResolvers($node);

if ($type instanceof Type) {
$type = $this->correctType($type);
$type = $this->nodeTypeCorrector->correctType($type);

if ($type instanceof ObjectType) {
$scope = $node->getAttribute(AttributeKey::SCOPE);
Expand Down Expand Up @@ -236,7 +231,7 @@ public function getType(Node $node): Type
return new MixedType();
}

$type = $this->correctType($scope->getType($node));
$type = $this->nodeTypeCorrector->correctType($scope->getType($node));

// hot fix for phpstan not resolving chain method calls
if (! $node instanceof MethodCall) {
Expand Down Expand Up @@ -284,7 +279,7 @@ public function getNativeType(Expr $expr): Type
return new ObjectWithoutClassType();
}

return $this->correctType($type);
return $this->nodeTypeCorrector->correctType($type);
}

return $this->resolveNativeUnionType($type);
Expand Down Expand Up @@ -372,14 +367,6 @@ public function isMethodStaticCallOrClassMethodObjectType(Node $node, ObjectType
return $classReflection->hasTraitUse($objectType->getClassName());
}

private function correctType(Type $type): Type
{
$type = $this->accessoryNonEmptyStringTypeCorrector->correct($type);
$type = $this->genericClassStringTypeCorrector->correct($type);

return $this->accessoryNonEmptyArrayTypeCorrector->correct($type);
}

/**
* Allow pull type from
*
Expand Down