Skip to content

Commit 79ea7e3

Browse files
authored
PHPStan 2.0 (#17)
* PHPStan 2.0 * Remove PHP 7.1 from github actions * remove old version mabe enum support * drop support for old phpunit & fix github actions
1 parent 63d391c commit 79ea7e3

14 files changed

+85
-115
lines changed

.github/workflows/phpstan.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ jobs:
1818
php-version:
1919
- "7.4"
2020
- "8.0"
21+
- "8.1"
22+
- "8.2"
23+
- "8.3"
24+
- "8.4"
2125

2226
steps:
2327
- name: "Checkout"

.github/workflows/tests-code-coverage.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,8 @@ jobs:
1616
fail-fast: false
1717
matrix:
1818
php-version:
19-
- "7.2"
20-
- "7.3"
2119
- "7.4"
2220
- "8.0"
23-
- "8.1"
2421

2522
steps:
2623
- name: "Checkout"

.github/workflows/tests.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ jobs:
1616
fail-fast: false
1717
matrix:
1818
php-version:
19-
- "7.1"
19+
- "8.1"
20+
- "8.2"
21+
- "8.3"
22+
- "8.4"
2023

2124
steps:
2225
- name: "Checkout"

composer.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
"keywords": ["enum", "phpstan"],
66
"license": "BSD-3-Clause",
77
"require": {
8-
"php": "^7.1 | ^8.0",
9-
"marc-mabe/php-enum": "^1.1 || ^2.0 || ^3.0 || ^4.0",
10-
"phpstan/phpstan": "^1.0"
8+
"php": "^7.4 | ^8.0",
9+
"marc-mabe/php-enum": "^4.0",
10+
"phpstan/phpstan": "^2.0"
1111
},
1212
"require-dev": {
13-
"phpunit/phpunit": "^7.5 | ^8.5 | 9.4"
13+
"phpunit/phpunit": "^9.0"
1414
},
1515
"autoload": {
1616
"psr-4": {

src/EnumDynamicReturnTypeExtension.php

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,38 +23,36 @@ class EnumDynamicReturnTypeExtension implements DynamicStaticMethodReturnTypeExt
2323
*
2424
* @var array<string, callable>
2525
*/
26-
private $objectMethods = [];
26+
private array $objectMethods = [];
2727

2828
/**
2929
* Map supported static method to a callable function detecting return type
3030
*
3131
* @var array<string, callable>
3232
*/
33-
private $staticMethods = [];
33+
private array $staticMethods = [];
3434

3535
/**
3636
* Buffer of all types of enumeration values
3737
* @phpstan-var array<class-string<Enum>, Type[]>
3838
*/
39-
private $enumValueTypesBuffer = [];
39+
private array $enumValueTypesBuffer = [];
4040

4141
/**
4242
* Buffer of all types of enumeration ordinals
4343
* @phpstan-var array<class-string<Enum>, Type[]>
4444
*/
45-
private $enumOrdinalTypesBuffer = [];
45+
private array $enumOrdinalTypesBuffer = [];
4646

4747
public function __construct()
4848
{
4949
$this->objectMethods['getvalue'] = function (string $class) {
5050
return $this->detectGetValueReturnType($class);
5151
};
5252

53-
if (method_exists(Enum::class, 'getvalues')) {
54-
$this->staticMethods['getvalues'] = function (string $class) {
55-
return $this->detectGetValuesReturnType($class);
56-
};
57-
}
53+
$this->staticMethods['getvalues'] = function (string $class) {
54+
return $this->detectGetValuesReturnType($class);
55+
};
5856

5957
// static methods can be called like object methods
6058
$this->objectMethods = array_merge($this->objectMethods, $this->staticMethods);
@@ -87,15 +85,23 @@ public function getTypeFromStaticMethodCall(
8785
// The call class is not a name
8886
// E.g. an expression on $enumClass::getValues()
8987
if (!$callClass instanceof Name) {
90-
return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType();
88+
return ParametersAcceptorSelector::selectFromArgs(
89+
$scope,
90+
$staticCall->getArgs(),
91+
$methodReflection->getVariants()
92+
)->getReturnType();
9193
}
9294

9395
$callClassName = $callClass->toString();
9496

9597
// Can't detect possible types on static::*()
9698
// as it depends on defined enumerators of unknown inherited classes
9799
if ($callClassName === 'static') {
98-
return ParametersAcceptorSelector::selectSingle($methodReflection->getVariants())->getReturnType();
100+
return ParametersAcceptorSelector::selectFromArgs(
101+
$scope,
102+
$staticCall->getArgs(),
103+
$methodReflection->getVariants()
104+
)->getReturnType();
99105
}
100106

101107
if ($callClassName === 'self') {

src/EnumMethodReflection.php

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,9 @@
1313

1414
class EnumMethodReflection implements MethodReflection
1515
{
16-
/**
17-
* @var ClassReflection
18-
*/
19-
private $classReflection;
20-
21-
/**
22-
* @var string
23-
*/
24-
private $name;
16+
private ClassReflection $classReflection;
17+
18+
private string $name;
2519

2620
public function __construct(ClassReflection $classReflection, string $name)
2721
{

src/EnumMethodsClassReflectionExtension.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ public function hasMethod(ClassReflection $classReflection, string $methodName):
1515
return false;
1616
}
1717

18-
/** @var string|Enum $class */
1918
$class = $classReflection->getName();
2019
return array_key_exists($methodName, $class::getConstants());
2120
}

tests/integration/IntegrationTest.php

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,21 @@
1-
<?php declare(strict_types = 1);
1+
<?php declare(strict_types=1);
22

33
namespace MabeEnum\PHPStan\tests\integration;
44

5-
use MabeEnum\Enum;
65
use PHPStan\Testing\LevelsTestCase;
76

87
final class IntegrationTest extends LevelsTestCase
98
{
10-
119
/**
1210
* @return string[][]
1311
*/
14-
public function dataTopics(): array
12+
public static function dataTopics(): array
1513
{
16-
$dataTopics = [
14+
return [
1715
['EnumMethodsClassReflection'],
1816
['EnumGetValueReturnType'],
17+
['EnumGetValuesReturnType'],
1918
];
20-
21-
if (method_exists(Enum::class, 'getValues')) {
22-
$dataTopics[] = ['EnumGetValuesReturnType'];
23-
}
24-
25-
return $dataTopics;
2619
}
2720

2821
public function getDataPath(): string

tests/integration/data/EnumGetValuesReturnType-3.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
[
2+
{
3+
"message": "Method MabeEnum\\PHPStan\\tests\\integration\\data\\EnumGetValuesReturnType\\Example::staticBaseExprMethodFail() should return array<int, null> but returns array<int, array<int|string, mixed>|bool|float|int|string|null>.",
4+
"line": 21,
5+
"ignorable": true
6+
},
27
{
38
"message": "Method MabeEnum\\PHPStan\\tests\\integration\\data\\EnumGetValuesReturnType\\Example::staticMethodFail() should return array<int, null> but returns array<int, float|int|string>.",
49
"line": 40,
@@ -14,9 +19,19 @@
1419
"line": 70,
1520
"ignorable": true
1621
},
22+
{
23+
"message": "Method MabeEnum\\PHPStan\\tests\\integration\\data\\EnumGetValuesReturnType\\MyEnum::staticGetValuesFail() should return array<int, null> but returns array<int, array<int|string, mixed>|bool|float|int|string|null>.",
24+
"line": 76,
25+
"ignorable": true
26+
},
1727
{
1828
"message": "Method MabeEnum\\PHPStan\\tests\\integration\\data\\EnumGetValuesReturnType\\MyInheritedEnum::inheritSelfGetValuesFail() should return array<int, null> but returns array<int, float|int|string>.",
1929
"line": 93,
2030
"ignorable": true
31+
},
32+
{
33+
"message": "Method MabeEnum\\PHPStan\\tests\\integration\\data\\EnumGetValuesReturnType\\MyInheritedEnum::inheritStaticGetValuesFail() should return array<int, null> but returns array<int, array<int|string, mixed>|bool|float|int|string|null>.",
34+
"line": 99,
35+
"ignorable": true
2136
}
2237
]

tests/integration/data/EnumGetValuesReturnType-7.json

Lines changed: 0 additions & 17 deletions
This file was deleted.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[
2+
{
3+
"message": "Method MabeEnum\\PHPStan\\tests\\integration\\data\\EnumMethodsClassReflection\\Example::fail() should return MabeEnum\\PHPStan\\tests\\integration\\data\\EnumMethodsClassReflection\\MyEnum but returns mixed.",
4+
"line": 16,
5+
"ignorable": true
6+
}
7+
]

tests/unit/EnumDynamicReturnTypeExtensionTest.php

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@
99

1010
class EnumDynamicReturnTypeExtensionTest extends PHPStanTestCase
1111
{
12-
/**
13-
* @var EnumDynamicReturnTypeExtension
14-
*/
15-
protected $extension;
12+
protected EnumDynamicReturnTypeExtension $extension;
1613

1714
public function setUp(): void
1815
{
@@ -72,13 +69,7 @@ public function testIsMethodSupportedShouldReturnFalse(): void
7269

7370
public function staticMethodsProvider(): array
7471
{
75-
$staticMethods = [];
76-
77-
if (method_exists(Enum::class, 'getValues')) {
78-
$staticMethods[] = ['getValues'];
79-
}
80-
81-
return $staticMethods;
72+
return [['getValues']];
8273
}
8374

8475
public function objectMethodsProvider(): array

tests/unit/EnumMethodReflectionTest.php

Lines changed: 22 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,15 @@
77
use MabeEnum\PHPStan\tests\assets\DocCommentEnum;
88
use MabeEnum\PHPStan\tests\assets\VisibilityEnum;
99
use PHPStan\Reflection\ParametersAcceptorSelector;
10+
use PHPStan\Reflection\ReflectionProvider;
1011
use PHPStan\Testing\PHPStanTestCase;
1112
use PHPStan\Type\VerbosityLevel;
13+
use PHPStan\Analyser\Scope;
1214

1315
class EnumMethodReflectionTest extends PHPStanTestCase
1416
{
15-
/**
16-
* @var \PHPStan\Reflection\ReflectionProvider
17-
*/
18-
protected $reflectionProvider;
19-
20-
/**
21-
* @var EnumMethodsClassReflectionExtension
22-
*/
23-
protected $reflectionExtension;
17+
protected ReflectionProvider $reflectionProvider;
18+
protected EnumMethodsClassReflectionExtension $reflectionExtension;
2419

2520
public function setUp(): void
2621
{
@@ -30,59 +25,68 @@ public function setUp(): void
3025

3126
public function testGetName(): void
3227
{
33-
$classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class);
28+
$classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class);
3429
$methodReflection = $this->reflectionExtension->getMethod($classReflection, 'STR');
3530

3631
$this->assertSame('STR', $methodReflection->getName());
3732
}
3833

3934
public function testGetDeclaringClass(): void
4035
{
41-
$classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class);
36+
$classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class);
4237
$methodReflection = $this->reflectionExtension->getMethod($classReflection, 'STR');
4338

4439
$this->assertSame($classReflection, $methodReflection->getDeclaringClass());
4540
}
4641

4742
public function testShouldBeStatic(): void
4843
{
49-
$classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class);
44+
$classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class);
5045
$methodReflection = $this->reflectionExtension->getMethod($classReflection, 'STR');
5146

5247
$this->assertTrue($methodReflection->isStatic());
5348
}
5449

5550
public function testShouldNotBePrivate(): void
5651
{
57-
$classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class);
52+
$classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class);
5853
$methodReflection = $this->reflectionExtension->getMethod($classReflection, 'STR');
5954

6055
$this->assertFalse($methodReflection->isPrivate());
6156
}
6257

6358
public function testShouldBePublic(): void
6459
{
65-
$classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class);
60+
$classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class);
6661
$methodReflection = $this->reflectionExtension->getMethod($classReflection, 'STR');
6762

6863
$this->assertTrue($methodReflection->isPublic());
6964
}
7065

7166
public function testGetPrototype(): void
7267
{
73-
$classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class);
68+
$classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class);
7469
$methodReflection = $this->reflectionExtension->getMethod($classReflection, 'STR');
7570

7671
$this->assertSame($methodReflection, $methodReflection->getPrototype());
7772
}
7873

7974
public function testGetVariants(): void
8075
{
81-
$classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class);
76+
$classReflection = $this->reflectionProvider->getClass(VisibilityEnum::class);
8277
$methodReflection = $this->reflectionExtension->getMethod($classReflection, 'STR');
83-
$parametersAcceptor = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants());
8478

85-
$this->assertSame(VisibilityEnum::class, $parametersAcceptor->getReturnType()->describe(VerbosityLevel::value()));
79+
$scope = $this->createMock(Scope::class);
80+
$parametersAcceptor = ParametersAcceptorSelector::selectFromArgs(
81+
$scope,
82+
[],
83+
$methodReflection->getVariants()
84+
);
85+
86+
$this->assertSame(
87+
VisibilityEnum::class,
88+
$parametersAcceptor->getReturnType()->describe(VerbosityLevel::value())
89+
);
8690
}
8791

8892
public function testGetDocComment(): void
@@ -152,24 +156,4 @@ public function testHasSideEffects(): void
152156

153157
$this->assertTrue($methodReflection->hasSideEffects()->no());
154158
}
155-
156-
public static function assertMatchesRegularExpression(string $pattern, string $string, string $message = ''): void
157-
{
158-
if (method_exists(parent::class, 'assertMatchesRegularExpression')) {
159-
parent::assertMatchesRegularExpression($pattern, $string, $message);
160-
return;
161-
}
162-
163-
self::assertRegExp($pattern, $string, $message);
164-
}
165-
166-
public static function assertDoesNotMatchRegularExpression(string $pattern, string $string, string $message = ''): void
167-
{
168-
if (method_exists(parent::class, 'assertDoesNotMatchRegularExpression')) {
169-
parent::assertDoesNotMatchRegularExpression($pattern, $string, $message);
170-
return;
171-
}
172-
173-
self::assertNotRegExp($pattern, $string, $message);
174-
}
175159
}

0 commit comments

Comments
 (0)