Skip to content

Commit 5ac0f96

Browse files
zonuexeondrejmirtes
authored andcommitted
Add named argument tests for @pure-unless-callable-is-impure
1 parent 670bcc1 commit 5ac0f96

2 files changed

Lines changed: 189 additions & 0 deletions

File tree

tests/PHPStan/Rules/Pure/PureFunctionRuleTest.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,57 @@ public function testPureUnlessCallableIsImpure(): void
296296
]);
297297
}
298298

299+
#[RequiresPhp('>= 8.0.0')]
300+
public function testPureUnlessCallableIsImpureNamedArgs(): void
301+
{
302+
$this->analyse([__DIR__ . '/data/pure-unless-callable-is-impure-named-arg.php'], [
303+
[
304+
'Impure call to function PureUnlessCallableIsImpureNamedArg\myMap() in pure function PureUnlessCallableIsImpureNamedArg\pureCallingUserlandWithImpureCallbackByName().',
305+
61,
306+
],
307+
[
308+
'Impure echo in pure function PureUnlessCallableIsImpureNamedArg\pureCallingUserlandWithImpureCallbackByName().',
309+
62,
310+
],
311+
[
312+
'Possibly impure call to a callable in pure function PureUnlessCallableIsImpureNamedArg\pureCallingUserlandWithOpaqueCallbackByName().',
313+
75,
314+
],
315+
[
316+
'Possibly impure call to function PureUnlessCallableIsImpureNamedArg\myMap() in pure function PureUnlessCallableIsImpureNamedArg\pureCallingUserlandWithOpaqueCallbackByName().',
317+
75,
318+
],
319+
[
320+
'Impure call to function array_map() in pure function PureUnlessCallableIsImpureNamedArg\pureWithImpureCallbackByName().',
321+
85,
322+
],
323+
[
324+
'Impure echo in pure function PureUnlessCallableIsImpureNamedArg\pureWithImpureCallbackByName().',
325+
86,
326+
],
327+
[
328+
'Possibly impure call to a callable in pure function PureUnlessCallableIsImpureNamedArg\pureWithOpaqueCallbackByName().',
329+
99,
330+
],
331+
[
332+
'Possibly impure call to function array_map() in pure function PureUnlessCallableIsImpureNamedArg\pureWithOpaqueCallbackByName().',
333+
99,
334+
],
335+
[
336+
'Impure call to function PureUnlessCallableIsImpureNamedArg\myMap() in pure function PureUnlessCallableIsImpureNamedArg\pureCallingUserlandWithImpureCallbackShuffled().',
337+
121,
338+
],
339+
[
340+
'Impure echo in pure function PureUnlessCallableIsImpureNamedArg\pureCallingUserlandWithImpureCallbackShuffled().',
341+
122,
342+
],
343+
[
344+
'Impure call to method PureUnlessCallableIsImpureNamedArg\Mapper::map() in pure function PureUnlessCallableIsImpureNamedArg\pureCallingMethodWithImpureCallbackByName().',
345+
134,
346+
],
347+
]);
348+
}
349+
299350
#[RequiresPhp('>= 8.4.0')]
300351
public function testPureUnlessCallableIsImpurePhp84(): void
301352
{
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
<?php // lint >= 8.0
2+
3+
declare(strict_types = 1);
4+
5+
namespace PureUnlessCallableIsImpureNamedArg;
6+
7+
/**
8+
* @param callable(int): int $f
9+
* @param array<int> $arr
10+
* @return array<int>
11+
* @pure-unless-callable-is-impure $f
12+
*/
13+
function myMap(callable $f, array $arr): array
14+
{
15+
$result = [];
16+
foreach ($arr as $i => $v) {
17+
$result[$i] = $f($v);
18+
}
19+
20+
return $result;
21+
}
22+
23+
class Mapper
24+
{
25+
26+
/**
27+
* @param callable(int): int $f
28+
* @param array<int> $arr
29+
* @return array<int>
30+
* @pure-unless-callable-is-impure $f
31+
*/
32+
public function map(callable $f, array $arr): array
33+
{
34+
$result = [];
35+
foreach ($arr as $i => $v) {
36+
$result[$i] = $f($v);
37+
}
38+
39+
return $result;
40+
}
41+
42+
}
43+
44+
/**
45+
* @param array<int> $arr
46+
* @return array<int>
47+
* @phpstan-pure
48+
*/
49+
function pureCallingUserlandWithPureCallbackByName(array $arr): array
50+
{
51+
return myMap(f: static fn (int $x): int => $x * 2, arr: $arr);
52+
}
53+
54+
/**
55+
* @param array<int> $arr
56+
* @return array<int>
57+
* @phpstan-pure
58+
*/
59+
function pureCallingUserlandWithImpureCallbackByName(array $arr): array
60+
{
61+
return myMap(f: static function (int $x): int {
62+
echo $x;
63+
return $x * 2;
64+
}, arr: $arr);
65+
}
66+
67+
/**
68+
* @param array<int> $arr
69+
* @param callable(int): int $cb
70+
* @return array<int>
71+
* @phpstan-pure
72+
*/
73+
function pureCallingUserlandWithOpaqueCallbackByName(array $arr, callable $cb): array
74+
{
75+
return myMap(f: $cb, arr: $arr);
76+
}
77+
78+
/**
79+
* @param array<int> $arr
80+
* @return array<int>
81+
* @phpstan-pure
82+
*/
83+
function pureWithImpureCallbackByName(array $arr): array
84+
{
85+
return array_map(callback: static function (int $x): int {
86+
echo $x;
87+
return $x * 2;
88+
}, array: $arr);
89+
}
90+
91+
/**
92+
* @param array<int> $arr
93+
* @param callable(int): int $cb
94+
* @return array<int>
95+
* @phpstan-pure
96+
*/
97+
function pureWithOpaqueCallbackByName(array $arr, callable $cb): array
98+
{
99+
return array_map(callback: $cb, array: $arr);
100+
}
101+
102+
/**
103+
* @param array<int> $arr
104+
* @return array<int>
105+
* @phpstan-pure
106+
*/
107+
function pureCallingUserlandWithPureCallbackShuffled(array $arr): array
108+
{
109+
// Arguments are passed in shuffled order using names, so name-based matching
110+
// (not positional matching) determines which argument is judged for purity.
111+
return myMap(arr: $arr, f: static fn (int $x): int => $x * 2);
112+
}
113+
114+
/**
115+
* @param array<int> $arr
116+
* @return array<int>
117+
* @phpstan-pure
118+
*/
119+
function pureCallingUserlandWithImpureCallbackShuffled(array $arr): array
120+
{
121+
return myMap(arr: $arr, f: static function (int $x): int {
122+
echo $x;
123+
return $x * 2;
124+
});
125+
}
126+
127+
/**
128+
* @param array<int> $arr
129+
* @return array<int>
130+
* @phpstan-pure
131+
*/
132+
function pureCallingMethodWithImpureCallbackByName(Mapper $mapper, array $arr): array
133+
{
134+
return $mapper->map(f: static function (int $x): int {
135+
echo $x;
136+
return $x * 2;
137+
}, arr: $arr);
138+
}

0 commit comments

Comments
 (0)