Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 24db3f7

Browse files
Add support for PHP 8.5 #[\NoDiscard] on functions
1 parent fbb9cb6 commit 24db3f7

File tree

3 files changed

+106
-0
lines changed

3 files changed

+106
-0
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Functions;
4+
5+
use PhpParser\Node;
6+
use PHPStan\Analyser\Scope;
7+
use PHPStan\DependencyInjection\RegisteredRule;
8+
use PHPStan\Reflection\ReflectionProvider;
9+
use PHPStan\Rules\Rule;
10+
use PHPStan\Rules\RuleErrorBuilder;
11+
use function sprintf;
12+
13+
/**
14+
* @implements Rule<Node\Stmt\Expression>
15+
*/
16+
#[RegisteredRule(level: 4)]
17+
final class CallToFunctionStatementWithNoDiscardRule implements Rule
18+
{
19+
20+
public function __construct(private ReflectionProvider $reflectionProvider)
21+
{
22+
}
23+
24+
public function getNodeType(): string
25+
{
26+
return Node\Stmt\Expression::class;
27+
}
28+
29+
public function processNode(Node $node, Scope $scope): array
30+
{
31+
if (!$node->expr instanceof Node\Expr\FuncCall) {
32+
return [];
33+
}
34+
35+
$funcCall = $node->expr;
36+
if (!($funcCall->name instanceof Node\Name)) {
37+
return [];
38+
}
39+
40+
if (!$this->reflectionProvider->hasFunction($funcCall->name, $scope)) {
41+
return [];
42+
}
43+
44+
$function = $this->reflectionProvider->getFunction($funcCall->name, $scope);
45+
46+
$attributes = $function->getAttributes();
47+
$hasNoDiscard = false;
48+
foreach ($attributes as $attrib) {
49+
if ($attrib->getName() === 'NoDiscard') {
50+
$hasNoDiscard = true;
51+
break;
52+
}
53+
}
54+
if (!$hasNoDiscard) {
55+
return [];
56+
}
57+
58+
return [
59+
RuleErrorBuilder::message(sprintf(
60+
'Call to function %s() on a separate line discards return value.',
61+
$function->getName(),
62+
))->identifier('function.resultDiscarded')->build(),
63+
];
64+
}
65+
66+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Rules\Functions;
4+
5+
use PHPStan\Rules\Rule;
6+
use PHPStan\Testing\RuleTestCase;
7+
8+
/**
9+
* @extends RuleTestCase<CallToFunctionStatementWithNoDiscardRule>
10+
*/
11+
class CallToFunctionStatementWithNoDiscardRuleTest extends RuleTestCase
12+
{
13+
14+
protected function getRule(): Rule
15+
{
16+
return new CallToFunctionStatementWithNoDiscardRule(self::createReflectionProvider());
17+
}
18+
19+
public function testRule(): void
20+
{
21+
$this->analyse([__DIR__ . '/data/function-call-statement-result-discarded.php'], [
22+
[
23+
'Call to function FunctionCallStatementResultDiscarded\withSideEffects() on a separate line discards return value.',
24+
11,
25+
],
26+
]);
27+
}
28+
29+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace FunctionCallStatementResultDiscarded;
4+
5+
#[\NoDiscard]
6+
function withSideEffects(): int {
7+
echo __FUNCTION__ . "\n";
8+
return 1;
9+
}
10+
11+
withSideEffects();

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /