Skip to content

Commit

Permalink
forbidEnumInFunctionArguments: skip those detected by PHPStan itself
Browse files Browse the repository at this point in the history
  • Loading branch information
janedbal committed Nov 11, 2024
1 parent aefdbff commit 619037e
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 37 deletions.
27 changes: 2 additions & 25 deletions src/Rule/ForbidEnumInFunctionArgumentsRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,41 +18,26 @@
use function array_key_exists;
use function count;
use function implode;
use const SORT_REGULAR;

/**
* @template-implements Rule<FuncCall>
*/
class ForbidEnumInFunctionArgumentsRule implements Rule
{

private const ANY_ARGUMENT = -1;

private const REASON_IMPLICIT_TO_STRING = 'as the function causes implicit __toString conversion which is not supported for enums';
private const REASON_UNPREDICTABLE_RESULT = 'as the function causes unexpected results'; // https://3v4l.org/YtGVa
private const REASON_SKIPS_ENUMS = 'as the function will skip any enums and produce warning';

/**
* Function name -> [forbidden argument position, reason]]
*/
private const FUNCTION_MAP = [
'array_intersect' => [self::ANY_ARGUMENT, self::REASON_IMPLICIT_TO_STRING],
'array_intersect_assoc' => [self::ANY_ARGUMENT, self::REASON_IMPLICIT_TO_STRING],
'array_diff' => [self::ANY_ARGUMENT, self::REASON_IMPLICIT_TO_STRING],
'array_diff_assoc' => [self::ANY_ARGUMENT, self::REASON_IMPLICIT_TO_STRING],
'array_unique' => [0, self::REASON_IMPLICIT_TO_STRING],
'array_combine' => [0, self::REASON_IMPLICIT_TO_STRING],
'sort' => [0, self::REASON_UNPREDICTABLE_RESULT],
'asort' => [0, self::REASON_UNPREDICTABLE_RESULT],
'arsort' => [0, self::REASON_UNPREDICTABLE_RESULT],
'natsort' => [0, self::REASON_IMPLICIT_TO_STRING],
'natcasesort' => [0, self::REASON_IMPLICIT_TO_STRING],
'array_count_values' => [0, self::REASON_SKIPS_ENUMS],
'array_fill_keys' => [0, self::REASON_IMPLICIT_TO_STRING],
'array_flip' => [0, self::REASON_SKIPS_ENUMS],

// https://github.com/phpstan/phpstan/issues/11883
'array_product' => [0, self::REASON_UNPREDICTABLE_RESULT],
'array_sum' => [0, self::REASON_UNPREDICTABLE_RESULT],
'implode' => [1, self::REASON_IMPLICIT_TO_STRING],
];

private ReflectionProvider $reflectionProvider;
Expand Down Expand Up @@ -103,10 +88,6 @@ public function processNode(Node $node, Scope $scope): array
foreach ($funcCall->getArgs() as $position => $argument) {
$argumentType = $scope->getType($argument->value);

if ($functionName === 'array_unique' && $position === 1 && $argumentType->getConstantScalarValues() === [SORT_REGULAR]) {
return []; // this edgecase seems to be working fine
}

if (!$this->matchesPosition((int) $position, $forbiddenArgumentPosition)) {
continue;
}
Expand All @@ -130,10 +111,6 @@ public function processNode(Node $node, Scope $scope): array

private function matchesPosition(int $position, int $forbiddenArgumentPosition): bool
{
if ($forbiddenArgumentPosition === self::ANY_ARGUMENT) {
return true;
}

return $position === $forbiddenArgumentPosition;
}

Expand Down
24 changes: 12 additions & 12 deletions tests/Rule/data/ForbidEnumInFunctionArgumentsRule/code.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,23 @@ public function testAllFunctions()
$enums2 = [SomeEnum::Bar];
$enums3 = [SomeEnum::Baz];

array_intersect($enums1, $enums2, $enums3); // error: Arguments 1, 2, 3 in array_intersect() cannot contain enum as the function causes implicit __toString conversion which is not supported for enums
array_intersect_assoc($enums1, $enums2, $enums3); // error: Arguments 1, 2, 3 in array_intersect_assoc() cannot contain enum as the function causes implicit __toString conversion which is not supported for enums
array_diff($enums1, $enums2, $enums3); // error: Arguments 1, 2, 3 in array_diff() cannot contain enum as the function causes implicit __toString conversion which is not supported for enums
array_diff_assoc($enums1, $enums2, $enums3); // error: Arguments 1, 2, 3 in array_diff_assoc() cannot contain enum as the function causes implicit __toString conversion which is not supported for enums
array_unique($enums1); // error: Argument 1 in array_unique() cannot contain enum as the function causes implicit __toString conversion which is not supported for enums
array_combine($enums2, $enums3); // error: Argument 1 in array_combine() cannot contain enum as the function causes implicit __toString conversion which is not supported for enums
array_intersect($enums1, $enums2, $enums3); // reported by native PHPStan
array_intersect_assoc($enums1, $enums2, $enums3); // reported by native PHPStan
array_diff($enums1, $enums2, $enums3); // reported by native PHPStan
array_diff_assoc($enums1, $enums2, $enums3); // reported by native PHPStan
array_unique($enums1); // reported by native PHPStan
array_combine($enums2, $enums3); // reported by native PHPStan
sort($enums1); // error: Argument 1 in sort() cannot contain enum as the function causes unexpected results
asort($enums1); // error: Argument 1 in asort() cannot contain enum as the function causes unexpected results
arsort($enums1); // error: Argument 1 in arsort() cannot contain enum as the function causes unexpected results
natsort($enums1); // error: Argument 1 in natsort() cannot contain enum as the function causes implicit __toString conversion which is not supported for enums
natcasesort($enums1); // error: Argument 1 in natcasesort() cannot contain enum as the function causes implicit __toString conversion which is not supported for enums
array_count_values($enums1); // error: Argument 1 in array_count_values() cannot contain enum as the function will skip any enums and produce warning
array_fill_keys($enums1, 1); // error: Argument 1 in array_fill_keys() cannot contain enum as the function causes implicit __toString conversion which is not supported for enums
array_flip($enums1); // error: Argument 1 in array_flip() cannot contain enum as the function will skip any enums and produce warning
natsort($enums1); // reported by native PHPStan
natcasesort($enums1); // reported by native PHPStan
array_count_values($enums1); // reported by native PHPStan
array_fill_keys($enums1, 1); // reported by native PHPStan
array_flip($enums1); // reported by native PHPStan
array_product($enums1); // error: Argument 1 in array_product() cannot contain enum as the function causes unexpected results
array_sum($enums1); // error: Argument 1 in array_sum() cannot contain enum as the function causes unexpected results
implode('', $enums1); // error: Argument 2 in implode() cannot contain enum as the function causes implicit __toString conversion which is not supported for enums
implode('', $enums1); // reported by native PHPStan
in_array(SomeEnum::Bar, $enums1);
}

Expand Down

0 comments on commit 619037e

Please sign in to comment.