Skip to content

Commit 39bac3d

Browse files
Merge pull request #31 from DaveLiddament/feature/must-use-result
ADD #[MustUseResult] attribute
2 parents 3dfb73d + a8ac53b commit 39bac3d

File tree

4 files changed

+141
-0
lines changed

4 files changed

+141
-0
lines changed

README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ The intention, at least initially, is that these extra language features are enf
1515

1616
**Language feature added:**
1717
- [Friend](#friend)
18+
- [MustUseResult](#mustuseresult)
1819
- [NamespaceVisibility](#namespaceVisibility)
1920
- [InjectableVersion](#injectableVersion)
2021
- [Override](#override)
@@ -29,6 +30,7 @@ The intention, at least initially, is that these extra language features are enf
2930
- [Psalm](#psalm)
3031
- [New Language Features](#new-language-features)
3132
- [Friend](#friend)
33+
- [MustUseResult](#mustuseresult)
3234
- [NamespaceVisibility](#namespaceVisibility)
3335
- [InjectableVersion](#injectableVersion)
3436
- [Override](#override)
@@ -129,7 +131,40 @@ $person = new Person();
129131
```
130132
- This is currently limited to method calls (including `__construct`).
131133

134+
## MustUseResult
132135

136+
Add #[MustUseResult] attribute that can be used on methods. This enforces the result from the method call must be used.
137+
138+
E.g. if you have a class like this:
139+
140+
```php
141+
142+
class Money {
143+
144+
public function __construct(public readonly int $pence)
145+
{}
146+
147+
#[MustUseResult]
148+
public function add(int $pence): self
149+
{
150+
return new self($pence + $this->pence);
151+
}
152+
}
153+
```
154+
155+
You might misuse the `add` method in this way:
156+
157+
```php
158+
$cost = new Money(5);
159+
$cost->add(6); // ERROR - This statement has no effect.
160+
```
161+
162+
But this would be OK:
163+
164+
```php
165+
$cost = new Money(5);
166+
$updatedCost = $cost->add(6); // OK - The return from add method is being used.
167+
```
133168

134169
## NamespaceVisibility
135170

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace MustUseResultOnMethod {
4+
5+
6+
use DaveLiddament\PhpLanguageExtensions\MustUseResult;
7+
8+
class AClass {
9+
10+
#[MustUseResult]
11+
public function mustUseResult(): int
12+
{
13+
return 1;
14+
}
15+
16+
public function dontNeedToUseResult(): int
17+
{
18+
return 2;
19+
}
20+
21+
}
22+
23+
24+
$class = new AClass();
25+
26+
$class->dontNeedToUseResult(); // OK
27+
28+
$class->mustUseResult(); // ERROR
29+
30+
echo $class->mustUseResult(); // OK;
31+
32+
$value = 1 + $class->mustUseResult(); // OK
33+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
namespace MustUseResultOnMethod {
4+
5+
6+
use DaveLiddament\PhpLanguageExtensions\MustUseResult;
7+
8+
class AClass {
9+
10+
#[MustUseResult]
11+
public static function mustUseResult(): int
12+
{
13+
return 1;
14+
}
15+
16+
public static function dontNeedToUseResult(): int
17+
{
18+
return 2;
19+
}
20+
21+
}
22+
23+
24+
AClass::dontNeedToUseResult(); // OK
25+
26+
AClass::mustUseResult(); // ERROR
27+
28+
echo AClass::mustUseResult(); // OK;
29+
30+
$value = 1 + AClass::mustUseResult(); // OK
31+
}

src/MustUseResult.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DaveLiddament\PhpLanguageExtensions;
6+
7+
/**
8+
* Enforces that the result from a method call must be used.
9+
*
10+
* Assume the following class:
11+
* ```
12+
* class Money {
13+
*
14+
* public function __construct(public readonly int $pence)
15+
* {}
16+
*
17+
* #[MustUseResult]
18+
* public function add(int $pence): self
19+
* {
20+
* return new self($pence + $this->pence);
21+
* }
22+
* }
23+
* ```
24+
*
25+
* You might misuse the `add` method in this way:
26+
*
27+
* ```
28+
* $cost = new Money(5);
29+
* $cost->add(6); // ERROR - This statement has no effect.
30+
* ```
31+
*
32+
* But this would be OK:
33+
*
34+
* ```
35+
* $cost = new Money(5);
36+
* $updatedCost = $cost->add(6); // OK - The return from add method is being used.
37+
* ```
38+
*/
39+
#[\Attribute(\Attribute::TARGET_METHOD)]
40+
final class MustUseResult
41+
{
42+
}

0 commit comments

Comments
 (0)