Skip to content

Commit

Permalink
Update PHPStan to 2.x (#1492)
Browse files Browse the repository at this point in the history
* Update PHPStan to 2.x

* Update deps

* Update baseline
  • Loading branch information
Seldaek authored Nov 27, 2024
1 parent 8b3b1aa commit 1c4918f
Show file tree
Hide file tree
Showing 39 changed files with 360 additions and 380 deletions.
14 changes: 7 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,14 @@
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.4",
"phpstan/phpstan": "^1.9.2",
"phpstan/phpstan-deprecation-rules": "^1.1",
"phpstan/phpstan-doctrine": "^1",
"phpstan/phpstan-symfony": "^1.1",
"phpstan/phpstan-webmozart-assert": "^1.2",
"phpstan/phpstan": "^2",
"phpstan/phpstan-deprecation-rules": "^2",
"phpstan/phpstan-doctrine": "^2",
"phpstan/phpstan-symfony": "^2",
"phpstan/phpstan-webmozart-assert": "^2",
"phpunit/phpunit": "^11.0",
"staabm/phpstan-dba": "^0.2",
"staabm/phpstan-todo-by": "^0.1.27",
"staabm/phpstan-dba": "^0.3",
"staabm/phpstan-todo-by": "^0.2",
"symfony/browser-kit": "^7",
"symfony/css-selector": "^7",
"symfony/debug-bundle": "^7",
Expand Down
468 changes: 233 additions & 235 deletions composer.lock

Large diffs are not rendered by default.

60 changes: 42 additions & 18 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
@@ -1,61 +1,85 @@
parameters:
ignoreErrors:
-
message: "#^Dead catch \\- Symfony\\\\Component\\\\Lock\\\\Exception\\\\LockReleasingException is never thrown in the try block\\.$#"
message: '#^Dead catch \- Symfony\\Component\\Lock\\Exception\\LockReleasingException is never thrown in the try block\.$#'
identifier: catch.neverThrown
count: 1
path: src/Command/RunWorkersCommand.php

-
message: "#^Parameter \\#1 \\$job of method App\\\\Service\\\\UpdaterWorker\\:\\:process\\(\\) expects App\\\\Entity\\\\Job\\<array\\{id\\: int, update_equal_refs\\: bool, delete_before\\: bool, force_dump\\: bool\\}\\>, App\\\\Entity\\\\Job\\<array\\{id\\: int, update_equal_refs\\: false, delete_before\\: false, force_dump\\: false\\}\\> given\\.$#"
count: 1
path: src/DataFixtures/PackageFixtures.php

-
message: "#^Query error\\: Column \"audit_log\\.attributes\" expects value type string, got type array\\<string, mixed\\>$#"
message: '#^Query error\: Column "audit_log\.attributes" expects value type string, got type array\<string, mixed\>$#'
identifier: dba.keyValue
count: 1
path: src/Entity/AuditRecordRepository.php

-
message: "#^Query error\\: Column \"audit_log\\.datetime\" expects value type string, got type DateTimeImmutable$#"
message: '#^Query error\: Column "audit_log\.datetime" expects value type string, got type DateTimeImmutable$#'
identifier: dba.keyValue
count: 1
path: src/Entity/AuditRecordRepository.php

-
message: "#^Query error\\: Column \"audit_log\\.id\" expects value type string, got type Symfony\\\\Component\\\\Uid\\\\Ulid$#"
message: '#^Query error\: Column "audit_log\.id" expects value type string, got type Symfony\\Component\\Uid\\Ulid$#'
identifier: dba.keyValue
count: 1
path: src/Entity/AuditRecordRepository.php

-
message: "#^Method App\\\\Entity\\\\PackageRepository\\:\\:getDependents\\(\\) should return array\\<array\\{id\\: int, name\\: string, description\\: string\\|null, language\\: string\\|null, abandoned\\: int, replacementPackage\\: string\\|null\\}\\> but returns array\\<int\\<0, max\\>, non\\-empty\\-array\\<string, mixed\\>\\>\\.$#"
message: '#^Method App\\Entity\\PackageRepository\:\:getSuggestCount\(\) should return int\<0, max\> but returns int\.$#'
identifier: return.type
count: 1
path: src/Entity/PackageRepository.php

-
message: "#^Method App\\\\Entity\\\\PackageRepository\\:\\:getSuggestCount\\(\\) should return int\\<0, max\\> but returns int\\.$#"
message: '#^Query error\: Unknown column ''d\.total'' in ''order clause'' \(1054\)\.$#'
identifier: dba.syntaxError
count: 1
path: src/Entity/PackageRepository.php

-
message: "#^Query error\\: Unknown column 'd\\.total' in 'order clause' \\(1054\\)\\.$#"
message: '#^Method App\\Entity\\PhpStatRepository\:\:getStatVersions\(\) should return list\<array\{version\: string, depth\: 0\|1\|2\|3\}\> but returns array\<mixed\>\.$#'
identifier: return.type
count: 1
path: src/Entity/PackageRepository.php
path: src/Entity/PhpStatRepository.php

-
message: "#^Offset 'name' on array\\{name\\: string, description\\?\\: string\\} on left side of \\?\\? always exists and is not nullable\\.$#"
message: '#^Offset ''name'' on array\{name\: string, description\?\: string\} on left side of \?\? always exists and is not nullable\.$#'
identifier: nullCoalesce.offset
count: 2
path: src/Entity/Version.php

-
message: "#^Method App\\\\Model\\\\FavoriteManager\\:\\:getFavoriteCount\\(\\) should return int\\<0, max\\> but returns int\\.$#"
message: '#^Method App\\Model\\FavoriteManager\:\:getFavoriteCount\(\) should return int\<0, max\> but returns int\.$#'
identifier: return.type
count: 1
path: src/Model/FavoriteManager.php

-
message: "#^Parameter \\#1 \\$job of method App\\\\Service\\\\GitHubUserMigrationWorker\\:\\:process\\(\\) expects App\\\\Entity\\\\Job\\<array\\{id\\: int, update_equal_refs\\: bool, delete_before\\: bool, force_dump\\: bool\\}\\>\\|App\\\\Entity\\\\Job\\<array\\{id\\: int, old_scope\\: string, new_scope\\: string\\}\\>\\|App\\\\Entity\\\\Job\\<array\\{source\\: string\\}\\>, App\\\\Entity\\\\Job\\<array\\<string, bool\\|int\\|string\\>\\> given\\.$#"
message: '#^Parameter \#1 \$ids of method App\\Entity\\PackageRepository\:\:getPackagesWithVersions\(\) expects list\<int\>\|null, array\<int\<0, max\>, int\> given\.$#'
identifier: argument.type
count: 1
path: src/Service/QueueWorker.php
path: src/Package/SymlinkDumper.php

-
message: '#^Method App\\Package\\Updater\:\:sanitize\(\) should return T of string\|null but returns null\.$#'
identifier: return.type
count: 1
path: src/Package/Updater.php

-
message: '#^Method App\\Package\\Updater\:\:sanitize\(\) should return T of string\|null but returns string\.$#'
identifier: return.type
count: 1
path: src/Package/Updater.php

-
message: '#^Parameter \#1 \$ids of method App\\Entity\\PackageRepository\:\:getPackagesWithVersions\(\) expects list\<int\>\|null, array\<int\<0, max\>, int\> given\.$#'
identifier: argument.type
count: 1
path: src/Package/V2Dumper.php

-
message: "#^Parameter \\#1 \\$result of method App\\\\Entity\\\\Job\\<array\\<string, bool\\|int\\|string\\>\\>\\:\\:complete\\(\\) expects array\\{status\\: 'completed'\\|'errored'\\|'failed'\\|'package_deleted'\\|'package_gone'\\|'queued'\\|'reschedule'\\|'started'\\|'timeout', message\\?\\: string, after\\?\\: DateTimeInterface&Throwable, details\\?\\: string, exception\\?\\: Throwable, exceptionMsg\\?\\: string, exceptionClass\\?\\: class\\-string\\<Throwable\\>, results\\?\\: array, \\.\\.\\.\\}, array\\{status\\: 'completed'\\|'errored'\\|'failed'\\|'package_deleted'\\|'package_gone', message\\: string, after\\?\\: DateTimeInterface, details\\?\\: string, exception\\?\\: Throwable, exceptionMsg\\?\\: string, exceptionClass\\?\\: class\\-string\\<Throwable\\>, results\\?\\: array, \\.\\.\\.\\} given\\.$#"
message: '#^Parameter \#1 \$job of method App\\Service\\GitHubUserMigrationWorker\:\:process\(\) expects App\\Entity\\Job\<array\{id\: int, update_equal_refs\: bool, delete_before\: bool, force_dump\: bool\}\>\|App\\Entity\\Job\<array\{id\: int, old_scope\: string, new_scope\: string\}\>\|App\\Entity\\Job\<array\{source\: string\}\>, App\\Entity\\Job\<array\<string, bool\|int\|string\>\> given\.$#'
identifier: argument.type
count: 1
path: src/Service/QueueWorker.php
1 change: 1 addition & 0 deletions phpstan-bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
$config->stringifyTypes(false);
// $config->analyzeQueryPlans(true);
// $config->debugMode(true);
// $config->utilizeSqlAst(true); // requires sqlftw/sqlftw

(new Dotenv())->bootEnv(__DIR__ . '/.env');
$dsn = parse_url($_SERVER['DATABASE_URL']);
Expand Down
15 changes: 13 additions & 2 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,16 @@ parameters:
PackageUpdateJob: 'array{id: int, update_equal_refs: bool, delete_before: bool, force_dump: bool}'
GitHubUserMigrateJob: 'array{id: int, old_scope: string, new_scope: string}'
SecurityAdvisoryJob: 'array{source: string}'
# TODO maybe split those results per class as well instead of this cobbled up mess
JobResult: 'array{status: \App\Entity\Job::STATUS_*, message?: string, after?: \DateTimeInterface, details?: string, exception?: \Throwable, exceptionMsg?: string, exceptionClass?: class-string<\Throwable>, results?: array<mixed>, vendor?: string}'

JobResult: 'array{status: \App\Entity\Job::STATUS_*, message: string, vendor?: string, details?: string, exceptionMsg?: string, exceptionClass?: class-string<\Throwable>, results?: array{hooks_setup: int, hooks_failed: array<int, array{package: string, reason: mixed}>, hooks_ok_unchanged: int}}'
ErroredResult: 'array{status: \App\Entity\Job::STATUS_ERRORED, message: string, exception: \Throwable}'
GenericCompletedResult: 'array{status: \App\Entity\Job::STATUS_COMPLETED, message: string}'
RescheduleResult: 'array{status: \App\Entity\Job::STATUS_RESCHEDULE, after: \DateTimeInterface, message: string, vendor?: string}'
PackageCompletedResult: 'array{status: \App\Entity\Job::STATUS_COMPLETED, message: string, details: string, vendor: string}'
PackageFailedResult: 'array{status: \App\Entity\Job::STATUS_FAILED, message: string, vendor: string, exception: \Throwable, details?: string}'
PackageGoneResult: 'array{status: \App\Entity\Job::STATUS_PACKAGE_GONE, message: string, vendor: string, exception: \Throwable, details?: string}'
PackageDeletedResult: 'array{status: \App\Entity\Job::STATUS_PACKAGE_DELETED, message: string, vendor: string, exception: \Throwable, details: string}'
AdvisoriesCompletedResult: 'array{status: \App\Entity\Job::STATUS_COMPLETED, message: string, details: string}'
AdvisoriesErroredResult: 'array{status: \App\Entity\Job::STATUS_ERRORED, message: string}'
GitHubMigrationResult: 'array{status: \App\Entity\Job::STATUS_COMPLETED, message: string, results: array{hooks_setup: int, hooks_failed: array<int, array{package: string, reason: mixed}>, hooks_ok_unchanged: int}}'
GitHubMigrationFailedResult: 'array{status: \App\Entity\Job::STATUS_FAILED, message: string}'
1 change: 0 additions & 1 deletion src/Controller/ExploreController.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ public function popularAction(Request $req, RedisClient $redis, FavoriteManager
'total' => $packages->getNbResults(),
];

/** @var Package $package */
foreach ($packages as $package) {
$url = $this->generateUrl('view_package', ['name' => $package->getName()], UrlGeneratorInterface::ABSOLUTE_URL);

Expand Down
9 changes: 9 additions & 0 deletions src/Controller/PackageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -1571,13 +1571,19 @@ public function securityAdvisoryAction(Request $request, string $id): Response
return $this->render('package/security_advisory.html.twig', ['securityAdvisories' => $securityAdvisories, 'id' => $id]);
}

/**
* @return FormInterface<MaintainerRequest>
*/
private function createAddMaintainerForm(Package $package): FormInterface
{
$maintainerRequest = new MaintainerRequest();

return $this->createForm(AddMaintainerRequestType::class, $maintainerRequest);
}

/**
* @return FormInterface<MaintainerRequest>
*/
private function createRemoveMaintainerForm(Package $package): FormInterface
{
$maintainerRequest = new MaintainerRequest();
Expand All @@ -1587,6 +1593,9 @@ private function createRemoveMaintainerForm(Package $package): FormInterface
]);
}

/**
* @return FormInterface<array{}>
*/
private function createDeletePackageForm(Package $package): FormInterface
{
return $this->createFormBuilder([])->getForm();
Expand Down
6 changes: 3 additions & 3 deletions src/Controller/WebController.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public function searchApi(Request $req, Algolia $algolia): JsonResponse
try {
$query = new Query(
$req->query->has('q') ? $req->query->getString('q') : $req->query->getString('query'),
(array) ($req->query->all()['tags'] ?? []),
array_values((array) ($req->query->all()['tags'] ?? [])),
$req->query->getString('type', ''),
$req->query->getInt('per_page', 15),
$req->query->getInt('page', 1)
Expand Down Expand Up @@ -177,9 +177,9 @@ public function statsAction(RedisClient $redis): Response
'versions' => !empty($chart['versions']) ? max($chart['versions']) : 0,
'downloads' => $downloads,
'downloadsChart' => $dlChart,
'maxDailyDownloads' => !empty($dlChart) ? max($dlChart['values']) : null,
'maxDailyDownloads' => !empty($dlChart) && \count($dlChart['values']) > 0 ? max($dlChart['values']) : null,
'downloadsChartMonthly' => $dlChartMonthly,
'maxMonthlyDownloads' => !empty($dlChartMonthly) ? max($dlChartMonthly['values']) : null,
'maxMonthlyDownloads' => !empty($dlChartMonthly) && \count($dlChartMonthly['values']) > 0 ? max($dlChartMonthly['values']) : null,
'downloadsStartDate' => $downloadsStartDate,
]);
}
Expand Down
33 changes: 0 additions & 33 deletions src/Entity/DependentRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@
use Doctrine\Persistence\ManagerRegistry;

/**
* @method Dependent|null find($id, $lockMode = null, $lockVersion = null)
* @method Dependent|null findOneBy(array $criteria, array $orderBy = null)
* @method Dependent[] findAll()
* @method Dependent[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
* @extends ServiceEntityRepository<Dependent>
*/
class DependentRepository extends ServiceEntityRepository
Expand Down Expand Up @@ -63,33 +59,4 @@ public function deletePackageDependentSuggesters(int $packageId): void
$conn->executeStatement('DELETE FROM dependent WHERE package_id = :id', ['id' => $packageId]);
$conn->executeStatement('DELETE FROM suggester WHERE package_id = :id', ['id' => $packageId]);
}

// /**
// * @return Dependent[] Returns an array of Dependent objects
// */
/*
public function findByExampleField($value)
{
return $this->createQueryBuilder('d')
->andWhere('d.exampleField = :val')
->setParameter('val', $value)
->orderBy('d.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
}
*/

/*
public function findOneBySomeField($value): ?Dependent
{
return $this->createQueryBuilder('d')
->andWhere('d.exampleField = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
}
*/
}
6 changes: 3 additions & 3 deletions src/Entity/Job.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class Job
#[ORM\Column(type: 'string')]
private string $status = self::STATUS_QUEUED;

/** @var (JobResult&array<string, int|string|bool|null|array<mixed>|\Throwable>)|null */
/** @var JobResult|null */
#[ORM\Column(type: 'json', nullable: true)]
private ?array $result = null;

Expand Down Expand Up @@ -97,7 +97,7 @@ public function start(): void
}

/**
* @param JobResult&array<string, int|string|bool|null|array<mixed>|\Throwable> $result
* @param JobResult $result
*/
public function complete(array $result): void
{
Expand Down Expand Up @@ -158,7 +158,7 @@ public function getStatus(): string
}

/**
* @return JobResult&array<string, int|string|bool|null|array<mixed>|\Throwable>
* @return JobResult
*/
public function getResult(): ?array
{
Expand Down
4 changes: 3 additions & 1 deletion src/Entity/PackageRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ public function getPackagesWithFields(array $filters, array $fields): array
}

/**
* @param Query<mixed, array{name: string}> $query
* @return list<string>
*/
private function getPackageNamesForQuery(Query $query): array
Expand Down Expand Up @@ -500,7 +501,7 @@ public function getDependentCount(string $name, ?int $type = null): int
* @param string $name Package name to find the dependents of
* @param int|null $type One of Dependent::TYPE_*
* @param 'downloads'|'name' $orderBy
* @return array<array{id: int, name: string, description: string|null, language: string|null, abandoned: int, replacementPackage: string|null}>
* @return list<array{id: int, name: string, description: string|null, language: string|null, abandoned: int, replacementPackage: string|null}>
*/
public function getDependents(string $name, int $offset = 0, int $limit = 15, string $orderBy = 'name', ?int $type = null): array
{
Expand All @@ -526,6 +527,7 @@ public function getDependents(string $name, int $offset = 0, int $limit = 15, st
) x ON x.package_id = p.id '.$join.' ORDER BY '.$orderByField.' LIMIT '.((int) $limit).' OFFSET '.((int) $offset);

$res = [];
/** @var array{id: int, name: string, description: string|null, language: string|null, abandoned: bool, replacementPackage: string|null} $row */
foreach ($this->getEntityManager()->getConnection()->fetchAllAssociative($sql, $args) as $row) {
$res[] = ['id' => (int) $row['id'], 'abandoned' => (int) $row['abandoned']] + $row;
}
Expand Down
33 changes: 0 additions & 33 deletions src/Entity/SuggesterRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@
use Doctrine\Persistence\ManagerRegistry;

/**
* @method Suggester|null find($id, $lockMode = null, $lockVersion = null)
* @method Suggester|null findOneBy(array $criteria, array $orderBy = null)
* @method Suggester[] findAll()
* @method Suggester[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
* @extends ServiceEntityRepository<Suggester>
*/
class SuggesterRepository extends ServiceEntityRepository
Expand All @@ -28,33 +24,4 @@ public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Suggester::class);
}

// /**
// * @return Suggester[] Returns an array of Suggester objects
// */
/*
public function findByExampleField($value)
{
return $this->createQueryBuilder('d')
->andWhere('d.exampleField = :val')
->setParameter('val', $value)
->orderBy('d.id', 'ASC')
->setMaxResults(10)
->getQuery()
->getResult()
;
}
*/

/*
public function findOneBySomeField($value): ?Suggester
{
return $this->createQueryBuilder('d')
->andWhere('d.exampleField = :val')
->setParameter('val', $value)
->getQuery()
->getOneOrNullResult()
;
}
*/
}
2 changes: 1 addition & 1 deletion src/Entity/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class User implements UserInterface, TwoFactorInterface, BackupCodeInterface, Eq
private bool $enabled = false;

/**
* @var list<string>
* @var array<string>
*/
#[ORM\Column(type: 'json')]
private array $roles = [];
Expand Down
4 changes: 2 additions & 2 deletions src/Entity/Version.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@
* autoload?: array<mixed>,
* extra?: array<mixed>,
* target-dir?: string,
* include-path?: list<string>,
* bin?: list<string>,
* include-path?: array<string>,
* bin?: array<string>,
* default-branch?: true,
* require?: array<string, string>,
* require-dev?: array<string, string>,
Expand Down
3 changes: 3 additions & 0 deletions src/Form/ChangePasswordFormType.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
use Symfony\Component\Security\Core\Validator\Constraints\UserPassword;
use Symfony\Component\Validator\Constraints\NotBlank;

/**
* @extends AbstractType<User>
*/
class ChangePasswordFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
Expand Down
3 changes: 3 additions & 0 deletions src/Form/RegistrationFormType.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\IsTrue;

/**
* @extends AbstractType<User>
*/
class RegistrationFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
Expand Down
Loading

0 comments on commit 1c4918f

Please sign in to comment.