diff --git a/src/Helpers/Cache.php b/src/Helpers/Cache.php index 0678120..6d311ee 100644 --- a/src/Helpers/Cache.php +++ b/src/Helpers/Cache.php @@ -4,6 +4,9 @@ namespace DaveLiddament\PhpstanPhpLanguageExtensions\Helpers; +use function array_key_exists; +use Closure; + /** * @template TValue */ @@ -12,24 +15,15 @@ class Cache /** @var array */ private array $cache = []; - public function hasEntry(string $key): bool - { - return array_key_exists($key, $this->cache); - } - - /** @return TValue */ - public function getEntry(string $key) + /** + * @return TValue + */ + public function get(string $key, Closure $initializer): mixed { if (!array_key_exists($key, $this->cache)) { - throw new \LogicException('Call hasEntry first'); + $this->cache[$key] = $initializer(); } return $this->cache[$key]; } - - /** @param TValue $entry */ - public function addEntry(string $key, $entry): void - { - $this->cache[$key] = $entry; - } } diff --git a/src/Rules/AbstractFriendRule.php b/src/Rules/AbstractFriendRule.php index f619a57..4f891b0 100644 --- a/src/Rules/AbstractFriendRule.php +++ b/src/Rules/AbstractFriendRule.php @@ -45,26 +45,22 @@ protected function getErrorOrNull( $className = $classReflection->getName(); $fullMethodName = "{$className}::{$methodName}"; - if ($this->cache->hasEntry($fullMethodName)) { - $allowedCallingClassesFromMethod = $this->cache->getEntry($fullMethodName); - } else { - $allowedCallingClassesFromMethod = AttributeValueReader::getAttributeValuesForMethod( + $allowedCallingClassesFromMethod = $this->cache->get( + $fullMethodName, + static fn (): array => AttributeValueReader::getAttributeValuesForMethod( $classReflection->getNativeReflection(), $methodName, Friend::class - ); - $this->cache->addEntry($fullMethodName, $allowedCallingClassesFromMethod); - } + ) + ); - if ($this->cache->hasEntry($className)) { - $allowedCallingClassesFromClass = $this->cache->getEntry($className); - } else { - $allowedCallingClassesFromClass = AttributeValueReader::getAttributeValuesForClass( + $allowedCallingClassesFromClass = $this->cache->get( + $className, + static fn (): array => AttributeValueReader::getAttributeValuesForClass( $classReflection->getNativeReflection(), Friend::class - ); - $this->cache->addEntry($className, $allowedCallingClassesFromClass); - } + ) + ); $allowedCallingClasses = array_merge($allowedCallingClassesFromClass, $allowedCallingClassesFromMethod); diff --git a/src/Rules/AbstractPackageRule.php b/src/Rules/AbstractPackageRule.php index bdda039..e457416 100644 --- a/src/Rules/AbstractPackageRule.php +++ b/src/Rules/AbstractPackageRule.php @@ -4,6 +4,7 @@ namespace DaveLiddament\PhpstanPhpLanguageExtensions\Rules; +use function count; use DaveLiddament\PhpLanguageExtensions\Package; use DaveLiddament\PhpstanPhpLanguageExtensions\Config\TestConfig; use DaveLiddament\PhpstanPhpLanguageExtensions\Helpers\Cache; @@ -45,24 +46,16 @@ protected function getErrorOrNull( $fullMethodName = "{$className}::{$methodName}"; - if ($this->cache->hasEntry($fullMethodName)) { - $isMethodPackageLevel = $this->cache->getEntry($fullMethodName); - } else { - if ($nativeReflection->hasMethod($methodName)) { - $methodReflection = $nativeReflection->getMethod($methodName); - $isMethodPackageLevel = count($methodReflection->getAttributes(Package::class)) > 0; - } else { - $isMethodPackageLevel = false; - } - $this->cache->addEntry($fullMethodName, $isMethodPackageLevel); - } + $isMethodPackageLevel = $this->cache->get( + $fullMethodName, + static fn (): bool => $nativeReflection->hasMethod($methodName) + && count($nativeReflection->getMethod($methodName)->getAttributes(Package::class)) > 0 + ); - if ($this->cache->hasEntry($className)) { - $isClassPackageLevel = $this->cache->getEntry($className); - } else { - $isClassPackageLevel = count($nativeReflection->getAttributes(Package::class)) > 0; - $this->cache->addEntry($className, $isClassPackageLevel); - } + $isClassPackageLevel = $this->cache->get( + $className, + static fn (): bool => count($nativeReflection->getAttributes(Package::class)) > 0 + ); $isPackageLevel = $isClassPackageLevel || $isMethodPackageLevel; diff --git a/src/Rules/AbstractTestTagRule.php b/src/Rules/AbstractTestTagRule.php index 85e5bee..76b86dc 100644 --- a/src/Rules/AbstractTestTagRule.php +++ b/src/Rules/AbstractTestTagRule.php @@ -4,6 +4,7 @@ namespace DaveLiddament\PhpstanPhpLanguageExtensions\Rules; +use function count; use DaveLiddament\PhpLanguageExtensions\TestTag; use DaveLiddament\PhpstanPhpLanguageExtensions\Config\TestConfig; use DaveLiddament\PhpstanPhpLanguageExtensions\Helpers\Cache; @@ -45,17 +46,11 @@ protected function getErrorOrNull( $fullMethodName = "{$className}::{$methodName}"; - if ($this->cache->hasEntry($fullMethodName)) { - $isTestTag = $this->cache->getEntry($fullMethodName); - } else { - if ($nativeReflection->hasMethod($methodName)) { - $methodReflection = $nativeReflection->getMethod($methodName); - $isTestTag = count($methodReflection->getAttributes(TestTag::class)) > 0; - } else { - $isTestTag = false; - } - $this->cache->addEntry($fullMethodName, $isTestTag); - } + $isTestTag = $this->cache->get( + $fullMethodName, + static fn (): bool => $nativeReflection->hasMethod($methodName) + && count($nativeReflection->getMethod($methodName)->getAttributes(TestTag::class)) > 0 + ); if (!$isTestTag) { return null; diff --git a/src/Rules/InjectableVersionRule.php b/src/Rules/InjectableVersionRule.php index e15b331..0805b1c 100644 --- a/src/Rules/InjectableVersionRule.php +++ b/src/Rules/InjectableVersionRule.php @@ -73,12 +73,7 @@ public function processNode(Node $node, Scope $scope): array : $type->getReferencedClasses(); foreach ($classesToCheck as $className) { - if ($this->cache->hasEntry($className)) { - $classToUse = $this->cache->getEntry($className); - } else { - $classToUse = $this->checkClass($className); - $this->cache->addEntry($className, $classToUse); - } + $classToUse = $this->cache->get($className, fn () => $this->checkClass($className)); if (null !== $classToUse) { $message = sprintf( diff --git a/tests/Unit/CacheTest.php b/tests/Unit/CacheTest.php index c40b37c..a92708c 100644 --- a/tests/Unit/CacheTest.php +++ b/tests/Unit/CacheTest.php @@ -22,21 +22,20 @@ protected function setup(): void $this->cache = new Cache(); } - public function testEmptyCache(): void + public function testEntriesShouldOnlyBeInitializedOnce(): void { - $this->assertFalse($this->cache->hasEntry(self::ENTRY_1)); - } + $initializationCount = 0; - public function testAddValueToCache(): void - { - $this->cache->addEntry(self::ENTRY_1, self::VALUE_1); - $this->assertTrue($this->cache->hasEntry(self::ENTRY_1)); - $this->assertSame(self::VALUE_1, $this->cache->getEntry(self::ENTRY_1)); - } + $initializer = static function () use (&$initializationCount): string { + ++$initializationCount; - public function testAccessMissingEntry(): void - { - $this->expectException(\LogicException::class); - $this->cache->getEntry(self::ENTRY_1); + return self::VALUE_1; + }; + + self::assertSame(self::VALUE_1, $this->cache->get(self::ENTRY_1, $initializer)); + self::assertSame(1, $initializationCount); + + self::assertSame(self::VALUE_1, $this->cache->get(self::ENTRY_1, $initializer)); + self::assertSame(1, $initializationCount); } }