Skip to content

Commit 5e09137

Browse files
committed
add disallow mutating functions rule
1 parent 6a6d863 commit 5e09137

File tree

4 files changed

+219
-0
lines changed

4 files changed

+219
-0
lines changed

Diff for: extension.neon

+8
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ parametersSchema:
55
disallowThrow: bool()
66
disallowUnusedExpression: bool()
77
disallowVariablesMutation: bool()
8+
disallowMutatingFunctions: bool()
89
])
910

1011
parameters:
@@ -14,6 +15,7 @@ parameters:
1415
disallowThrow: true
1516
disallowUnusedExpression: true
1617
disallowVariablesMutation: true
18+
disallowMutatingFunctions: true
1719

1820
services:
1921
-
@@ -94,3 +96,9 @@ services:
9496
- phpstan.rules.rule
9597
arguments:
9698
disallowVariablesMutation: %phpstanFunctionalProgramming.disallowVariablesMutation%
99+
-
100+
class: Hexlet\PHPStanFp\Rules\Functions\DisallowMutatingFunctionsRule
101+
tags:
102+
- phpstan.rules.rule
103+
arguments:
104+
disallowMutatingFunctions: %phpstanFunctionalProgramming.disallowMutatingFunctions%
+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?php
2+
3+
namespace Hexlet\PHPStanFp\Rules\Functions;
4+
5+
use PHPStan\Rules\Rule;
6+
use PhpParser\Node;
7+
use PHPStan\Analyser\Scope;
8+
use PhpParser\Node\Expr\FuncCall;
9+
10+
class DisallowMutatingFunctionsRule implements Rule
11+
{
12+
private bool $disallowMutatingFunctions;
13+
14+
/**
15+
* @var array<string>
16+
*/
17+
private array $mutatingFunctionsNames = [
18+
'array_multisort',
19+
'array_pop',
20+
'array_push',
21+
'array_shift',
22+
'array_splice',
23+
'array_unshift',
24+
'arsort',
25+
'asort',
26+
'krsort',
27+
'ksort',
28+
'natcasesort',
29+
'natsort',
30+
'rsort',
31+
'shuffle',
32+
'sort',
33+
'uasort',
34+
'uksort',
35+
'usort',
36+
];
37+
38+
public function __construct(bool $disallowMutatingFunctions)
39+
{
40+
$this->disallowMutatingFunctions = $disallowMutatingFunctions;
41+
}
42+
43+
public function getNodeType(): string
44+
{
45+
return FuncCall::class;
46+
}
47+
48+
/**
49+
* @param \PhpParser\Node\Expr\FuncCall $node
50+
* @param \PHPStan\Analyser\Scope $scope
51+
* @return string[]
52+
*/
53+
public function processNode(Node $node, Scope $scope): array
54+
{
55+
if (!$this->disallowMutatingFunctions) {
56+
return [];
57+
}
58+
59+
if (!$node->name instanceof \PhpParser\Node\Name\FullyQualified) {
60+
return [];
61+
}
62+
63+
$name = $node->name->getFirst();
64+
if (!in_array($name, $this->mutatingFunctionsNames)) {
65+
return [];
66+
}
67+
68+
return ["The use of function '{$name}' is not allowed as it might be a mutating function"];
69+
}
70+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?php
2+
3+
namespace Hexlet\PHPStanFp\Tests\Rules\Functions;
4+
5+
use PHPStan\Testing\RuleTestCase;
6+
use PHPStan\Rules\Rule;
7+
use Hexlet\PHPStanFp\Rules\Functions\DisallowMutatingFunctionsRule;
8+
9+
class DisallowMutatingFunctionsRuleTest extends RuleTestCase
10+
{
11+
private bool $disallowMutatingFunctions;
12+
13+
protected function getRule(): Rule
14+
{
15+
return new DisallowMutatingFunctionsRule($this->disallowMutatingFunctions);
16+
}
17+
18+
public function testWithEnabledRule(): void
19+
{
20+
$this->disallowMutatingFunctions = true;
21+
$this->analyse([__DIR__ . '/data/functions.php'], [
22+
[
23+
'The use of function \'array_multisort\' is not allowed as it might be a mutating function',
24+
5,
25+
],
26+
[
27+
'The use of function \'array_pop\' is not allowed as it might be a mutating function',
28+
7,
29+
],
30+
[
31+
'The use of function \'array_push\' is not allowed as it might be a mutating function',
32+
9,
33+
],
34+
[
35+
'The use of function \'array_shift\' is not allowed as it might be a mutating function',
36+
11,
37+
],
38+
[
39+
'The use of function \'array_splice\' is not allowed as it might be a mutating function',
40+
13,
41+
],
42+
[
43+
'The use of function \'array_unshift\' is not allowed as it might be a mutating function',
44+
15,
45+
],
46+
[
47+
'The use of function \'arsort\' is not allowed as it might be a mutating function',
48+
17,
49+
],
50+
[
51+
'The use of function \'asort\' is not allowed as it might be a mutating function',
52+
19,
53+
],
54+
[
55+
'The use of function \'krsort\' is not allowed as it might be a mutating function',
56+
21,
57+
],
58+
[
59+
'The use of function \'ksort\' is not allowed as it might be a mutating function',
60+
23,
61+
],
62+
[
63+
'The use of function \'natcasesort\' is not allowed as it might be a mutating function',
64+
25,
65+
],
66+
[
67+
'The use of function \'natsort\' is not allowed as it might be a mutating function',
68+
27,
69+
],
70+
[
71+
'The use of function \'rsort\' is not allowed as it might be a mutating function',
72+
29,
73+
],
74+
[
75+
'The use of function \'shuffle\' is not allowed as it might be a mutating function',
76+
31,
77+
],
78+
[
79+
'The use of function \'sort\' is not allowed as it might be a mutating function',
80+
33,
81+
],
82+
[
83+
'The use of function \'uasort\' is not allowed as it might be a mutating function',
84+
35,
85+
],
86+
[
87+
'The use of function \'uksort\' is not allowed as it might be a mutating function',
88+
37,
89+
],
90+
[
91+
'The use of function \'usort\' is not allowed as it might be a mutating function',
92+
39,
93+
],
94+
]);
95+
}
96+
97+
public function testWithDisabledRule(): void
98+
{
99+
$this->disallowMutatingFunctions = false;
100+
$this->analyse([__DIR__ . '/data/functions.php'], []);
101+
}
102+
}

Diff for: tests/Rules/Functions/data/functions.php

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
3+
$ar1 = array(10, 100, 100, 0);
4+
$ar2 = array(1, 3, 2, 4);
5+
array_multisort($ar1, $ar2);
6+
7+
$last = array_pop($ar2);
8+
9+
array_push($ar2, 6, 7);
10+
11+
$first = array_shift($ar2);
12+
13+
array_splice($ar1, 2);
14+
15+
array_unshift($ar1, -1, 0);
16+
17+
arsort($ar2);
18+
19+
asort($ar2);
20+
21+
krsort($ar2);
22+
23+
ksort($ar2);
24+
25+
natcasesort($ar2);
26+
27+
natsort($ar2);
28+
29+
rsort($ar2);
30+
31+
shuffle($ar2);
32+
33+
sort($ar2);
34+
35+
uasort($ar2);
36+
37+
uksort($ar2);
38+
39+
usort($ar2);

0 commit comments

Comments
 (0)