Skip to content

Commit

Permalink
NarrowPublicClassMethodParamTypeRule: Take default value into account (
Browse files Browse the repository at this point in the history
…#4)

* Added failling test

* better test

* fix

* Update MethodCallArgTypesCollector.php

* Update NarrowPrivateClassMethodParamTypeRule.php

* Update CollectorMetadataPrinter.php

* run rectorrunr rector
  • Loading branch information
staabm committed Jun 16, 2024
1 parent a8d7852 commit 4b2b573
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 6 deletions.
12 changes: 10 additions & 2 deletions src/Collector/MethodCall/MethodCallArgTypesCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Rector\TypePerfect\Collector\MethodCall;

use PhpParser\Node\Identifier;
use PHPStan\Reflection\ExtendedMethodReflection;
use PhpParser\Node;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
Expand Down Expand Up @@ -34,7 +36,13 @@ public function getNodeType(): string
*/
public function processNode(Node $node, Scope $scope): ?array
{
if ($node->getArgs() === []) {
if ($node->isFirstClassCallable() || $node->getArgs() === [] || !$node->name instanceof Identifier) {
return null;
}

$methodCalledOnType = $scope->getType($node->var);
$methodReflection = $scope->getMethodReflection($methodCalledOnType, $node->name->name);
if (!$methodReflection instanceof ExtendedMethodReflection) {
return null;
}

Expand All @@ -45,7 +53,7 @@ public function processNode(Node $node, Scope $scope): ?array

$classMethodReference = $this->createClassMethodReference($classMethodCallReference);

$stringArgTypesString = $this->collectorMetadataPrinter->printArgTypesAsString($node, $scope);
$stringArgTypesString = $this->collectorMetadataPrinter->printArgTypesAsString($node, $methodReflection, $scope);
return [$classMethodReference, $stringArgTypesString];
}

Expand Down
18 changes: 15 additions & 3 deletions src/Printer/CollectorMetadataPrinter.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
use PhpParser\Node\UnionType;
use PhpParser\PrettyPrinter\Standard;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ExtendedMethodReflection;
use PHPStan\Reflection\ParametersAcceptorSelector;
use PHPStan\Type\ArrayType;
use PHPStan\Type\BooleanType;
use PHPStan\Type\ClassStringType;
Expand All @@ -25,6 +27,7 @@
use PHPStan\Type\ObjectType;
use PHPStan\Type\ThisType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeCombinator;
use PHPStan\Type\UnionType as PHPStanUnionType;
use PHPStan\Type\VerbosityLevel;
use Rector\TypePerfect\Enum\Types\ResolvedTypes;
Expand All @@ -38,11 +41,13 @@ public function __construct()
$this->printerStandard = new Standard();
}

public function printArgTypesAsString(MethodCall $methodCall, Scope $scope): string
public function printArgTypesAsString(MethodCall $methodCall, ExtendedMethodReflection $extendedMethodReflection, Scope $scope): string
{
$stringArgTypes = [];
$parametersAcceptor = ParametersAcceptorSelector::selectFromArgs($scope, $methodCall->getArgs(), $extendedMethodReflection->getVariants(), $extendedMethodReflection->getNamedArgumentsVariants());
$parameters = $parametersAcceptor->getParameters();

foreach ($methodCall->getArgs() as $arg) {
$stringArgTypes = [];
foreach ($methodCall->getArgs() as $i => $arg) {
$argType = $scope->getType($arg->value);

// we have no idea, nothing we can do
Expand All @@ -62,6 +67,13 @@ public function printArgTypesAsString(MethodCall $methodCall, Scope $scope): str
$argType = new ObjectType($argType->getClassName());
}

if (array_key_exists($i, $parameters)) {
$defaultValueType = $parameters[$i]->getDefaultValue();
if ($defaultValueType instanceof Type) {
$argType = TypeCombinator::union($argType, $defaultValueType);
}
}

$stringArgTypes[] = $this->printTypeToString($argType);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Rules/NarrowPrivateClassMethodParamTypeRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public function getNodeType(): string
*/
public function processNode(Node $node, Scope $scope): array
{
if (! $this->configuration->isNarrowEnabled()) {
if (! $this->configuration->isNarrowEnabled() || $node->isFirstClassCallable()) {
return [];
}

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

declare(strict_types=1);

namespace Rector\TypePerfect\Tests\Rules\NarrowPublicClassMethodParamTypeRule\Fixture;

class HandleDefaultValue {
public function takesUnionWithDifferentDefaultValue(
int|string $value = "hallo"
): bool
{
return true;
}

public function takesUnionWithSameTypeDefaultValue(
int|string $value = 123
): bool
{
return true;
}

static public function run(): void
{
$o = new HandleDefaultValue();
$o->takesUnionWithDifferentDefaultValue(1);

$o = new HandleDefaultValue();
$o->takesUnionWithSameTypeDefaultValue(1);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ public static function provideData(): Iterator
yield [[
__DIR__ . '/Fixture/SkipSelf.php',
], []];

$argErrorMessage = sprintf(NarrowPublicClassMethodParamTypeRule::ERROR_MESSAGE, 'int');
yield [[
__DIR__ . '/Fixture/HandleDefaultValue.php'
], [[$argErrorMessage, 15]]];
}

/**
Expand Down

0 comments on commit 4b2b573

Please sign in to comment.