Skip to content

Commit

Permalink
Fix param castable to string rule
Browse files Browse the repository at this point in the history
  • Loading branch information
schlndh committed Jun 17, 2024
1 parent 7d9800c commit 322de33
Show file tree
Hide file tree
Showing 21 changed files with 940 additions and 375 deletions.
12 changes: 10 additions & 2 deletions conf/config.level5.neon
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ conditionalTags:
phpstan.rules.rule: %featureToggles.arrayValues%
PHPStan\Rules\Functions\CallUserFuncRule:
phpstan.rules.rule: %featureToggles.callUserFunc%
PHPStan\Rules\Functions\ParameterCastableToStringFunctionRule:
PHPStan\Rules\Functions\ParameterCastableToStringRule:
phpstan.rules.rule: %featureToggles.checkParameterCastableToStringFunctions%
PHPStan\Rules\Functions\ImplodeParameterCastableToStringRule:
phpstan.rules.rule: %featureToggles.checkParameterCastableToStringFunctions%
PHPStan\Rules\Functions\SortParameterCastableToStringRule:
phpstan.rules.rule: %featureToggles.checkParameterCastableToStringFunctions%

rules:
Expand Down Expand Up @@ -45,4 +49,8 @@ services:
tags:
- phpstan.rules.rule
-
class: PHPStan\Rules\Functions\ParameterCastableToStringFunctionRule
class: PHPStan\Rules\Functions\ParameterCastableToStringRule
-
class: PHPStan\Rules\Functions\ImplodeParameterCastableToStringRule
-
class: PHPStan\Rules\Functions\SortParameterCastableToStringRule
2 changes: 2 additions & 0 deletions conf/config.neon
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,8 @@ services:

-
class: PHPStan\Rules\FunctionReturnTypeCheck
-
class: PHPStan\Rules\ParameterCastableToStringCheck

-
class: PHPStan\Rules\Generics\CrossCheckInterfacesHelper
Expand Down
4 changes: 2 additions & 2 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -1823,15 +1823,15 @@ parameters:
-
message: """
#^Instantiation of deprecated class PHPStan\\\\Rules\\\\Functions\\\\ImplodeFunctionRule\\:
Replaced by PHPStan\\\\Rules\\\\Functions\\\\ParameterCastableToStringFunctionRule$#
Replaced by PHPStan\\\\Rules\\\\Functions\\\\ImplodeParameterCastableToStringRuleTest$#
"""
count: 1
path: tests/PHPStan/Rules/Functions/ImplodeFunctionRuleTest.php

-
message: """
#^Return type of method PHPStan\\\\Rules\\\\Functions\\\\ImplodeFunctionRuleTest\\:\\:getRule\\(\\) has typehint with deprecated class PHPStan\\\\Rules\\\\Functions\\\\ImplodeFunctionRule\\:
Replaced by PHPStan\\\\Rules\\\\Functions\\\\ParameterCastableToStringFunctionRule$#
Replaced by PHPStan\\\\Rules\\\\Functions\\\\ImplodeParameterCastableToStringRuleTest$#
"""
count: 1
path: tests/PHPStan/Rules/Functions/ImplodeFunctionRuleTest.php
Expand Down
2 changes: 1 addition & 1 deletion src/Rules/Functions/ImplodeFunctionRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
use function sprintf;

/**
* @deprecated Replaced by PHPStan\Rules\Functions\ParameterCastableToStringFunctionRule
* @deprecated Replaced by PHPStan\Rules\Functions\ImplodeParameterCastableToStringRuleTest
* @implements Rule<Node\Expr\FuncCall>
*/
class ImplodeFunctionRule implements Rule
Expand Down
117 changes: 117 additions & 0 deletions src/Rules/Functions/ImplodeParameterCastableToStringRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Functions;

use PhpParser\Node;
use PhpParser\Node\Expr\FuncCall;
use PHPStan\Analyser\ArgumentsNormalizer;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ParametersAcceptorSelector;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\ParameterCastableToStringCheck;
use PHPStan\Rules\Rule;
use PHPStan\Type\Type;
use function array_key_exists;
use function count;
use function in_array;
use function sprintf;

/**
* @implements Rule<Node\Expr\FuncCall>
*/
class ImplodeParameterCastableToStringRule implements Rule
{

public function __construct(
private ReflectionProvider $reflectionProvider,
private ParameterCastableToStringCheck $parameterCastableToStringCheck,
)
{
}

public function getNodeType(): string
{
return FuncCall::class;
}

public function processNode(Node $node, Scope $scope): array
{
if (!($node->name instanceof Node\Name)) {
return [];
}

if (!$this->reflectionProvider->hasFunction($node->name, $scope)) {
return [];
}

$functionReflection = $this->reflectionProvider->getFunction($node->name, $scope);
$functionName = $functionReflection->getName();
if (!in_array($functionName, ['implode', 'join'], true)) {
return [];
}

$origArgs = $node->getArgs();
$parametersAcceptor = ParametersAcceptorSelector::selectFromArgs(
$scope,
$origArgs,
$functionReflection->getVariants(),
$functionReflection->getNamedArgumentsVariants(),
);

$normalizedFuncCall = ArgumentsNormalizer::reorderFuncArguments($parametersAcceptor, $node);

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

$normalizedArgs = $normalizedFuncCall->getArgs();
$errorMessage = 'Parameter %s of function %s expects array<string>, %s given.';
if (count($normalizedArgs) === 1) {
$argsToCheck = [0 => $normalizedArgs[0]];
} elseif (count($normalizedArgs) === 2) {
$argsToCheck = [1 => $normalizedArgs[1]];
} else {
return [];
}

$origNamedArgs = [];
foreach ($origArgs as $arg) {
if ($arg->unpack || $arg->name === null) {
continue;
}

$origNamedArgs[$arg->name->toString()] = $arg;
}

$errors = [];

foreach ($argsToCheck as $argIdx => $arg) {
// implode has weird variants, so $array has to be fixed. It's especially weird with named arguments.
if (array_key_exists('array', $origNamedArgs)) {
$argName = '$array';
} elseif (array_key_exists('separator', $origNamedArgs) && count($origArgs) === 1) {
$argName = '$separator';
} else {
$argName = sprintf('#%d $array', $argIdx + 1);
}

$error = $this->parameterCastableToStringCheck->checkParameter(
$arg,
$scope,
$errorMessage,
static fn (Type $t) => $t->toString(),
$functionName,
$argName,
);

if ($error === null) {
continue;
}

$errors[] = $error;
}

return $errors;
}

}
170 changes: 0 additions & 170 deletions src/Rules/Functions/ParameterCastableToStringFunctionRule.php

This file was deleted.

0 comments on commit 322de33

Please sign in to comment.