From 5ff933f2a5e60e58813d5a1ec1fc357a82231c72 Mon Sep 17 00:00:00 2001 From: Daniel Beardsley Date: Fri, 24 Mar 2023 17:27:48 -0700 Subject: [PATCH 1/4] @property annotations: allow *not* implying @psalm-seal-properties Add a setting that allows usage of `@property` to *augment* classes that use __get() and __set(). Previously, using `@property` once would force you to exhaustively list all possible properties. This didn't use to be the case, but was changed in df33405635cbdb6d41474503ca20c8adda55d438 This was really unexpected for our team and for a while we thought it was a psalm bug until I found the above commit. We are using `__get()` for ORM objects and we want to use `@property` to explicitly document some of columns without being forced to document every column. --- docs/running_psalm/configuration.md | 9 +++++++++ src/Psalm/Config.php | 8 ++++++++ .../PhpVisitor/Reflector/ClassLikeNodeScanner.php | 4 +++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/docs/running_psalm/configuration.md b/docs/running_psalm/configuration.md index c642eb3f0..aa6e58b4a 100644 --- a/docs/running_psalm/configuration.md +++ b/docs/running_psalm/configuration.md @@ -90,6 +90,15 @@ Whether or not to use types as defined in docblocks. Defaults to `true`. ``` If not using all docblock types, you can still use docblock property types. Defaults to `false` (though only relevant if `useDocblockTypes` is `false`). +#### docblockPropertyTypesSealProperties + +```xml + +``` +Whether using @property in class docblocks should imply @psalm-seal-properties + #### usePhpDocMethodsWithoutMagicCall ```xml diff --git a/src/Psalm/Config.php b/src/Psalm/Config.php index de71b0d1e..e09d0b722 100644 --- a/src/Psalm/Config.php +++ b/src/Psalm/Config.php @@ -194,6 +194,13 @@ class Config */ public $use_docblock_property_types = false; + /** + * Whether using @property in docblocks should implicitly seal properties + * + * @var bool + */ + public $docblock_property_types_seal_properties = true; + /** * Whether or not to throw an exception on first error * @@ -1049,6 +1056,7 @@ class Config $booleanAttributes = [ 'useDocblockTypes' => 'use_docblock_types', 'useDocblockPropertyTypes' => 'use_docblock_property_types', + 'docblockPropertyTypesSealProperties' => 'docblock_property_types_seal_properties', 'throwExceptionOnError' => 'throw_exception', 'hideExternalErrors' => 'hide_external_errors', 'hideAllErrorsExceptPassedFiles' => 'hide_all_errors_except_passed_files', diff --git a/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php b/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php index e581bbdb9..f33b2efcd 100644 --- a/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php +++ b/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php @@ -568,7 +568,9 @@ class ClassLikeNodeScanner } } - $storage->sealed_properties = true; + if ($config->docblock_property_types_seal_properties) { + $storage->sealed_properties = true; + } } foreach ($docblock_info->methods as $method) { From ad05b138a57d37309fbf5e42a4c9841edf905933 Mon Sep 17 00:00:00 2001 From: Daniel Beardsley Date: Mon, 27 Mar 2023 08:14:46 -0700 Subject: [PATCH 2/4] ClassLikeNodeScanner.php: Fix missing $this Derp! Co-authored-by: Bruce Weirdan --- .../Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php b/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php index f33b2efcd..7b6cd0f4a 100644 --- a/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php +++ b/src/Psalm/Internal/PhpVisitor/Reflector/ClassLikeNodeScanner.php @@ -568,7 +568,7 @@ class ClassLikeNodeScanner } } - if ($config->docblock_property_types_seal_properties) { + if ($this->config->docblock_property_types_seal_properties) { $storage->sealed_properties = true; } } From 7b541ed74f40f06e84a56dde0eb4bee34eef6e8d Mon Sep 17 00:00:00 2001 From: Daniel Beardsley Date: Mon, 27 Mar 2023 09:48:36 -0700 Subject: [PATCH 3/4] src/Psalm/Config.php: don't use annotations Psalm was parsing this as a property annotation, derp. --- src/Psalm/Config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Psalm/Config.php b/src/Psalm/Config.php index e09d0b722..a740d853b 100644 --- a/src/Psalm/Config.php +++ b/src/Psalm/Config.php @@ -195,7 +195,7 @@ class Config public $use_docblock_property_types = false; /** - * Whether using @property in docblocks should implicitly seal properties + * Whether using property annotations in docblocks should implicitly seal properties * * @var bool */ From bf00ecae91d6b31f229784fa9e44ee10d2214c7f Mon Sep 17 00:00:00 2001 From: Daniel Beardsley Date: Mon, 27 Mar 2023 10:37:29 -0700 Subject: [PATCH 4/4] Config: document default on new option Also add it to the config schema. --- config.xsd | 1 + docs/running_psalm/configuration.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/config.xsd b/config.xsd index f4302e200..a0a9db0e3 100644 --- a/config.xsd +++ b/config.xsd @@ -62,6 +62,7 @@ + diff --git a/docs/running_psalm/configuration.md b/docs/running_psalm/configuration.md index aa6e58b4a..43f42c3bf 100644 --- a/docs/running_psalm/configuration.md +++ b/docs/running_psalm/configuration.md @@ -97,7 +97,7 @@ If not using all docblock types, you can still use docblock property types. Defa docblockPropertyTypesSealProperties="[bool]" > ``` -Whether using @property in class docblocks should imply @psalm-seal-properties +Whether using @property in class docblocks should imply @psalm-seal-properties. Defaults to `true`. #### usePhpDocMethodsWithoutMagicCall