From 67ba758c091768ae93b094f10d2f26a3977d51a5 Mon Sep 17 00:00:00 2001 From: Bruce Weirdan Date: Sat, 27 Jan 2024 22:19:17 +0100 Subject: [PATCH 1/6] Fix unstable `hasFullyQualified(Interface|Enum)()` Before this change, calling: ```php $classlikes->hasFullyQualifiedInterfaceName($i); // true $classlikes->hasFullyQualifiedClassName($i); // false $classlikes->hasFullyQualifiedInterfaceName($i); // false ``` would result in the last call returning `false` --- src/Psalm/Internal/Codebase/ClassLikes.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Psalm/Internal/Codebase/ClassLikes.php b/src/Psalm/Internal/Codebase/ClassLikes.php index b57bbe076da..552fab265d5 100644 --- a/src/Psalm/Internal/Codebase/ClassLikes.php +++ b/src/Psalm/Internal/Codebase/ClassLikes.php @@ -356,6 +356,7 @@ public function hasFullyQualifiedClassName( } } + // fixme: this looks like a crazy caching hack if (!isset($this->existing_classes_lc[$fq_class_name_lc]) || !$this->existing_classes_lc[$fq_class_name_lc] || !$this->classlike_storage_provider->has($fq_class_name_lc) @@ -396,13 +397,14 @@ public function hasFullyQualifiedInterfaceName( ): bool { $fq_class_name_lc = strtolower($this->getUnAliasedName($fq_class_name)); + // fixme: this looks like a crazy caching hack if (!isset($this->existing_interfaces_lc[$fq_class_name_lc]) || !$this->existing_interfaces_lc[$fq_class_name_lc] || !$this->classlike_storage_provider->has($fq_class_name_lc) ) { if (( - !isset($this->existing_classes_lc[$fq_class_name_lc]) - || $this->existing_classes_lc[$fq_class_name_lc] + !isset($this->existing_interfaces_lc[$fq_class_name_lc]) + || $this->existing_interfaces_lc[$fq_class_name_lc] ) && !$this->classlike_storage_provider->has($fq_class_name_lc) ) { @@ -463,13 +465,14 @@ public function hasFullyQualifiedEnumName( ): bool { $fq_class_name_lc = strtolower($this->getUnAliasedName($fq_class_name)); + // fixme: this looks like a crazy caching hack if (!isset($this->existing_enums_lc[$fq_class_name_lc]) || !$this->existing_enums_lc[$fq_class_name_lc] || !$this->classlike_storage_provider->has($fq_class_name_lc) ) { if (( - !isset($this->existing_classes_lc[$fq_class_name_lc]) - || $this->existing_classes_lc[$fq_class_name_lc] + !isset($this->existing_enums_lc[$fq_class_name_lc]) + || $this->existing_enums_lc[$fq_class_name_lc] ) && !$this->classlike_storage_provider->has($fq_class_name_lc) ) { From 58b7139470b4977936d4e26ff10d85733951ada5 Mon Sep 17 00:00:00 2001 From: Bruce Weirdan Date: Mon, 29 Jan 2024 21:49:45 +0100 Subject: [PATCH 2/6] Reflection may reference interfaces and enums --- tests/Internal/Codebase/InternalCallMapHandlerTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/Internal/Codebase/InternalCallMapHandlerTest.php b/tests/Internal/Codebase/InternalCallMapHandlerTest.php index e3e99991c13..c0c1293928a 100644 --- a/tests/Internal/Codebase/InternalCallMapHandlerTest.php +++ b/tests/Internal/Codebase/InternalCallMapHandlerTest.php @@ -26,9 +26,11 @@ use function array_shift; use function class_exists; use function count; +use function enum_exists; use function explode; use function function_exists; use function in_array; +use function interface_exists; use function is_array; use function is_int; use function json_encode; @@ -631,6 +633,8 @@ private function assertTypeValidity(ReflectionType $reflected, string $specified } catch (InvalidArgumentException $e) { if (preg_match('/^Could not get class storage for (.*)$/', $e->getMessage(), $matches) && !class_exists($matches[1]) + && !interface_exists($matches[1]) + && !enum_exists($matches[1]) ) { $this->fail("Class used in CallMap does not exist: {$matches[1]}"); } From c935cc307b3d9ce1d0af7dc9507b64313de412d6 Mon Sep 17 00:00:00 2001 From: Bruce Weirdan Date: Mon, 29 Jan 2024 21:56:36 +0100 Subject: [PATCH 3/6] Un-ignore recursiveiteratoriterator::__construct --- tests/Internal/Codebase/InternalCallMapHandlerTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Internal/Codebase/InternalCallMapHandlerTest.php b/tests/Internal/Codebase/InternalCallMapHandlerTest.php index c0c1293928a..5ae7945209e 100644 --- a/tests/Internal/Codebase/InternalCallMapHandlerTest.php +++ b/tests/Internal/Codebase/InternalCallMapHandlerTest.php @@ -142,7 +142,6 @@ class InternalCallMapHandlerTest extends TestCase 'oci_result', 'ocigetbufferinglob', 'ocisetbufferinglob', - 'recursiveiteratoriterator::__construct', // Class used in CallMap does not exist: recursiveiterator 'sqlsrv_fetch_array', 'sqlsrv_fetch_object', 'sqlsrv_get_field', From e8763968a0ee1c6492971d34ac7aca98e42e8e58 Mon Sep 17 00:00:00 2001 From: Bruce Weirdan Date: Mon, 29 Jan 2024 22:03:59 +0100 Subject: [PATCH 4/6] Un-ignore arrayobject::getiterator - appears it's been fixed too --- tests/Internal/Codebase/InternalCallMapHandlerTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Internal/Codebase/InternalCallMapHandlerTest.php b/tests/Internal/Codebase/InternalCallMapHandlerTest.php index 5ae7945209e..3768c83ea37 100644 --- a/tests/Internal/Codebase/InternalCallMapHandlerTest.php +++ b/tests/Internal/Codebase/InternalCallMapHandlerTest.php @@ -174,7 +174,6 @@ class InternalCallMapHandlerTest extends TestCase private static array $ignoredReturnTypeOnlyFunctions = [ 'appenditerator::getinneriterator' => ['8.1', '8.2', '8.3'], 'appenditerator::getiteratorindex' => ['8.1', '8.2', '8.3'], - 'arrayobject::getiterator' => ['8.1', '8.2', '8.3'], 'cachingiterator::getinneriterator' => ['8.1', '8.2', '8.3'], 'callbackfilteriterator::getinneriterator' => ['8.1', '8.2', '8.3'], 'curl_multi_getcontent', From b2aebd90a769537cd89f8581dea356aa2aa0a8df Mon Sep 17 00:00:00 2001 From: Bruce Weirdan Date: Mon, 29 Jan 2024 22:22:34 +0100 Subject: [PATCH 5/6] Fix test by preloading interface --- tests/TypeReconciliation/ReconcilerTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/TypeReconciliation/ReconcilerTest.php b/tests/TypeReconciliation/ReconcilerTest.php index a3b722ff3fd..91f958425eb 100644 --- a/tests/TypeReconciliation/ReconcilerTest.php +++ b/tests/TypeReconciliation/ReconcilerTest.php @@ -61,6 +61,7 @@ class A {} class B {} interface SomeInterface {} '); + $this->project_analyzer->getCodebase()->queueClassLikeForScanning('Countable'); $this->project_analyzer->getCodebase()->scanFiles(); } From e63db9c12a42e5de16a0c183847f1e0fb3915c10 Mon Sep 17 00:00:00 2001 From: Bruce Weirdan Date: Mon, 29 Jan 2024 22:29:19 +0100 Subject: [PATCH 6/6] Drop suppression as the method is now used in tests --- src/Psalm/Codebase.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Psalm/Codebase.php b/src/Psalm/Codebase.php index db400c999c2..a02f61403f6 100644 --- a/src/Psalm/Codebase.php +++ b/src/Psalm/Codebase.php @@ -2406,7 +2406,6 @@ public function getKeyValueParamsForTraversableObject(Atomic $type): array /** * @param array $phantom_classes - * @psalm-suppress PossiblyUnusedMethod part of the public API */ public function queueClassLikeForScanning( string $fq_classlike_name,