1
0
mirror of https://github.com/danog/psalm.git synced 2024-12-02 09:37:59 +01:00

Merge pull request #10344 from robchett/seal_method_seal_properties_without_prefix

Support @(no-)seal-(properties|methods) annotations without prefix
This commit is contained in:
orklah 2023-11-04 09:57:52 +01:00 committed by GitHub
commit d041b652cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 64 additions and 15 deletions

View File

@ -202,7 +202,7 @@ takesFoo(getFoo());
This provides the same, but for `false`. Psalm uses this internally for functions like `preg_replace`, which can return false if the given input has encoding errors, but where 99.9% of the time the function operates as expected.
### `@psalm-seal-properties`, `@psalm-no-seal-properties`
### `@psalm-seal-properties`, `@psalm-no-seal-properties`, `@seal-properties`, `@no-seal-properties`
If you have a magic property getter/setter, you can use `@psalm-seal-properties` to instruct Psalm to disallow getting and setting any properties not contained in a list of `@property` (or `@property-read`/`@property-write`) annotations.
This is automatically enabled with the configuration option `sealAllProperties` and can be disabled for a class with `@psalm-no-seal-properties`
@ -211,7 +211,7 @@ This is automatically enabled with the configuration option `sealAllProperties`
<?php
/**
* @property string $foo
* @psalm-seal-properties
* @seal-properties
*/
class A {
public function __get(string $name): ?string {
@ -227,7 +227,7 @@ $a = new A();
$a->bar = 5; // this call fails
```
### `@psalm-seal-methods`, `@psalm-no-seal-methods`
### `@psalm-seal-methods`, `@psalm-no-seal-methods`, `@seal-methods`, `@no-seal-methods`
If you have a magic method caller, you can use `@psalm-seal-methods` to instruct Psalm to disallow calling any methods not contained in a list of `@method` annotations.
This is automatically enabled with the configuration option `sealAllMethods` and can be disabled for a class with `@psalm-no-seal-methods`
@ -236,7 +236,7 @@ This is automatically enabled with the configuration option `sealAllMethods` and
<?php
/**
* @method foo(): string
* @psalm-seal-methods
* @seal-methods
*/
class A {
public function __call(string $name, array $args) {

View File

@ -236,19 +236,21 @@ final class ClassLikeDocblockParser
}
}
if (isset($parsed_docblock->tags['psalm-seal-properties'])) {
foreach (['', 'psalm-'] as $prefix) {
if (isset($parsed_docblock->tags[$prefix . 'seal-properties'])) {
$info->sealed_properties = true;
}
if (isset($parsed_docblock->tags['psalm-no-seal-properties'])) {
if (isset($parsed_docblock->tags[$prefix . 'no-seal-properties'])) {
$info->sealed_properties = false;
}
if (isset($parsed_docblock->tags['psalm-seal-methods'])) {
if (isset($parsed_docblock->tags[$prefix . 'seal-methods'])) {
$info->sealed_methods = true;
}
if (isset($parsed_docblock->tags['psalm-no-seal-methods'])) {
if (isset($parsed_docblock->tags[$prefix . 'no-seal-methods'])) {
$info->sealed_methods = false;
}
}
if (isset($parsed_docblock->tags['psalm-inheritors'])) {
foreach ($parsed_docblock->tags['psalm-inheritors'] as $template_line) {

View File

@ -1118,6 +1118,21 @@ class MagicMethodAnnotationTest extends TestCase
$b->foo();',
'error_message' => 'UndefinedMagicMethod',
],
'inheritSealedMethodsWithoutPrefix' => [
'code' => '<?php
/**
* @seal-methods
*/
class A {
public function __call(string $method, array $args) {}
}
class B extends A {}
$b = new B();
$b->foo();',
'error_message' => 'UndefinedMagicMethod',
],
'lonelyMethod' => [
'code' => '<?php
/**

View File

@ -1189,6 +1189,38 @@ class MagicPropertyTest extends TestCase
}',
'error_message' => 'InvalidDocblock',
],
'sealedWithNoProperties' => [
'code' => '<?php
/**
* @psalm-seal-properties
*/
final class OrganizationObject {
public function __get(string $key)
{
return [];
}
}
echo (new OrganizationObject)->errors;',
'error_message' => 'UndefinedMagicPropertyFetch',
],
'sealedWithNoPropertiesNoPrefix' => [
'code' => '<?php
/**
* @seal-properties
*/
final class OrganizationObject {
public function __get(string $key)
{
return [];
}
}
echo (new OrganizationObject)->errors;',
'error_message' => 'UndefinedMagicPropertyFetch',
],
];
}