Skip to content

Commit

Permalink
Upgrade to PHPStan 2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Slamdunk committed Nov 12, 2024
1 parent 5bc64db commit 34de4ae
Show file tree
Hide file tree
Showing 14 changed files with 76 additions and 61 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM php:8.3
FROM php:8.2

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

Expand Down
16 changes: 8 additions & 8 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,23 @@
],
"require": {
"php": "~8.2.0 || ~8.3.0",
"phpstan/phpstan": "^1.12.4"
"phpstan/phpstan": "^2.0.1"
},
"require-dev": {
"laminas/laminas-cache": "^3.12.2",
"laminas/laminas-cache-storage-adapter-memory": "^2.3.0",
"laminas/laminas-filter": "^2.37.0",
"laminas/laminas-form": "^3.20.1",
"laminas/laminas-filter": "^2.39.0",
"laminas/laminas-form": "^3.21.0",
"laminas/laminas-hydrator": "^4.15.0",
"laminas/laminas-i18n": "^2.28.1",
"laminas/laminas-i18n": "^2.29.0",
"laminas/laminas-inputfilter": "^2.30.1",
"laminas/laminas-mail": "^2.25.1",
"laminas/laminas-mvc": "^3.7.0",
"laminas/laminas-paginator": "^2.18.1",
"laminas/laminas-paginator": "^2.19.0",
"laminas/laminas-validator": "^2.64.1",
"phpstan/phpstan-deprecation-rules": "^1.2.1",
"phpstan/phpstan-phpunit": "^1.4.0",
"phpunit/phpunit": "^9.6.21",
"phpstan/phpstan-deprecation-rules": "^2",
"phpstan/phpstan-phpunit": "^2",
"phpunit/phpunit": "^11.4.3",
"slam/php-cs-fixer-extensions": "^3.11.1"
},
"conflict": {
Expand Down
27 changes: 26 additions & 1 deletion phpstan-baseline.neon
Original file line number Diff line number Diff line change
@@ -1,6 +1,31 @@
parameters:
ignoreErrors:
-
message: "#^Call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertInstanceOf\\(\\) with 'LaminasPhpStan\\\\\\\\TestAsset\\\\\\\\BarService' and Laminas\\\\Stdlib\\\\DispatchableInterface will always evaluate to false\\.$#"
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\.$#'
identifier: phpstanApi.runtimeReflection
count: 1
path: src/Rules/Laminas/ServiceManagerGetMethodCallRule.php

-
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\.$#'
identifier: argument.type
count: 1
path: src/ServiceManagerLoader.php

-
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\.$#'
identifier: argument.type
count: 1
path: src/ServiceManagerLoader.php

-
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\.$#'
identifier: phpstanApi.runtimeReflection
count: 2
path: src/Type/Laminas/AbstractServiceLocatorGetDynamicReturnTypeExtension.php

-
message: '#^Call to static method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) with ''LaminasPhpStan\\\\TestAsset\\\\BarService'' and Laminas\\Stdlib\\DispatchableInterface will always evaluate to false\.$#'
identifier: staticMethod.impossibleType
count: 1
path: tests/Type/Laminas/ServiceManagerLoaderTest.php
10 changes: 5 additions & 5 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
<?xml version="1.0"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
bootstrap="./vendor/autoload.php"
colors="true"
verbose="true"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
>
<coverage>
<include>
<directory suffix=".php">./src</directory>
</include>
<report>
<text outputFile="php://stdout" showOnlySummary="true"/>
</report>
</coverage>
<testsuite name="LaminasPhpStan">
<directory>./tests</directory>
</testsuite>
<source>
<include>
<directory>./src</directory>
</include>
</source>
</phpunit>
17 changes: 5 additions & 12 deletions src/Rules/Laminas/ServiceManagerGetMethodCallRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
use LaminasPhpStan\ServiceManagerLoader;
use LaminasPhpStan\Type\Laminas\ObjectServiceManagerType;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use Psr\Container\ContainerInterface as PsrContainerInterface;
Expand All @@ -35,22 +35,15 @@ public function getNodeType(): string
return MethodCall::class;
}

/**
* @param MethodCall $node
*
* @return string[]
*/
/** @param MethodCall $node */
public function processNode(Node $node, Scope $scope): array
{
$args = $node->getArgs();
if (1 !== \count($args)) {
return [];
}

$firstArg = $args[0];
if (! $firstArg instanceof Arg) {
return [];
}
$firstArg = $args[0];
$argType = $scope->getType($firstArg->value);
$constantStrings = $argType->getConstantStrings();
if (1 !== \count($constantStrings)) {
Expand Down Expand Up @@ -92,14 +85,14 @@ public function processNode(Node $node, Scope $scope): array
}
}

return [\sprintf(
return [RuleErrorBuilder::message(\sprintf(
'The service "%s" was not configured in %s%s.',
$serviceName,
$calledOnType instanceof ObjectServiceManagerType
? $calledOnType->getServiceName()
: $calledOnType->getClassName(),
$classDoesNotExistNote
)];
))->identifier('servicemanager.servicenotconfigured')->build()];
}

/** @phpstan-assert-if-true ObjectType $type */
Expand Down
4 changes: 1 addition & 3 deletions src/ServiceManagerLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,10 @@ public function getServiceLocator(string $serviceManagerName): ServiceLocatorInt
}
if (\class_exists(ServiceListenerFactory::class)) {
$refProp = new ReflectionProperty(ServiceListenerFactory::class, 'defaultServiceConfig');
$refProp->setAccessible(true);
$config = $refProp->getValue(new ServiceListenerFactory());
$config = $refProp->getValue(new ServiceListenerFactory());
\assert(\is_array($config));
\assert(\is_array($config['factories']));
unset($config['factories']['config']);
$refProp->setAccessible(false);
$serviceManager->configure($config);
}
foreach ($this->knownModules as $module) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@

use Laminas\ServiceManager\AbstractPluginManager;
use LaminasPhpStan\ServiceManagerLoader;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\ShouldNotHappenException;
use PHPStan\Type\DynamicMethodReturnTypeExtension;
use PHPStan\Type\MixedType;
use PHPStan\Type\NeverType;
Expand Down Expand Up @@ -48,15 +46,7 @@ final public function getTypeFromMethodCall(

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

$firstArg = $args[0];
if (! $firstArg instanceof Arg) {
throw new ShouldNotHappenException(\sprintf(
'Argument passed to %s::%s should be a string, %s given',
$methodReflection->getDeclaringClass()->getName(),
$methodReflection->getName(),
$firstArg->getType()
));
}
$firstArg = $args[0];

Check warning on line 49 in src/Type/Laminas/AbstractServiceLocatorGetDynamicReturnTypeExtension.php

View check run for this annotation

Codecov / codecov/patch

src/Type/Laminas/AbstractServiceLocatorGetDynamicReturnTypeExtension.php#L49

Added line #L49 was not covered by tests
$argType = $scope->getType($firstArg->value);
$constantStringTypes = $argType->getConstantStrings();
if (1 !== \count($constantStringTypes)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
namespace LaminasPhpStan\Type\Laminas\PluginMethodDynamicReturnTypeExtension;

use LaminasPhpStan\ServiceManagerLoader;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;
Expand Down Expand Up @@ -36,17 +35,9 @@ final public function getTypeFromMethodCall(
Scope $scope
): Type {
$firstArg = $methodCall->getArgs()[0];
if (! $firstArg instanceof Arg) {
throw new ShouldNotHappenException(\sprintf(
'Argument passed to %s::%s should be a string, %s given',
$methodReflection->getDeclaringClass()->getName(),
$methodReflection->getName(),
$firstArg->getType()
));
}
$argType = $scope->getType($firstArg->value);
$strings = $argType->getConstantStrings();
$plugin = 1 === \count($strings) ? $strings[0]->getValue() : null;
$argType = $scope->getType($firstArg->value);
$strings = $argType->getConstantStrings();
$plugin = 1 === \count($strings) ? $strings[0]->getValue() : null;

Check warning on line 40 in src/Type/Laminas/PluginMethodDynamicReturnTypeExtension/AbstractPluginMethodDynamicReturnTypeExtension.php

View check run for this annotation

Codecov / codecov/patch

src/Type/Laminas/PluginMethodDynamicReturnTypeExtension/AbstractPluginMethodDynamicReturnTypeExtension.php#L38-L40

Added lines #L38 - L40 were not covered by tests

if (null !== $plugin) {
$pluginManager = $this->serviceManagerLoader->getServiceLocator($this->getPluginManagerName());
Expand Down
4 changes: 2 additions & 2 deletions tests/LaminasIntegration/IntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*/
final class IntegrationTest extends LevelsTestCase
{
public function dataTopics(): array
public static function dataTopics(): array
{
return [
['serviceManagerDynamicReturn'],
Expand All @@ -36,7 +36,7 @@ public function getPhpStanExecutablePath(): string
return __DIR__ . '/../../vendor/bin/phpstan';
}

public function getPhpStanConfigPath(): ?string
public function getPhpStanConfigPath(): string
{
return __DIR__ . '/phpstan.neon';
}
Expand Down
7 changes: 7 additions & 0 deletions tests/LaminasIntegration/data/controllerPluginMethod-10.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"message": "Cannot call method isFoo() on mixed.",
"line": 16,
"ignorable": true
}
]
12 changes: 12 additions & 0 deletions tests/LaminasIntegration/data/serviceManagerDynamicReturn-4.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[
{
"message": "Expression \"(static function (\\LaminasPhpStan\\TestAsset\\FooService $fooService): void {…\" on a separate line does not do anything.",
"line": 52,
"ignorable": true
},
{
"message": "Expression \"(static function (\\LaminasPhpStan\\TestAsset\\FooInterface $fooService): void {…\" on a separate line does not do anything.",
"line": 55,
"ignorable": true
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"ignorable": true
},
{
"message": "Property class@anonymous/stdlibAbstractOptionsProperties.php:27::$myxyz is not writable.",
"message": "Property Laminas\\Stdlib\\AbstractOptions@anonymous/stdlibAbstractOptionsProperties.php:27::$myxyz is not writable.",
"line": 37,
"ignorable": true
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[
{
"message": "Property class@anonymous/stdlibAbstractOptionsProperties.php:27::$myxyz is never read, only written.",
"message": "Property Laminas\\Stdlib\\AbstractOptions@anonymous/stdlibAbstractOptionsProperties.php:27::$myxyz is never read, only written.",
"line": 28,
"ignorable": true
}
Expand Down
7 changes: 3 additions & 4 deletions tests/Type/Laminas/PluginMethodReflectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,20 @@
namespace LaminasPhpStan\Tests\Type\Laminas;

use LaminasPhpStan\Type\Laminas\PluginMethodReflection;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\FunctionVariant;
use PHPStan\Testing\PHPStanTestCase;
use PHPStan\TrinaryLogic;
use PHPStan\Type\ObjectType;
use PHPUnit\Framework\TestCase;
use stdClass;

/**
* @covers \LaminasPhpStan\Type\Laminas\PluginMethodReflection
*/
final class PluginMethodReflectionTest extends TestCase
final class PluginMethodReflectionTest extends PHPStanTestCase
{
public function testTrivialUsage(): void
{
$declaringClass = $this->createMock(ClassReflection::class);
$declaringClass = $this->createReflectionProvider()->getClass(stdClass::class);
$methodName = 'redirect';
$returnType = new ObjectType(stdClass::class);

Expand Down

0 comments on commit 34de4ae

Please sign in to comment.