From ad44bd9371dd12c0f24252eb024015dba5ea6a45 Mon Sep 17 00:00:00 2001 From: Jordi Sala Morales Date: Tue, 2 Nov 2021 08:32:40 +0100 Subject: [PATCH 1/2] PHPStan 1.0 and Psalm level 2 --- composer.json | 10 +++++----- phpstan-baseline.neon | 2 +- phpstan.neon.dist | 4 +++- psalm.xml | 7 ++++++- src/Builder/DatagridBuilder.php | 11 ++++++++++- src/Builder/FormContractor.php | 5 +++++ src/Builder/ListBuilder.php | 5 +++++ src/Builder/ShowBuilder.php | 5 +++++ .../config/doctrine_orm_filter_types.php | 7 +++++++ tests/App/AppKernel.php | 7 +++++++ tests/App/Entity/Reader.php | 2 +- tests/Filter/FilterTestCase.php | 15 +++++++++++++++ tests/Fixtures/Entity/AssociatedEntity.php | 8 ++++---- tests/Fixtures/Entity/ContainerEntity.php | 10 +++++----- tests/Fixtures/Entity/DoubleNameEntity.php | 16 ++++++++-------- tests/Model/ModelManagerTest.php | 2 +- 16 files changed, 88 insertions(+), 28 deletions(-) diff --git a/composer.json b/composer.json index 9de44d033..b2649bab8 100644 --- a/composer.json +++ b/composer.json @@ -56,10 +56,10 @@ "require-dev": { "doctrine/doctrine-fixtures-bundle": "^3.4", "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^0.12.52", - "phpstan/phpstan-phpunit": "^0.12.18", - "phpstan/phpstan-strict-rules": "^0.12.10", - "phpstan/phpstan-symfony": "^0.12.10", + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-phpunit": "^1.0", + "phpstan/phpstan-strict-rules": "^1.0", + "phpstan/phpstan-symfony": "^1.0", "phpunit/phpunit": "^9.5", "psalm/plugin-phpunit": "^0.16", "psalm/plugin-symfony": "^3.0", @@ -71,7 +71,7 @@ "symfony/templating": "^4.4 || ^5.3", "symfony/yaml": "^4.4 || ^5.3", "vimeo/psalm": "^4.1.1", - "weirdan/doctrine-psalm-plugin": "^1.0" + "weirdan/doctrine-psalm-plugin": "^2.0" }, "suggest": { "sonata-project/entity-audit-bundle": "If you want to support for versioning of entities and their associations." diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 599647ecb..d7b0a8c29 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -16,5 +16,5 @@ parameters: message: '#Method Sonata\\DoctrineORMAdminBundle\\Model\\ModelManager::getMetadata\(\) should return Doctrine\\ORM\\Mapping\\ClassMetadata\ but returns Doctrine\\ORM\\Mapping\\ClassMetadata\\.$#' path: src/Model/ModelManager.php - # https://github.com/phpstan/phpstan-strict-rules/issues/131 - message: '#^Call to function in_array\(\) with arguments (0|1), array&nonEmpty and true will always evaluate to true\.$#' + message: '#^Call to function in_array\(\) with arguments (0|1), non-empty-array and true will always evaluate to true\.$#' path: src/Filter/BooleanFilter.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist index b99353330..d61077c83 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -2,12 +2,14 @@ includes: - phpstan-baseline.neon parameters: - level: max + level: 8 paths: - src - tests treatPhpDocTypesAsCertain: false checkGenericClassInNonGenericObjectType: true + checkInternalClassCaseSensitivity: true checkMissingIterableValueType: true checkMissingVarTagTypehint: true checkMissingTypehints: true + checkUninitializedProperties: true diff --git a/psalm.xml b/psalm.xml index 69a55895c..568d58af2 100644 --- a/psalm.xml +++ b/psalm.xml @@ -1,5 +1,5 @@ - + @@ -12,4 +12,9 @@ + + + + + diff --git a/src/Builder/DatagridBuilder.php b/src/Builder/DatagridBuilder.php index 3ed3ee8a1..375a40778 100644 --- a/src/Builder/DatagridBuilder.php +++ b/src/Builder/DatagridBuilder.php @@ -33,6 +33,9 @@ /** * @phpstan-implements DatagridBuilderInterface + * @psalm-suppress DeprecatedInterface + * + * @see https://github.com/sonata-project/SonataAdminBundle/pull/7519 */ final class DatagridBuilder implements DatagridBuilderInterface { @@ -93,7 +96,13 @@ public function fixFieldDescription(FieldDescriptionInterface $fieldDescription) ]); } - // NEXT_MAJOR: Remove the ModelAutocompleteFilter::class check + /** + * NEXT_MAJOR: Remove the ModelAutocompleteFilter::class check. + * + * @psalm-suppress DeprecatedClass + * + * @see https://github.com/sonata-project/SonataDoctrineORMAdminBundle/pull/1545 + */ if ( ModelAutocompleteFilter::class === $fieldDescription->getType() && null === $fieldDescription->getOption('field_type') || ModelAutocompleteType::class === $fieldDescription->getOption('field_type') diff --git a/src/Builder/FormContractor.php b/src/Builder/FormContractor.php index a16e5ec59..3b6461bd1 100644 --- a/src/Builder/FormContractor.php +++ b/src/Builder/FormContractor.php @@ -15,6 +15,11 @@ use Sonata\AdminBundle\Builder\AbstractFormContractor; +/** + * @psalm-suppress DeprecatedInterface + * + * @see https://github.com/sonata-project/SonataAdminBundle/pull/7519 + */ final class FormContractor extends AbstractFormContractor { } diff --git a/src/Builder/ListBuilder.php b/src/Builder/ListBuilder.php index a787a8ad0..188e999de 100644 --- a/src/Builder/ListBuilder.php +++ b/src/Builder/ListBuilder.php @@ -20,6 +20,11 @@ use Sonata\AdminBundle\FieldDescription\FieldDescriptionInterface; use Sonata\AdminBundle\FieldDescription\TypeGuesserInterface; +/** + * @psalm-suppress DeprecatedInterface + * + * @see https://github.com/sonata-project/SonataAdminBundle/pull/7519 + */ final class ListBuilder implements ListBuilderInterface { /** diff --git a/src/Builder/ShowBuilder.php b/src/Builder/ShowBuilder.php index 85e1d56b1..e32422d1b 100644 --- a/src/Builder/ShowBuilder.php +++ b/src/Builder/ShowBuilder.php @@ -18,6 +18,11 @@ use Sonata\AdminBundle\FieldDescription\FieldDescriptionInterface; use Sonata\AdminBundle\FieldDescription\TypeGuesserInterface; +/** + * @psalm-suppress DeprecatedInterface + * + * @see https://github.com/sonata-project/SonataAdminBundle/pull/7519 + */ final class ShowBuilder implements ShowBuilderInterface { /** diff --git a/src/Resources/config/doctrine_orm_filter_types.php b/src/Resources/config/doctrine_orm_filter_types.php index e48533a30..f7425cc8a 100644 --- a/src/Resources/config/doctrine_orm_filter_types.php +++ b/src/Resources/config/doctrine_orm_filter_types.php @@ -59,6 +59,13 @@ $services->set('sonata.admin.orm.filter.type.datetime_range', DateTimeRangeFilter::class) ->tag('sonata.admin.filter.type', ['alias' => 'doctrine_orm_datetime_range']); + /** + * NEXT_MAJOR: Remove this service definition. + * + * @psalm-suppress DeprecatedClass + * + * @see https://github.com/sonata-project/SonataDoctrineORMAdminBundle/pull/1545 + */ $services->set('sonata.admin.orm.filter.type.model_autocomplete', ModelAutocompleteFilter::class) ->tag('sonata.admin.filter.type', ['alias' => 'doctrine_orm_model_autocomplete']); diff --git a/tests/App/AppKernel.php b/tests/App/AppKernel.php index 7def2f735..dfba76c98 100644 --- a/tests/App/AppKernel.php +++ b/tests/App/AppKernel.php @@ -33,6 +33,11 @@ use Symfony\Component\Routing\RouteCollectionBuilder; use Symfony\Component\Security\Http\Authentication\AuthenticatorManager; +/** + * @psalm-suppress PropertyNotSetInConstructor + * + * @see https://github.com/psalm/psalm-plugin-symfony/pull/220 + */ final class AppKernel extends Kernel { use MicroKernelTrait; @@ -78,6 +83,8 @@ public function getProjectDir(): string /** * TODO: Drop RouteCollectionBuilder when support for Symfony < 5.1 is dropped. * + * @psalm-suppress DeprecatedClass + * * @param RoutingConfigurator|RouteCollectionBuilder $routes */ protected function configureRoutes($routes): void diff --git a/tests/App/Entity/Reader.php b/tests/App/Entity/Reader.php index dde115707..685ba5aa3 100644 --- a/tests/App/Entity/Reader.php +++ b/tests/App/Entity/Reader.php @@ -25,7 +25,7 @@ class Reader * * @var int|null */ - private $id; + public $id; public function __construct() { diff --git a/tests/Filter/FilterTestCase.php b/tests/Filter/FilterTestCase.php index abb6c8f8a..bcda76ed3 100644 --- a/tests/Filter/FilterTestCase.php +++ b/tests/Filter/FilterTestCase.php @@ -53,18 +53,27 @@ final protected function createQueryBuilderStub(): TestQueryBuilder $queryBuilder = $this->createStub(TestQueryBuilder::class); $queryBuilder->method('setParameter')->willReturnCallback( + /** + * @param mixed $value + */ static function (string $name, $value) use ($queryBuilder): void { $queryBuilder->queryParameters[$name] = $value; } ); $queryBuilder->method('andWhere')->willReturnCallback( + /** + * @param mixed $query + */ static function ($query) use ($queryBuilder): void { $queryBuilder->query[] = sprintf('WHERE %s', $query); } ); $queryBuilder->method('andHaving')->willReturnCallback( + /** + * @param mixed $query + */ static function ($query) use ($queryBuilder): void { $queryBuilder->query[] = sprintf('HAVING %s', $query); } @@ -120,6 +129,9 @@ static function (): Andx { ); $expr->method('in')->willReturnCallback( + /** + * @param mixed $parameter + */ static function (string $alias, $parameter): string { if (\is_array($parameter)) { return sprintf('%s IN ("%s")', $alias, implode(', ', $parameter)); @@ -130,6 +142,9 @@ static function (string $alias, $parameter): string { ); $expr->method('notIn')->willReturnCallback( + /** + * @param mixed $parameter + */ static function (string $alias, $parameter): string { if (\is_array($parameter)) { return sprintf('%s NOT IN ("%s")', $alias, implode(', ', $parameter)); diff --git a/tests/Fixtures/Entity/AssociatedEntity.php b/tests/Fixtures/Entity/AssociatedEntity.php index e7a9d3844..1f00ea878 100644 --- a/tests/Fixtures/Entity/AssociatedEntity.php +++ b/tests/Fixtures/Entity/AssociatedEntity.php @@ -16,14 +16,14 @@ final class AssociatedEntity { /** - * @var int + * @var Embeddable\EmbeddedEntity */ - private $plainField; + public $embeddedEntity; /** - * @var Embeddable\EmbeddedEntity + * @var int */ - private $embeddedEntity; + private $plainField; public function __construct(Embeddable\EmbeddedEntity $embeddedEntity, int $plainField) { diff --git a/tests/Fixtures/Entity/ContainerEntity.php b/tests/Fixtures/Entity/ContainerEntity.php index 17b8ce92c..f748c4c31 100644 --- a/tests/Fixtures/Entity/ContainerEntity.php +++ b/tests/Fixtures/Entity/ContainerEntity.php @@ -18,17 +18,17 @@ final class ContainerEntity /** * @var int|null */ - private $plainField; + public $plainField; /** - * @var AssociatedEntity + * @var Embeddable\EmbeddedEntity */ - private $associatedEntity; + public $embeddedEntity; /** - * @var Embeddable\EmbeddedEntity + * @var AssociatedEntity */ - private $embeddedEntity; + private $associatedEntity; public function __construct(AssociatedEntity $associatedEntity, Embeddable\EmbeddedEntity $embeddedEntity) { diff --git a/tests/Fixtures/Entity/DoubleNameEntity.php b/tests/Fixtures/Entity/DoubleNameEntity.php index 70e5e74c6..628441fbb 100644 --- a/tests/Fixtures/Entity/DoubleNameEntity.php +++ b/tests/Fixtures/Entity/DoubleNameEntity.php @@ -20,6 +20,14 @@ /** @Entity */ final class DoubleNameEntity { + /** + * @Id + * @Column(type="integer") + * + * @var int + */ + public $id; + /** * @Column(type="string") * @@ -34,14 +42,6 @@ final class DoubleNameEntity */ public $name2; - /** - * @Id - * @Column(type="integer") - * - * @var int - */ - private $id; - public function __construct(int $id, string $name, ?string $name2) { $this->id = $id; diff --git a/tests/Model/ModelManagerTest.php b/tests/Model/ModelManagerTest.php index 05b65fcbc..4d322cf2e 100644 --- a/tests/Model/ModelManagerTest.php +++ b/tests/Model/ModelManagerTest.php @@ -519,7 +519,7 @@ public function testAddIdentifiersToQuery(array $expectedParameters, array $iden /** @var QueryBuilder&MockObject $queryBuilder */ $queryBuilder = $this->getMockBuilder(QueryBuilder::class) ->setConstructorArgs([$em]) - ->setMethodsExcept(['getParameters', 'setParameter']) + ->onlyMethods(['getRootAliases', 'andWhere']) ->getMock(); $queryBuilder From 3e753c8c8c1bb5c362990374d682e435af2b2996 Mon Sep 17 00:00:00 2001 From: Jordi Sala Morales Date: Tue, 2 Nov 2021 08:53:34 +0100 Subject: [PATCH 2/2] Improve php-cs-fixer configuration --- .php-cs-fixer.dist.php | 1 + 1 file changed, 1 insertion(+) diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 534b21846..7ac21310c 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -48,6 +48,7 @@ 'php_unit_test_annotation' => false, 'php_unit_test_case_static_method_calls' => true, 'phpdoc_order' => true, + 'phpdoc_to_comment' => ['ignored_tags' => ['psalm-suppress']], 'single_line_throw' => false, 'static_lambda' => true, 'strict_comparison' => true,