diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml index 5b21f42..aebaaa3 100644 --- a/.github/workflows/phpstan.yml +++ b/.github/workflows/phpstan.yml @@ -18,6 +18,10 @@ jobs: php-version: - "7.4" - "8.0" + - "8.1" + - "8.2" + - "8.3" + - "8.4" steps: - name: "Checkout" diff --git a/.github/workflows/tests-code-coverage.yml b/.github/workflows/tests-code-coverage.yml index 9985786..960be7c 100644 --- a/.github/workflows/tests-code-coverage.yml +++ b/.github/workflows/tests-code-coverage.yml @@ -16,11 +16,8 @@ jobs: fail-fast: false matrix: php-version: - - "7.2" - - "7.3" - "7.4" - "8.0" - - "8.1" steps: - name: "Checkout" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6d29345..2866175 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,7 +16,10 @@ jobs: fail-fast: false matrix: php-version: - - "7.1" + - "8.1" + - "8.2" + - "8.3" + - "8.4" steps: - name: "Checkout" diff --git a/composer.json b/composer.json index 8515c66..903e455 100644 --- a/composer.json +++ b/composer.json @@ -5,12 +5,12 @@ "keywords": ["enum", "phpstan"], "license": "BSD-3-Clause", "require": { - "php": "^7.1 | ^8.0", - "marc-mabe/php-enum": "^1.1 || ^2.0 || ^3.0 || ^4.0", - "phpstan/phpstan": "^1.0" + "php": "^7.4 | ^8.0", + "marc-mabe/php-enum": "^4.0", + "phpstan/phpstan": "^2.0" }, "require-dev": { - "phpunit/phpunit": "^7.5 | ^8.5 | 9.4" + "phpunit/phpunit": "^9.0" }, "autoload": { "psr-4": { diff --git a/src/EnumDynamicReturnTypeExtension.php b/src/EnumDynamicReturnTypeExtension.php index 8dc0226..86b3237 100644 --- a/src/EnumDynamicReturnTypeExtension.php +++ b/src/EnumDynamicReturnTypeExtension.php @@ -23,26 +23,26 @@ class EnumDynamicReturnTypeExtension implements DynamicStaticMethodReturnTypeExt * * @var array */ - private $objectMethods = []; + private array $objectMethods = []; /** * Map supported static method to a callable function detecting return type * * @var array */ - private $staticMethods = []; + private array $staticMethods = []; /** * Buffer of all types of enumeration values * @phpstan-var array, Type[]> */ - private $enumValueTypesBuffer = []; + private array $enumValueTypesBuffer = []; /** * Buffer of all types of enumeration ordinals * @phpstan-var array, Type[]> */ - private $enumOrdinalTypesBuffer = []; + private array $enumOrdinalTypesBuffer = []; public function __construct() { @@ -50,11 +50,9 @@ public function __construct() return $this->detectGetValueReturnType($class); }; - if (method_exists(Enum::class, 'getvalues')) { - $this->staticMethods['getvalues'] = function (string $class) { - return $this->detectGetValuesReturnType($class); - }; - } + $this->staticMethods['getvalues'] = function (string $class) { + return $this->detectGetValuesReturnType($class); + }; // static methods can be called like object methods $this->objectMethods = array_merge($this->objectMethods, $this->staticMethods); @@ -87,7 +85,11 @@ public function getTypeFromStaticMethodCall( // The call class is not a name // E.g. an expression on $enumClass::getValues() if (!$callClass instanceof Name) { - return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); + return ParametersAcceptorSelector::selectFromArgs( + $scope, + $staticCall->getArgs(), + $methodReflection->getVariants() + )->getReturnType(); } $callClassName = $callClass->toString(); @@ -95,7 +97,11 @@ public function getTypeFromStaticMethodCall( // Can't detect possible types on static::*() // as it depends on defined enumerators of unknown inherited classes if ($callClassName === 'static') { - return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType(); + return ParametersAcceptorSelector::selectFromArgs( + $scope, + $staticCall->getArgs(), + $methodReflection->getVariants() + )->getReturnType(); } if ($callClassName === 'self') { diff --git a/src/EnumMethodReflection.php b/src/EnumMethodReflection.php index 8a02d1d..db8c6e3 100644 --- a/src/EnumMethodReflection.php +++ b/src/EnumMethodReflection.php @@ -13,15 +13,9 @@ class EnumMethodReflection implements MethodReflection { - /** - * @var ClassReflection - */ - private $classReflection; - - /** - * @var string - */ - private $name; + private ClassReflection $classReflection; + + private string $name; public function __construct(ClassReflection $classReflection, string $name) { diff --git a/src/EnumMethodsClassReflectionExtension.php b/src/EnumMethodsClassReflectionExtension.php index d078181..d653b5f 100644 --- a/src/EnumMethodsClassReflectionExtension.php +++ b/src/EnumMethodsClassReflectionExtension.php @@ -15,7 +15,6 @@ public function hasMethod(ClassReflection $classReflection, string $methodName): return false; } - /** @var string|Enum $class */ $class = $classReflection->getName(); return array_key_exists($methodName, $class::getConstants()); } diff --git a/tests/integration/IntegrationTest.php b/tests/integration/IntegrationTest.php index 125ed51..4ff5ebc 100644 --- a/tests/integration/IntegrationTest.php +++ b/tests/integration/IntegrationTest.php @@ -1,28 +1,21 @@ - but returns array|bool|float|int|string|null>.", + "line": 21, + "ignorable": true + }, { "message": "Method MabeEnum\\PHPStan\\tests\\integration\\data\\EnumGetValuesReturnType\\Example::staticMethodFail() should return array but returns array.", "line": 40, @@ -14,9 +19,19 @@ "line": 70, "ignorable": true }, + { + "message": "Method MabeEnum\\PHPStan\\tests\\integration\\data\\EnumGetValuesReturnType\\MyEnum::staticGetValuesFail() should return array but returns array|bool|float|int|string|null>.", + "line": 76, + "ignorable": true + }, { "message": "Method MabeEnum\\PHPStan\\tests\\integration\\data\\EnumGetValuesReturnType\\MyInheritedEnum::inheritSelfGetValuesFail() should return array but returns array.", "line": 93, "ignorable": true + }, + { + "message": "Method MabeEnum\\PHPStan\\tests\\integration\\data\\EnumGetValuesReturnType\\MyInheritedEnum::inheritStaticGetValuesFail() should return array but returns array|bool|float|int|string|null>.", + "line": 99, + "ignorable": true } ] \ No newline at end of file diff --git a/tests/integration/data/EnumGetValuesReturnType-7.json b/tests/integration/data/EnumGetValuesReturnType-7.json deleted file mode 100644 index a844752..0000000 --- a/tests/integration/data/EnumGetValuesReturnType-7.json +++ /dev/null @@ -1,17 +0,0 @@ -[ - { - "message": "Method MabeEnum\\PHPStan\\tests\\integration\\data\\EnumGetValuesReturnType\\Example::staticBaseExprMethodFail() should return array but returns array|bool|float|int|string|null>.", - "line": 21, - "ignorable": true - }, - { - "message": "Method MabeEnum\\PHPStan\\tests\\integration\\data\\EnumGetValuesReturnType\\MyEnum::staticGetValuesFail() should return array but returns array|bool|float|int|string|null>.", - "line": 76, - "ignorable": true - }, - { - "message": "Method MabeEnum\\PHPStan\\tests\\integration\\data\\EnumGetValuesReturnType\\MyInheritedEnum::inheritStaticGetValuesFail() should return array but returns array|bool|float|int|string|null>.", - "line": 99, - "ignorable": true - } -] \ No newline at end of file diff --git a/tests/integration/data/EnumMethodsClassReflection-10.json b/tests/integration/data/EnumMethodsClassReflection-10.json new file mode 100644 index 0000000..8c96f53 --- /dev/null +++ b/tests/integration/data/EnumMethodsClassReflection-10.json @@ -0,0 +1,7 @@ +[ + { + "message": "Method MabeEnum\\PHPStan\\tests\\integration\\data\\EnumMethodsClassReflection\\Example::fail() should return MabeEnum\\PHPStan\\tests\\integration\\data\\EnumMethodsClassReflection\\MyEnum but returns mixed.", + "line": 16, + "ignorable": true + } +] \ No newline at end of file diff --git a/tests/unit/EnumDynamicReturnTypeExtensionTest.php b/tests/unit/EnumDynamicReturnTypeExtensionTest.php index 32cd363..dd4ecf2 100644 --- a/tests/unit/EnumDynamicReturnTypeExtensionTest.php +++ b/tests/unit/EnumDynamicReturnTypeExtensionTest.php @@ -9,10 +9,7 @@ class EnumDynamicReturnTypeExtensionTest extends PHPStanTestCase { - /** - * @var EnumDynamicReturnTypeExtension - */ - protected $extension; + protected EnumDynamicReturnTypeExtension $extension; public function setUp(): void { @@ -72,13 +69,7 @@ public function testIsMethodSupportedShouldReturnFalse(): void public function staticMethodsProvider(): array { - $staticMethods = []; - - if (method_exists(Enum::class, 'getValues')) { - $staticMethods[] = ['getValues']; - } - - return $staticMethods; + return [['getValues']]; } public function objectMethodsProvider(): array diff --git a/tests/unit/EnumMethodReflectionTest.php b/tests/unit/EnumMethodReflectionTest.php index 03f70dd..7fc042b 100644 --- a/tests/unit/EnumMethodReflectionTest.php +++ b/tests/unit/EnumMethodReflectionTest.php @@ -7,20 +7,15 @@ use MabeEnum\PHPStan\tests\assets\DocCommentEnum; use MabeEnum\PHPStan\tests\assets\VisibilityEnum; use PHPStan\Reflection\ParametersAcceptorSelector; +use PHPStan\Reflection\ReflectionProvider; use PHPStan\Testing\PHPStanTestCase; use PHPStan\Type\VerbosityLevel; +use PHPStan\Analyser\Scope; class EnumMethodReflectionTest extends PHPStanTestCase { - /** - * @var \PHPStan\Reflection\ReflectionProvider - */ - protected $reflectionProvider; - - /** - * @var EnumMethodsClassReflectionExtension - */ - protected $reflectionExtension; + protected ReflectionProvider $reflectionProvider; + protected EnumMethodsClassReflectionExtension $reflectionExtension; public function setUp(): void { @@ -30,7 +25,7 @@ public function setUp(): void public function testGetName(): void { - $classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class); + $classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class); $methodReflection = $this->reflectionExtension->getMethod($classReflection, 'STR'); $this->assertSame('STR', $methodReflection->getName()); @@ -38,7 +33,7 @@ public function testGetName(): void public function testGetDeclaringClass(): void { - $classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class); + $classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class); $methodReflection = $this->reflectionExtension->getMethod($classReflection, 'STR'); $this->assertSame($classReflection, $methodReflection->getDeclaringClass()); @@ -46,7 +41,7 @@ public function testGetDeclaringClass(): void public function testShouldBeStatic(): void { - $classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class); + $classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class); $methodReflection = $this->reflectionExtension->getMethod($classReflection, 'STR'); $this->assertTrue($methodReflection->isStatic()); @@ -54,7 +49,7 @@ public function testShouldBeStatic(): void public function testShouldNotBePrivate(): void { - $classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class); + $classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class); $methodReflection = $this->reflectionExtension->getMethod($classReflection, 'STR'); $this->assertFalse($methodReflection->isPrivate()); @@ -62,7 +57,7 @@ public function testShouldNotBePrivate(): void public function testShouldBePublic(): void { - $classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class); + $classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class); $methodReflection = $this->reflectionExtension->getMethod($classReflection, 'STR'); $this->assertTrue($methodReflection->isPublic()); @@ -70,7 +65,7 @@ public function testShouldBePublic(): void public function testGetPrototype(): void { - $classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class); + $classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class); $methodReflection = $this->reflectionExtension->getMethod($classReflection, 'STR'); $this->assertSame($methodReflection, $methodReflection->getPrototype()); @@ -78,11 +73,20 @@ public function testGetPrototype(): void public function testGetVariants(): void { - $classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class); + $classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class); $methodReflection = $this->reflectionExtension->getMethod($classReflection, 'STR'); - $parametersAcceptor = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants()); - $this->assertSame(VisibilityEnum::class, $parametersAcceptor->getReturnType()->describe(VerbosityLevel::value())); + $scope = $this->createMock(Scope::class); + $parametersAcceptor = ParametersAcceptorSelector::selectFromArgs( + $scope, + [], + $methodReflection->getVariants() + ); + + $this->assertSame( + VisibilityEnum::class, + $parametersAcceptor->getReturnType()->describe(VerbosityLevel::value()) + ); } public function testGetDocComment(): void @@ -152,24 +156,4 @@ public function testHasSideEffects(): void $this->assertTrue($methodReflection->hasSideEffects()->no()); } - - public static function assertMatchesRegularExpression(string $pattern, string $string, string $message = ''): void - { - if (method_exists(parent::class, 'assertMatchesRegularExpression')) { - parent::assertMatchesRegularExpression($pattern, $string, $message); - return; - } - - self::assertRegExp($pattern, $string, $message); - } - - public static function assertDoesNotMatchRegularExpression(string $pattern, string $string, string $message = ''): void - { - if (method_exists(parent::class, 'assertDoesNotMatchRegularExpression')) { - parent::assertDoesNotMatchRegularExpression($pattern, $string, $message); - return; - } - - self::assertNotRegExp($pattern, $string, $message); - } } diff --git a/tests/unit/EnumMethodsClassReflectionExtensionTest.php b/tests/unit/EnumMethodsClassReflectionExtensionTest.php index 121381d..fcc848c 100644 --- a/tests/unit/EnumMethodsClassReflectionExtensionTest.php +++ b/tests/unit/EnumMethodsClassReflectionExtensionTest.php @@ -6,19 +6,13 @@ use MabeEnumPHPStan\EnumMethodsClassReflectionExtension; use MabeEnum\PHPStan\tests\assets\NotAnEnum; use MabeEnum\PHPStan\tests\assets\VisibilityEnum; +use PHPStan\Reflection\ReflectionProvider; use PHPStan\Testing\PHPStanTestCase; class EnumMethodsClassReflectionExtensionTest extends PHPStanTestCase { - /** - * @var \PHPStan\Reflection\ReflectionProvider - */ - protected $reflectionProvider; - - /** - * @var EnumMethodsClassReflectionExtension - */ - protected $extension; + protected ReflectionProvider $reflectionProvider; + protected EnumMethodsClassReflectionExtension $extension; public function setUp(): void {