From 2b39ab02a042f86734f81ab5fd26a6fbd124222f Mon Sep 17 00:00:00 2001 From: Bruce Weirdan Date: Fri, 22 Jan 2021 02:38:17 +0200 Subject: [PATCH] Resolve class aliases when accessing properties (#5068) * Resolve class aliases when accessing properties * Moved Properties::getClasslikeStorage() to ClassLikes::getStorageFor() --- src/Psalm/Codebase.php | 11 +++++---- src/Psalm/Internal/Codebase/ClassLikes.php | 11 +++++++++ src/Psalm/Internal/Codebase/Properties.php | 27 +++++++++++++++------- tests/ClassTest.php | 9 ++++++++ 4 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/Psalm/Codebase.php b/src/Psalm/Codebase.php index 5a1c3a3c5..30185fa0c 100644 --- a/src/Psalm/Codebase.php +++ b/src/Psalm/Codebase.php @@ -309,11 +309,6 @@ class Codebase $this->functions = new Internal\Codebase\Functions($providers->file_storage_provider, $reflection); - $this->properties = new Internal\Codebase\Properties( - $providers->classlike_storage_provider, - $providers->file_reference_provider - ); - $this->classlikes = new Internal\Codebase\ClassLikes( $this->config, $providers->classlike_storage_provider, @@ -322,6 +317,12 @@ class Codebase $this->scanner ); + $this->properties = new Internal\Codebase\Properties( + $providers->classlike_storage_provider, + $providers->file_reference_provider, + $this->classlikes + ); + $this->methods = new Internal\Codebase\Methods( $providers->classlike_storage_provider, $providers->file_reference_provider, diff --git a/src/Psalm/Internal/Codebase/ClassLikes.php b/src/Psalm/Internal/Codebase/ClassLikes.php index e8d924339..4136d68de 100644 --- a/src/Psalm/Internal/Codebase/ClassLikes.php +++ b/src/Psalm/Internal/Codebase/ClassLikes.php @@ -2076,4 +2076,15 @@ class ClassLikes $this->existing_interfaces = array_merge($existing_interfaces, $this->existing_interfaces); $this->existing_classes = array_merge($existing_classes, $this->existing_classes); } + + public function getStorageFor(string $fq_class_name): ?ClassLikeStorage + { + $fq_class_name = $this->getUnAliasedName($fq_class_name); + + try { + return $this->classlike_storage_provider->get($fq_class_name); + } catch (\InvalidArgumentException $e) { + return null; + } + } } diff --git a/src/Psalm/Internal/Codebase/Properties.php b/src/Psalm/Internal/Codebase/Properties.php index d563fed83..297c72bbc 100644 --- a/src/Psalm/Internal/Codebase/Properties.php +++ b/src/Psalm/Internal/Codebase/Properties.php @@ -11,6 +11,7 @@ use Psalm\Internal\Provider\PropertyExistenceProvider; use Psalm\Internal\Provider\PropertyTypeProvider; use Psalm\Internal\Provider\PropertyVisibilityProvider; use Psalm\StatementsSource; +use Psalm\Storage\ClassLikeStorage; use Psalm\Type; use function strtolower; @@ -26,6 +27,9 @@ class Properties */ private $classlike_storage_provider; + /** @var ClassLikes */ + private $classlikes; + /** * @var bool */ @@ -51,15 +55,18 @@ class Properties */ public $property_visibility_provider; + public function __construct( ClassLikeStorageProvider $storage_provider, - FileReferenceProvider $file_reference_provider + FileReferenceProvider $file_reference_provider, + ClassLikes $classlikes ) { $this->classlike_storage_provider = $storage_provider; $this->file_reference_provider = $file_reference_provider; $this->property_existence_provider = new PropertyExistenceProvider(); $this->property_visibility_provider = new PropertyVisibilityProvider(); $this->property_type_provider = new PropertyTypeProvider(); + $this->classlikes = $classlikes; } /** @@ -94,7 +101,11 @@ class Properties } } - $class_storage = $this->classlike_storage_provider->get($fq_class_name); + $class_storage = $this->classlikes->getStorageFor($fq_class_name); + + if (!$class_storage) { + return false; + } if ($source && $context @@ -174,9 +185,9 @@ class Properties } } - $class_storage = $this->classlike_storage_provider->get($fq_class_name); + $class_storage = $this->classlikes->getStorageFor($fq_class_name); - if (isset($class_storage->declaring_property_ids[$property_name])) { + if ($class_storage && isset($class_storage->declaring_property_ids[$property_name])) { return $class_storage->declaring_property_ids[$property_name]; } @@ -205,9 +216,9 @@ class Properties } } - $class_storage = $this->classlike_storage_provider->get($fq_class_name); + $class_storage = $this->classlikes->getStorageFor($fq_class_name); - if (isset($class_storage->appearing_property_ids[$property_name])) { + if ($class_storage && isset($class_storage->appearing_property_ids[$property_name])) { $appearing_property_id = $class_storage->appearing_property_ids[$property_name]; return explode('::$', $appearing_property_id)[0]; @@ -262,9 +273,9 @@ class Properties } } - $class_storage = $this->classlike_storage_provider->get($fq_class_name); + $class_storage = $this->classlikes->getStorageFor($fq_class_name); - if (isset($class_storage->declaring_property_ids[$property_name])) { + if ($class_storage && isset($class_storage->declaring_property_ids[$property_name])) { $declaring_property_class = $class_storage->declaring_property_ids[$property_name]; $declaring_class_storage = $this->classlike_storage_provider->get($declaring_property_class); diff --git a/tests/ClassTest.php b/tests/ClassTest.php index 77ed89d97..fc886ad52 100644 --- a/tests/ClassTest.php +++ b/tests/ClassTest.php @@ -481,6 +481,15 @@ class ClassTest extends TestCase action(new OldA()); action(new OldAChild());' ], + 'classAliasStaticProperty' => [ + ' [ '