Skip to content

Commit 2c65f4e

Browse files
Add Immutable attribute
1 parent 29992c6 commit 2c65f4e

7 files changed

+116
-26
lines changed

README.md

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -97,27 +97,27 @@ This extension works by interacting with the parser that Psalm uses to parse the
9797

9898
These are the available attributes and their corresponding PHPDoc annotations:
9999

100-
| Attribute | PHPDoc Annotations |
101-
|---------------------------------------------------------------------------------------------------|--------------------|
102-
| [Deprecated](https://github.com/php-static-analysis/attributes/blob/main/doc/Deprecated.md) | `@deprecated` |
103-
| [Impure](https://github.com/php-static-analysis/attributes/blob/main/doc/Impure.md) | `@impure` |
104-
| [Internal](https://github.com/php-static-analysis/attributes/blob/main/doc/Internal.md) | `@internal` |
105-
| [IsReadOnly](https://github.com/php-static-analysis/attributes/blob/main/doc/IsReadOnly.md) | `@readonly` |
106-
| [Method](https://github.com/php-static-analysis/attributes/blob/main/doc/Method.md) | `@method` |
107-
| [Mixin](https://github.com/php-static-analysis/attributes/blob/main/doc/Mixin.md) | `@mixin` |
108-
| [Param](https://github.com/php-static-analysis/attributes/blob/main/doc/Param.md) | `@param` |
109-
| [ParamOut](https://github.com/php-static-analysis/attributes/blob/main/doc/ParamOut.md) | `@param-out` |
110-
| [Property](https://github.com/php-static-analysis/attributes/blob/main/doc/Property.md) | `@property` `@var` |
111-
| [PropertyRead](https://github.com/php-static-analysis/attributes/blob/main/doc/PropertyRead.md) | `@property-read` |
112-
| [PropertyWrite](https://github.com/php-static-analysis/attributes/blob/main/doc/PropertyWrite.md) | `@property-write` |
113-
| [Pure](https://github.com/php-static-analysis/attributes/blob/main/doc/Pure.md) | `@pure` |
114-
| [RequireExtends](https://github.com/php-static-analysis/attributes/blob/main/doc/RequireExtends.md) | `@require-extends` |
115-
| [RequireImplements](https://github.com/php-static-analysis/attributes/blob/main/doc/RequireImplements.md) | `@require-implements` |
116-
| [Returns](https://github.com/php-static-analysis/attributes/blob/main/doc/Returns.md) | `@return` |
117-
| [SelfOut](https://github.com/php-static-analysis/attributes/blob/main/doc/SelfOut.md) | `@self-out` `@this-out` |
118-
| [Template](https://github.com/php-static-analysis/attributes/blob/main/doc/Template.md) | `@template` |
119-
| [TemplateCovariant](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateCovariant.md) | `@template-covariant` |
120-
| [TemplateExtends](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateExtends.md) | `@extends` `@template-extends` |
121-
| [TemplateImplements](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateImplements.md) | `@implements` `@template-implements` |
122-
| [TemplateUse](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateUse.md) | `@use` `@template-use` |
123-
| [Type](https://github.com/php-static-analysis/attributes/blob/main/doc/Type.md) | `@var` `@return` |
100+
| Attribute | PHPDoc Annotations |
101+
|-----------------------------------------------------------------------------------------------------------------|--------------------|
102+
| [Deprecated](https://github.com/php-static-analysis/attributes/blob/main/doc/Deprecated.md) | `@deprecated` |
103+
| [Immmutable](https://github.com/php-static-analysis/attributes/blob/main/doc/Immmutable.md) | `@immmutable` |
104+
| [Internal](https://github.com/php-static-analysis/attributes/blob/main/doc/Internal.md) | `@internal` |
105+
| [IsReadOnly](https://github.com/php-static-analysis/attributes/blob/main/doc/IsReadOnly.md) | `@readonly` |
106+
| [Method](https://github.com/php-static-analysis/attributes/blob/main/doc/Method.md) | `@method` |
107+
| [Mixin](https://github.com/php-static-analysis/attributes/blob/main/doc/Mixin.md) | `@mixin` |
108+
| [Param](https://github.com/php-static-analysis/attributes/blob/main/doc/Param.md) | `@param` |
109+
| [ParamOut](https://github.com/php-static-analysis/attributes/blob/main/doc/ParamOut.md) | `@param-out` |
110+
| [Property](https://github.com/php-static-analysis/attributes/blob/main/doc/Property.md) | `@property` `@var` |
111+
| [PropertyRead](https://github.com/php-static-analysis/attributes/blob/main/doc/PropertyRead.md) | `@property-read` |
112+
| [PropertyWrite](https://github.com/php-static-analysis/attributes/blob/main/doc/PropertyWrite.md) | `@property-write` |
113+
| [Pure](https://github.com/php-static-analysis/attributes/blob/main/doc/Pure.md) | `@pure` |
114+
| [RequireExtends](https://github.com/php-static-analysis/attributes/blob/main/doc/RequireExtends.md) | `@require-extends` |
115+
| [RequireImplements](https://github.com/php-static-analysis/attributes/blob/main/doc/RequireImplements.md) | `@require-implements` |
116+
| [Returns](https://github.com/php-static-analysis/attributes/blob/main/doc/Returns.md) | `@return` |
117+
| [SelfOut](https://github.com/php-static-analysis/attributes/blob/main/doc/SelfOut.md) | `@self-out` `@this-out` |
118+
| [Template](https://github.com/php-static-analysis/attributes/blob/main/doc/Template.md) | `@template` |
119+
| [TemplateCovariant](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateCovariant.md) | `@template-covariant` |
120+
| [TemplateExtends](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateExtends.md) | `@extends` `@template-extends` |
121+
| [TemplateImplements](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateImplements.md) | `@implements` `@template-implements` |
122+
| [TemplateUse](https://github.com/php-static-analysis/attributes/blob/main/doc/TemplateUse.md) | `@use` `@template-use` |
123+
| [Type](https://github.com/php-static-analysis/attributes/blob/main/doc/Type.md) | `@var` `@return` |

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
"require": {
2727
"php": ">=8.0",
2828
"ext-simplexml": "*",
29-
"php-static-analysis/attributes": "^0.1.16 || dev-main",
30-
"php-static-analysis/node-visitor": "^0.1.16 || dev-main",
29+
"php-static-analysis/attributes": "^0.1.17 || dev-main",
30+
"php-static-analysis/node-visitor": "^0.1.17 || dev-main",
3131
"vimeo/psalm": "^5"
3232
},
3333
"require-dev": {

tests/ImmutableAttributeTest.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
4+
namespace test\PhpStaticAnalysis\PsalmPlugin;
5+
6+
class ImmutableAttributeTest extends BaseAttributeTestCase
7+
{
8+
public function testClassImmutableAttribute(): void
9+
{
10+
$errors = $this->analyzeTestFile( '/data/Immutable/ClassImmutableAttribute.php');
11+
$expectedErrors = [
12+
'test\PhpStaticAnalysis\PsalmPlugin\data\Immutable\ClassImmutableAttribute::$name is marked readonly' => 14,
13+
];
14+
15+
$this->checkExpectedErrors($errors, $expectedErrors);
16+
}
17+
18+
public function testTraitImmutableAttribute(): void
19+
{
20+
$errors = $this->analyzeTestFile( '/data/Immutable/TraitImmutableAttribute.php');
21+
$this->assertCount(0, $errors);
22+
}
23+
24+
public function testInterfaceImmutableAttribute(): void
25+
{
26+
$errors = $this->analyzeTestFile( '/data/Immutable/InterfaceImmutableAttribute.php');
27+
$this->assertCount(0, $errors);
28+
}
29+
30+
public function testInvalidClassImmutableAttribute(): void
31+
{
32+
$errors = $this->analyzeTestFile( '/data/Immutable/InvalidClassImmutableAttribute.php');
33+
34+
$expectedErrors = [
35+
'Attribute Immutable is not repeatable' => 10,
36+
'Attribute Immutable cannot be used on a property' => 13,
37+
];
38+
39+
$this->checkExpectedErrors($errors, $expectedErrors);
40+
}
41+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace test\PhpStaticAnalysis\PsalmPlugin\data\Immutable;
4+
5+
use PhpStaticAnalysis\Attributes\Immutable;
6+
7+
#[Immutable] // All properties are read only
8+
class ClassImmutableAttribute
9+
{
10+
public string $name = '';
11+
}
12+
13+
$class = new ClassImmutableAttribute();
14+
$class->name = 'John';
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace test\PhpStaticAnalysis\PsalmPlugin\data\Immutable;
4+
5+
use PhpStaticAnalysis\Attributes\Immutable;
6+
7+
#[Immutable]
8+
interface InterfaceImmutableAttribute
9+
{
10+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
namespace test\PhpStaticAnalysis\PsalmPlugin\data\Immutable;
4+
5+
use PhpStaticAnalysis\Attributes\Immutable;
6+
use PhpStaticAnalysis\Attributes\Param;
7+
use PhpStaticAnalysis\Attributes\Returns;
8+
9+
#[Immutable]
10+
#[Immutable]
11+
class InvalidClassImmutableAttribute
12+
{
13+
#[Immutable]
14+
public string $name = '';
15+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace test\PhpStaticAnalysis\PsalmPlugin\data\Immutable;
4+
5+
use PhpStaticAnalysis\Attributes\Immutable;
6+
7+
#[Immutable]
8+
trait TraitImmutableAttribute
9+
{
10+
}

0 commit comments

Comments
 (0)