Skip to content

Commit 3399679

Browse files
authored
Upgrade to PHPStan 2.0 (#68)
1 parent 5bc64db commit 3399679

14 files changed

+76
-61
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM php:8.3
1+
FROM php:8.2
22

33
ADD --chmod=0755 https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
44

composer.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,23 @@
1919
],
2020
"require": {
2121
"php": "~8.2.0 || ~8.3.0",
22-
"phpstan/phpstan": "^1.12.4"
22+
"phpstan/phpstan": "^2.0.1"
2323
},
2424
"require-dev": {
2525
"laminas/laminas-cache": "^3.12.2",
2626
"laminas/laminas-cache-storage-adapter-memory": "^2.3.0",
27-
"laminas/laminas-filter": "^2.37.0",
28-
"laminas/laminas-form": "^3.20.1",
27+
"laminas/laminas-filter": "^2.39.0",
28+
"laminas/laminas-form": "^3.21.0",
2929
"laminas/laminas-hydrator": "^4.15.0",
30-
"laminas/laminas-i18n": "^2.28.1",
30+
"laminas/laminas-i18n": "^2.29.0",
3131
"laminas/laminas-inputfilter": "^2.30.1",
3232
"laminas/laminas-mail": "^2.25.1",
3333
"laminas/laminas-mvc": "^3.7.0",
34-
"laminas/laminas-paginator": "^2.18.1",
34+
"laminas/laminas-paginator": "^2.19.0",
3535
"laminas/laminas-validator": "^2.64.1",
36-
"phpstan/phpstan-deprecation-rules": "^1.2.1",
37-
"phpstan/phpstan-phpunit": "^1.4.0",
38-
"phpunit/phpunit": "^9.6.21",
36+
"phpstan/phpstan-deprecation-rules": "^2",
37+
"phpstan/phpstan-phpunit": "^2",
38+
"phpunit/phpunit": "^11.4.3",
3939
"slam/php-cs-fixer-extensions": "^3.11.1"
4040
},
4141
"conflict": {

phpstan-baseline.neon

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,31 @@
11
parameters:
22
ignoreErrors:
33
-
4-
message: "#^Call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertInstanceOf\\(\\) with 'LaminasPhpStan\\\\\\\\TestAsset\\\\\\\\BarService' and Laminas\\\\Stdlib\\\\DispatchableInterface will always evaluate to false\\.$#"
4+
message: '#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#'
5+
identifier: phpstanApi.runtimeReflection
6+
count: 1
7+
path: src/Rules/Laminas/ServiceManagerGetMethodCallRule.php
8+
9+
-
10+
message: '#^Parameter \#1 \$config of method Laminas\\ServiceManager\\ServiceManager\:\:configure\(\) expects array\{abstract_factories\?\: array\<class\-string\<Laminas\\ServiceManager\\Factory\\AbstractFactoryInterface\>\|Laminas\\ServiceManager\\Factory\\AbstractFactoryInterface\>, aliases\?\: array\<string, string\>, delegators\?\: mixed, factories\?\: mixed, initializers\?\: mixed, invokables\?\: array\<string, string\>, lazy_services\?\: array\{class_map\?\: array\<string, class\-string\>, proxies_namespace\?\: non\-empty\-string, proxies_target_dir\?\: non\-empty\-string, write_proxy_files\?\: bool\}, services\?\: array\<string, array\<mixed\>\|object\>, \.\.\.\}, mixed given\.$#'
11+
identifier: argument.type
12+
count: 1
13+
path: src/ServiceManagerLoader.php
14+
15+
-
16+
message: '#^Parameter \#1 \$config of method Laminas\\ServiceManager\\ServiceManager\:\:configure\(\) expects array\{abstract_factories\?\: array\<class\-string\<Laminas\\ServiceManager\\Factory\\AbstractFactoryInterface\>\|Laminas\\ServiceManager\\Factory\\AbstractFactoryInterface\>, aliases\?\: array\<string, string\>, delegators\?\: mixed, factories\?\: mixed, initializers\?\: mixed, invokables\?\: array\<string, string\>, lazy_services\?\: array\{class_map\?\: array\<string, class\-string\>, proxies_namespace\?\: non\-empty\-string, proxies_target_dir\?\: non\-empty\-string, write_proxy_files\?\: bool\}, services\?\: array\<string, array\<mixed\>\|object\>, \.\.\.\}, non\-empty\-array given\.$#'
17+
identifier: argument.type
18+
count: 1
19+
path: src/ServiceManagerLoader.php
20+
21+
-
22+
message: '#^Creating new ReflectionClass is a runtime reflection concept that might not work in PHPStan because it uses fully static reflection engine\. Use objects retrieved from ReflectionProvider instead\.$#'
23+
identifier: phpstanApi.runtimeReflection
24+
count: 2
25+
path: src/Type/Laminas/AbstractServiceLocatorGetDynamicReturnTypeExtension.php
26+
27+
-
28+
message: '#^Call to static method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''LaminasPhpStan\\\\TestAsset\\\\BarService'' and Laminas\\Stdlib\\DispatchableInterface will always evaluate to false\.$#'
29+
identifier: staticMethod.impossibleType
530
count: 1
631
path: tests/Type/Laminas/ServiceManagerLoaderTest.php

phpunit.xml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
<?xml version="1.0"?>
22
<phpunit
33
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4-
bootstrap="./vendor/autoload.php"
54
colors="true"
6-
verbose="true"
75
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
86
>
97
<coverage>
10-
<include>
11-
<directory suffix=".php">./src</directory>
12-
</include>
138
<report>
149
<text outputFile="php://stdout" showOnlySummary="true"/>
1510
</report>
1611
</coverage>
1712
<testsuite name="LaminasPhpStan">
1813
<directory>./tests</directory>
1914
</testsuite>
15+
<source>
16+
<include>
17+
<directory>./src</directory>
18+
</include>
19+
</source>
2020
</phpunit>

src/Rules/Laminas/ServiceManagerGetMethodCallRule.php

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
use LaminasPhpStan\ServiceManagerLoader;
1111
use LaminasPhpStan\Type\Laminas\ObjectServiceManagerType;
1212
use PhpParser\Node;
13-
use PhpParser\Node\Arg;
1413
use PhpParser\Node\Expr\MethodCall;
1514
use PHPStan\Analyser\Scope;
1615
use PHPStan\Reflection\ReflectionProvider;
1716
use PHPStan\Rules\Rule;
17+
use PHPStan\Rules\RuleErrorBuilder;
1818
use PHPStan\Type\ObjectType;
1919
use PHPStan\Type\Type;
2020
use Psr\Container\ContainerInterface as PsrContainerInterface;
@@ -35,22 +35,15 @@ public function getNodeType(): string
3535
return MethodCall::class;
3636
}
3737

38-
/**
39-
* @param MethodCall $node
40-
*
41-
* @return string[]
42-
*/
38+
/** @param MethodCall $node */
4339
public function processNode(Node $node, Scope $scope): array
4440
{
4541
$args = $node->getArgs();
4642
if (1 !== \count($args)) {
4743
return [];
4844
}
4945

50-
$firstArg = $args[0];
51-
if (! $firstArg instanceof Arg) {
52-
return [];
53-
}
46+
$firstArg = $args[0];
5447
$argType = $scope->getType($firstArg->value);
5548
$constantStrings = $argType->getConstantStrings();
5649
if (1 !== \count($constantStrings)) {
@@ -92,14 +85,14 @@ public function processNode(Node $node, Scope $scope): array
9285
}
9386
}
9487

95-
return [\sprintf(
88+
return [RuleErrorBuilder::message(\sprintf(
9689
'The service "%s" was not configured in %s%s.',
9790
$serviceName,
9891
$calledOnType instanceof ObjectServiceManagerType
9992
? $calledOnType->getServiceName()
10093
: $calledOnType->getClassName(),
10194
$classDoesNotExistNote
102-
)];
95+
))->identifier('servicemanager.servicenotconfigured')->build()];
10396
}
10497

10598
/** @phpstan-assert-if-true ObjectType $type */

src/ServiceManagerLoader.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,10 @@ public function getServiceLocator(string $serviceManagerName): ServiceLocatorInt
6767
}
6868
if (\class_exists(ServiceListenerFactory::class)) {
6969
$refProp = new ReflectionProperty(ServiceListenerFactory::class, 'defaultServiceConfig');
70-
$refProp->setAccessible(true);
71-
$config = $refProp->getValue(new ServiceListenerFactory());
70+
$config = $refProp->getValue(new ServiceListenerFactory());
7271
\assert(\is_array($config));
7372
\assert(\is_array($config['factories']));
7473
unset($config['factories']['config']);
75-
$refProp->setAccessible(false);
7674
$serviceManager->configure($config);
7775
}
7876
foreach ($this->knownModules as $module) {

src/Type/Laminas/AbstractServiceLocatorGetDynamicReturnTypeExtension.php

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@
66

77
use Laminas\ServiceManager\AbstractPluginManager;
88
use LaminasPhpStan\ServiceManagerLoader;
9-
use PhpParser\Node\Arg;
109
use PhpParser\Node\Expr\MethodCall;
1110
use PHPStan\Analyser\Scope;
1211
use PHPStan\Reflection\MethodReflection;
1312
use PHPStan\Reflection\ReflectionProvider;
14-
use PHPStan\ShouldNotHappenException;
1513
use PHPStan\Type\DynamicMethodReturnTypeExtension;
1614
use PHPStan\Type\MixedType;
1715
use PHPStan\Type\NeverType;
@@ -48,15 +46,7 @@ final public function getTypeFromMethodCall(
4846

4947
$serviceManager = $this->serviceManagerLoader->getServiceLocator($calledOnType->getObjectClassNames()[0]);
5048

51-
$firstArg = $args[0];
52-
if (! $firstArg instanceof Arg) {
53-
throw new ShouldNotHappenException(\sprintf(
54-
'Argument passed to %s::%s should be a string, %s given',
55-
$methodReflection->getDeclaringClass()->getName(),
56-
$methodReflection->getName(),
57-
$firstArg->getType()
58-
));
59-
}
49+
$firstArg = $args[0];
6050
$argType = $scope->getType($firstArg->value);
6151
$constantStringTypes = $argType->getConstantStrings();
6252
if (1 !== \count($constantStringTypes)) {

src/Type/Laminas/PluginMethodDynamicReturnTypeExtension/AbstractPluginMethodDynamicReturnTypeExtension.php

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
namespace LaminasPhpStan\Type\Laminas\PluginMethodDynamicReturnTypeExtension;
66

77
use LaminasPhpStan\ServiceManagerLoader;
8-
use PhpParser\Node\Arg;
98
use PhpParser\Node\Expr\MethodCall;
109
use PHPStan\Analyser\Scope;
1110
use PHPStan\Reflection\MethodReflection;
@@ -36,17 +35,9 @@ final public function getTypeFromMethodCall(
3635
Scope $scope
3736
): Type {
3837
$firstArg = $methodCall->getArgs()[0];
39-
if (! $firstArg instanceof Arg) {
40-
throw new ShouldNotHappenException(\sprintf(
41-
'Argument passed to %s::%s should be a string, %s given',
42-
$methodReflection->getDeclaringClass()->getName(),
43-
$methodReflection->getName(),
44-
$firstArg->getType()
45-
));
46-
}
47-
$argType = $scope->getType($firstArg->value);
48-
$strings = $argType->getConstantStrings();
49-
$plugin = 1 === \count($strings) ? $strings[0]->getValue() : null;
38+
$argType = $scope->getType($firstArg->value);
39+
$strings = $argType->getConstantStrings();
40+
$plugin = 1 === \count($strings) ? $strings[0]->getValue() : null;
5041

5142
if (null !== $plugin) {
5243
$pluginManager = $this->serviceManagerLoader->getServiceLocator($this->getPluginManagerName());

tests/LaminasIntegration/IntegrationTest.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*/
1212
final class IntegrationTest extends LevelsTestCase
1313
{
14-
public function dataTopics(): array
14+
public static function dataTopics(): array
1515
{
1616
return [
1717
['serviceManagerDynamicReturn'],
@@ -36,7 +36,7 @@ public function getPhpStanExecutablePath(): string
3636
return __DIR__ . '/../../vendor/bin/phpstan';
3737
}
3838

39-
public function getPhpStanConfigPath(): ?string
39+
public function getPhpStanConfigPath(): string
4040
{
4141
return __DIR__ . '/phpstan.neon';
4242
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[
2+
{
3+
"message": "Cannot call method isFoo() on mixed.",
4+
"line": 16,
5+
"ignorable": true
6+
}
7+
]

0 commit comments

Comments
 (0)