Skip to content

Commit d9b383f

Browse files
authored
Make ArrayFindArgVisitor supports array_any() and array_all()
1 parent 13798c2 commit d9b383f

File tree

6 files changed

+183
-5
lines changed

6 files changed

+183
-5
lines changed

src/Parser/ArrayFindArgVisitor.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public function enterNode(Node $node): ?Node
1515
{
1616
if ($node instanceof Node\Expr\FuncCall && $node->name instanceof Node\Name) {
1717
$functionName = $node->name->toLowerString();
18-
if (in_array($functionName, ['array_find', 'array_find_key'], true)) {
18+
if (in_array($functionName, ['array_all', 'array_any', 'array_find', 'array_find_key'], true)) {
1919
$args = $node->getRawArgs();
2020
if (isset($args[0])) {
2121
$args[0]->setAttribute(self::ATTRIBUTE_NAME, true);

tests/PHPStan/Rules/Functions/CallToFunctionParametersRuleTest.php

+64-4
Original file line numberDiff line numberDiff line change
@@ -886,6 +886,66 @@ public function testArrayFilterCallback(bool $checkExplicitMixed): void
886886
$this->analyse([__DIR__ . '/data/array_filter_callback.php'], $errors);
887887
}
888888

889+
public function testArrayAllCallback(): void
890+
{
891+
if (PHP_VERSION_ID < 80400) {
892+
$this->markTestSkipped('Test skipped on lower version than 8.4 (needs array_all function)');
893+
}
894+
895+
$this->analyse([__DIR__ . '/data/array_all.php'], [
896+
[
897+
'Parameter #2 $callback of function array_all expects callable(1|2, \'bar\'|\'foo\'): bool, Closure(string, int): bool given.',
898+
22,
899+
],
900+
[
901+
'Parameter #2 $callback of function array_all expects callable(1|2, \'bar\'|\'foo\'): bool, Closure(string, int): bool given.',
902+
30,
903+
],
904+
[
905+
'Parameter #2 $callback of function array_all expects callable(1|2, \'bar\'|\'foo\'): bool, Closure(int, string): (\'bar\'|\'foo\') given.',
906+
36,
907+
],
908+
[
909+
'Parameter #2 $callback of function array_all expects callable(mixed, int|string): bool, Closure(string, array): false given.',
910+
52,
911+
],
912+
[
913+
'Parameter #2 $callback of function array_all expects callable(mixed, int|string): bool, Closure(string, int): array{} given.',
914+
55,
915+
],
916+
]);
917+
}
918+
919+
public function testArrayAnyCallback(): void
920+
{
921+
if (PHP_VERSION_ID < 80400) {
922+
$this->markTestSkipped('Test skipped on lower version than 8.4 (needs array_any function)');
923+
}
924+
925+
$this->analyse([__DIR__ . '/data/array_any.php'], [
926+
[
927+
'Parameter #2 $callback of function array_any expects callable(1|2, \'bar\'|\'foo\'): bool, Closure(string, int): bool given.',
928+
22,
929+
],
930+
[
931+
'Parameter #2 $callback of function array_any expects callable(1|2, \'bar\'|\'foo\'): bool, Closure(string, int): bool given.',
932+
30,
933+
],
934+
[
935+
'Parameter #2 $callback of function array_any expects callable(1|2, \'bar\'|\'foo\'): bool, Closure(int, string): (\'bar\'|\'foo\') given.',
936+
36,
937+
],
938+
[
939+
'Parameter #2 $callback of function array_any expects callable(mixed, int|string): bool, Closure(string, array): false given.',
940+
52,
941+
],
942+
[
943+
'Parameter #2 $callback of function array_any expects callable(mixed, int|string): bool, Closure(string, int): array{} given.',
944+
55,
945+
],
946+
]);
947+
}
948+
889949
public function testArrayFindCallback(): void
890950
{
891951
$this->analyse([__DIR__ . '/data/array_find.php'], [
@@ -903,11 +963,11 @@ public function testArrayFindCallback(): void
903963
],
904964
[
905965
'Parameter #2 $callback of function array_find expects callable(mixed, int|string): bool, Closure(string, array): false given.',
906-
49,
966+
52,
907967
],
908968
[
909969
'Parameter #2 $callback of function array_find expects callable(mixed, int|string): bool, Closure(string, int): array{} given.',
910-
52,
970+
55,
911971
],
912972
]);
913973
}
@@ -929,11 +989,11 @@ public function testArrayFindKeyCallback(): void
929989
],
930990
[
931991
'Parameter #2 $callback of function array_find_key expects callable(mixed, int|string): bool, Closure(string, array): false given.',
932-
49,
992+
52,
933993
],
934994
[
935995
'Parameter #2 $callback of function array_find_key expects callable(mixed, int|string): bool, Closure(string, int): array{} given.',
936-
52,
996+
55,
937997
],
938998
]);
939999
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php declare(strict_types = 1); // lint >= 8.4
2+
3+
// ok
4+
array_all(
5+
['foo' => 1, 'bar' => 2],
6+
function($value, $key) {
7+
return $key === 0;
8+
}
9+
);
10+
11+
// ok
12+
array_all(
13+
['foo' => 1, 'bar' => 2],
14+
function(int $value, string $key) {
15+
return $key === 0;
16+
}
17+
);
18+
19+
// bad parameters
20+
array_all(
21+
['foo' => 1, 'bar' => 2],
22+
function(string $value, int $key): bool {
23+
return $key === 0;
24+
}
25+
);
26+
27+
// bad parameters
28+
array_all(
29+
['foo' => 1, 'bar' => 2],
30+
fn (string $item, int $key) => $key === 0,
31+
);
32+
33+
// bad return type
34+
array_all(
35+
['foo' => 1, 'bar' => 2],
36+
function(int $value, string $key) {
37+
return $key;
38+
},
39+
);
40+
41+
if (is_array($array)) {
42+
// ok
43+
array_all($array, fn ($value, $key) => $key === 0);
44+
45+
// ok
46+
array_all($array, fn (string $value, int $key) => $key === 0);
47+
48+
// ok
49+
array_all($array, fn (string $value) => $value === 'foo');
50+
51+
// bad parameters
52+
array_all($array, fn (string $item, array $key) => $key === 0);
53+
54+
// bad return type
55+
array_all($array, fn (string $value, int $key): array => []);
56+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php declare(strict_types = 1); // lint >= 8.4
2+
3+
// ok
4+
array_any(
5+
['foo' => 1, 'bar' => 2],
6+
function($value, $key) {
7+
return $key === 0;
8+
}
9+
);
10+
11+
// ok
12+
array_any(
13+
['foo' => 1, 'bar' => 2],
14+
function(int $value, string $key) {
15+
return $key === 0;
16+
}
17+
);
18+
19+
// bad parameters
20+
array_any(
21+
['foo' => 1, 'bar' => 2],
22+
function(string $value, int $key): bool {
23+
return $key === 0;
24+
}
25+
);
26+
27+
// bad parameters
28+
array_any(
29+
['foo' => 1, 'bar' => 2],
30+
fn (string $item, int $key) => $key === 0,
31+
);
32+
33+
// bad return type
34+
array_any(
35+
['foo' => 1, 'bar' => 2],
36+
function(int $value, string $key) {
37+
return $key;
38+
},
39+
);
40+
41+
if (is_array($array)) {
42+
// ok
43+
array_any($array, fn ($value, $key) => $key === 0);
44+
45+
// ok
46+
array_any($array, fn (string $value, int $key) => $key === 0);
47+
48+
// ok
49+
array_any($array, fn (string $value) => $value === 'foo');
50+
51+
// bad parameters
52+
array_any($array, fn (string $item, array $key) => $key === 0);
53+
54+
// bad return type
55+
array_any($array, fn (string $value, int $key): array => []);
56+
}

tests/PHPStan/Rules/Functions/data/array_find.php

+3
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ function(int $value, string $key) {
4545
// ok
4646
array_find($array, fn (string $value, int $key) => $key === 0);
4747

48+
// ok
49+
array_find($array, fn (string $value) => $key === 0);
50+
4851
// bad parameters
4952
array_find($array, fn (string $item, array $key) => $key === 0);
5053

tests/PHPStan/Rules/Functions/data/array_find_key.php

+3
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ function(int $value, string $key) {
4545
// ok
4646
array_find_key($array, fn (string $value, int $key) => $key === 0);
4747

48+
// ok
49+
array_find_key($array, fn (string $value) => $value === 'foo');
50+
4851
// bad parameters
4952
array_find_key($array, fn (string $item, array $key) => $key === 0);
5053

0 commit comments

Comments
 (0)