Skip to content

Commit

Permalink
Merge pull request #2437 from franmomu/specify_iterator_types_tests
Browse files Browse the repository at this point in the history
Add PHPStan check for iterable types
  • Loading branch information
malarzm authored Nov 6, 2022
2 parents 5987555 + babf193 commit 0981d3d
Show file tree
Hide file tree
Showing 48 changed files with 288 additions and 96 deletions.
10 changes: 5 additions & 5 deletions benchmark/Document/HydrateDocumentBench.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,19 @@
*/
final class HydrateDocumentBench extends BaseBench
{
/** @var array */
/** @var array<string, mixed> */
private static $data;

/** @var array */
/** @var array<string, mixed> */
private static $embedOneData;

/** @var array */
/** @var array<string, mixed[]> */
private static $embedManyData;

/** @var array */
/** @var array<string, mixed[]> */
private static $referenceOneData;

/** @var array */
/** @var array<string, mixed[]> */
private static $referenceManyData;

/** @var HydratorInterface */
Expand Down
6 changes: 6 additions & 0 deletions lib/Doctrine/ODM/MongoDB/Aggregation/Stage/Lookup.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ class Lookup extends Stage

private ?string $as = null;

/** @var array<string, string>|null */
private ?array $let = null;

/** @var array<array<string, mixed>>|null */
private ?array $pipeline = null;

private bool $excludeLocalAndForeignField = false;
Expand Down Expand Up @@ -155,6 +157,8 @@ public function foreignField(string $foreignField): self
*
* Use the variable expressions to access the fields from
* the joined collection's documents that are input to the pipeline.
*
* @param array<string, string> $let
*/
public function let(array $let): self
{
Expand All @@ -172,6 +176,8 @@ public function let(array $let): self
* The pipeline cannot directly access the joined document fields.
* Instead, define variables for the joined document fields using the let option
* and then reference the variables in the pipeline stages.
*
* @param array<array<string, mixed>> $pipeline
*/
public function pipeline(array $pipeline): self
{
Expand Down
15 changes: 7 additions & 8 deletions lib/Doctrine/ODM/MongoDB/Iterator/HydratingIterator.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@
*
* @psalm-import-type Hints from UnitOfWork
*
* @template TValue
* @template TDocument of object
* @template-implements Iterator<TValue>
* @template-implements Iterator<TDocument>
*/
final class HydratingIterator implements Iterator
{
/** @var Generator<mixed, TValue>|null */
/** @var Generator<mixed, array<string, mixed>>|null */
private $iterator;

private UnitOfWork $unitOfWork;
Expand All @@ -40,8 +39,8 @@ final class HydratingIterator implements Iterator
private array $unitOfWorkHints;

/**
* @param Traversable<mixed, TValue> $traversable
* @param ClassMetadata<TDocument> $class
* @param Traversable<mixed, array<string, mixed>> $traversable
* @param ClassMetadata<TDocument> $class
* @psalm-param Hints $unitOfWorkHints
*/
public function __construct(Traversable $traversable, UnitOfWork $unitOfWork, ClassMetadata $class, array $unitOfWorkHints = [])
Expand Down Expand Up @@ -100,7 +99,7 @@ public function valid(): bool
}

/**
* @return Generator<mixed, TValue>
* @return Generator<mixed, array<string, mixed>>
*/
private function getIterator(): Generator
{
Expand All @@ -122,9 +121,9 @@ private function hydrate(?array $document): ?object
}

/**
* @param Traversable<mixed, TValue> $traversable
* @param Traversable<mixed, array<string, mixed>> $traversable
*
* @return Generator<mixed, TValue>
* @return Generator<mixed, array<string, mixed>>
*/
private function wrapTraversable(Traversable $traversable): Generator
{
Expand Down
10 changes: 9 additions & 1 deletion lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,15 @@
* alsoLoadFields?: list<string>,
* }
* @psalm-type IndexKeys = array<string, mixed>
* @psalm-type IndexOptions = array<string, mixed>
* @psalm-type IndexOptions = array{
* background?: bool,
* unique?: bool,
* name?: string,
* partialFilterExpression?: mixed[],
* sparse?: bool,
* expireAfterSeconds?: int,
* storageEngine?: mixed[],
* }
* @psalm-type IndexMapping = array{
* keys: IndexKeys,
* options: IndexOptions
Expand Down
16 changes: 5 additions & 11 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,6 @@ parameters:
count: 1
path: tests/Doctrine/ODM/MongoDB/Tests/Query/BuilderTest.php

-
message: "#^Method Doctrine\\\\ODM\\\\MongoDB\\\\Tests\\\\SchemaManagerTest\\:\\:writeOptions\\(\\) should return PHPUnit\\\\Framework\\\\Constraint\\\\Constraint but returns PHPUnit\\\\Framework\\\\Constraint\\\\ArraySubset\\.$#"
count: 1
path: tests/Doctrine/ODM/MongoDB/Tests/SchemaManagerTest.php

# Support for doctrine/collections v1
-
message: '#^Method Doctrine\\ODM\\MongoDB\\PersistentCollection\:\:add\(\) with return type void returns true but should not return anything\.$#'
Expand Down Expand Up @@ -143,12 +138,6 @@ parameters:
count: 1
path: tests/Doctrine/ODM/MongoDB/Tests/DocumentRepositoryTest.php

# 'strategy' offset is defined as nullable, but here there is no check here
-
message: "#^Offset 'strategy' does not exist on array\\{\\}\\|array\\{type\\?\\: string, fieldName\\: string, name\\: string, isCascadeRemove\\: bool, isCascadePersist\\: bool, isCascadeRefresh\\: bool, isCascadeMerge\\: bool, isCascadeDetach\\: bool, \\.\\.\\.\\}\\.$#"
count: 1
path: lib/Doctrine/ODM/MongoDB/UnitOfWork.php

# When iterating over SimpleXMLElement, we cannot know the key values
-
message: "#^Parameter \\#2 \\$mapping of method Doctrine\\\\ODM\\\\MongoDB\\\\Mapping\\\\Driver\\\\XmlDriver\\:\\:addFieldMapping\\(\\) expects array#"
Expand Down Expand Up @@ -248,3 +237,8 @@ parameters:
message: "#^Call to an undefined method ReflectionEnum\\:\\:getBackingType\\(\\)\\.$#"
count: 1
path: lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadata.php

-
message: "#has parameter \\$[^\\s]+ with no value type specified in iterable type array\\.$#"
count: 6
path: tests/*
4 changes: 4 additions & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@ parameters:
- tests/PersistentCollections/
- tests/Proxies/
treatPhpDocTypesAsCertain: false
ignoreErrors:
# Ignore typing providers in tests
- '#^Method Doctrine\\ODM\\MongoDB\\Tests\\[^:]+(Test)::(get\w+|data\w+|provide\w+)\(\) return type has no value type specified in iterable type (array|iterable)\.#'
# To be removed when reaching phpstan level 6
checkMissingVarTagTypehint: true
checkMissingTypehints: true
checkMissingIterableValueType: true

# To be removed when reaching phpstan level 6
rules:
Expand Down
28 changes: 4 additions & 24 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="4.22.0@fc2c6ab4d5fa5d644d8617089f012f3bb84b8703">
<files psalm-version="4.29.0@7ec5ffbd5f68ae03782d7fd33fff0c45a69f95b3">
<file src="lib/Doctrine/ODM/MongoDB/Aggregation/Builder.php">
<InvalidArgument occurrences="1">
<code>$fields</code>
Expand All @@ -23,11 +23,6 @@
<code>TValue|false</code>
</ImplementedReturnTypeMismatch>
</file>
<file src="lib/Doctrine/ODM/MongoDB/Iterator/HydratingIterator.php">
<ImplementedReturnTypeMismatch occurrences="1">
<code>TDocument|null</code>
</ImplementedReturnTypeMismatch>
</file>
<file src="lib/Doctrine/ODM/MongoDB/Mapping/ClassMetadata.php">
<ImplementedReturnTypeMismatch occurrences="2">
<code>array&lt;string|null&gt;</code>
Expand All @@ -36,15 +31,15 @@
<InvalidArrayOffset occurrences="1">
<code>[$this-&gt;identifier =&gt; $this-&gt;getIdentifierValue($object)]</code>
</InvalidArrayOffset>
<LessSpecificImplementedReturnType occurrences="2">
<code>?string</code>
<LessSpecificImplementedReturnType occurrences="1">
<code>array</code>
</LessSpecificImplementedReturnType>
</file>
<file src="lib/Doctrine/ODM/MongoDB/Mapping/Driver/XmlDriver.php">
<InvalidArgument occurrences="2">
<InvalidArgument occurrences="3">
<code>$mapping</code>
<code>$mapping</code>
<code>$options</code>
</InvalidArgument>
<RedundantCondition occurrences="15">
<code>assert($attributes instanceof SimpleXMLElement)</code>
Expand Down Expand Up @@ -80,12 +75,6 @@
<code>$p</code>
<code>$p</code>
</InvalidArgument>
<InvalidNullableReturnType occurrences="1">
<code>getMapping</code>
</InvalidNullableReturnType>
<InvalidReturnType occurrences="1">
<code>getTypeClass</code>
</InvalidReturnType>
</file>
<file src="lib/Doctrine/ODM/MongoDB/Persisters/DocumentPersister.php">
<RedundantFunctionCall occurrences="1">
Expand Down Expand Up @@ -122,10 +111,6 @@
</RedundantCondition>
</file>
<file src="lib/Doctrine/ODM/MongoDB/UnitOfWork.php">
<InvalidPropertyAssignmentValue occurrences="2">
<code>$this-&gt;identityMap</code>
<code>$this-&gt;originalDocumentData</code>
</InvalidPropertyAssignmentValue>
<NullableReturnStatement occurrences="1">
<code>$mapping['targetDocument']</code>
</NullableReturnStatement>
Expand Down Expand Up @@ -182,11 +167,6 @@
<code>1</code>
</InvalidScalarArgument>
</file>
<file src="tests/Doctrine/ODM/MongoDB/Tests/Query/QueryExpressionVisitorTest.php">
<TooManyArguments occurrences="1">
<code>andX</code>
</TooManyArguments>
</file>
<file src="tests/Doctrine/ODM/MongoDB/Tests/QueryTest.php">
<InvalidArgument occurrences="1">
<code>['type' =&gt; -1]</code>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,9 @@ protected function createExpr(): Expr
}

/**
* @param mixed $args
* @param Closure(Expr): mixed[]|mixed[] $args
*
* @return mixed[]
*/
protected function resolveArgs($args): array
{
Expand Down
6 changes: 4 additions & 2 deletions tests/Doctrine/ODM/MongoDB/Tests/Aggregation/ExprTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ class ExprTest extends BaseTest
use AggregationOperatorsProviderTrait;

/**
* @param array|Closure $args
* @param array<string, string> $expected
* @param Closure(Expr): mixed[]|mixed[] $args
*
* @dataProvider provideAllOperators
*/
Expand All @@ -29,7 +30,8 @@ public function testGenericOperator(array $expected, string $operator, $args): v
}

/**
* @param array|Closure $args
* @param array<string, string> $expected
* @param Closure(Expr): mixed[]|mixed[] $args
*
* @dataProvider provideAllOperators
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ public function provideEmployeeAggregations(): array
}

/**
* @param Closure(Builder): GraphLookup $addGraphLookupStage
* @param array<string, string> $expectedFields
*
* @dataProvider provideEmployeeAggregations
*/
public function testGraphLookupWithEmployees(Closure $addGraphLookupStage, array $expectedFields): void
Expand Down Expand Up @@ -218,6 +221,9 @@ public function provideTravellerAggregations(): array
}

/**
* @param Closure(Builder): GraphLookup $addGraphLookupStage
* @param array<string, string> $expectedFields
*
* @dataProvider provideTravellerAggregations
*/
public function testGraphLookupWithTraveller(Closure $addGraphLookupStage, array $expectedFields): void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class GroupTest extends BaseTest
use AggregationOperatorsProviderTrait;

/**
* @param Closure|array $args
* @param Closure(Expr): Expr[]|mixed[] $args
*
* @dataProvider provideProxiedExprMethods
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ class OperatorTest extends BaseTest
use AggregationOperatorsProviderTrait;

/**
* @param Closure|array $args
* @param array<string, mixed> $expected
* @param Closure(Expr): mixed[]|mixed[] $args
*
* @dataProvider provideExpressionOperators
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ public function provideAccumulators(): array
}

/**
* @param string[] $args
*
* @dataProvider provideProxiedExprMethods
*/
public function testProxiedExprMethods(string $method, array $args = []): void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@
use Doctrine\ODM\MongoDB\Tests\Aggregation\AggregationTestTrait;
use Doctrine\ODM\MongoDB\Tests\BaseTest;

/**
* @psalm-import-type SortShape from Sort
*/
class SortTest extends BaseTest
{
use AggregationTestTrait;

/**
* @param string|array<string, string> $field
* @psalm-param SortShape $expectedSort
*
* @dataProvider provideSortOptions
*/
Expand All @@ -26,6 +30,7 @@ public function testSortStage(array $expectedSort, $field, ?string $order = null

/**
* @param string|array<string, string> $field
* @psalm-param SortShape $expectedSort
*
* @dataProvider provideSortOptions
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use BadMethodCallException;
use Doctrine\Common\Collections\Collection;
use Doctrine\ODM\MongoDB\DocumentManager;
use Doctrine\ODM\MongoDB\Event\LifecycleEventArgs;
use Doctrine\ODM\MongoDB\Event\PostCollectionLoadEventArgs;
use Doctrine\ODM\MongoDB\Events;
use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
Expand Down Expand Up @@ -224,6 +225,9 @@ class MyEventListener
/** @psalm-var array<string, list<class-string>> */
public array $called = [];

/**
* @param array{LifecycleEventArgs} $args
*/
public function __call(string $method, array $args): void
{
$document = $args[0]->getDocument();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public function __construct(PreUpdateEventArgsTest $phpunit)
$this->phpunit = $phpunit;
}

/** @param list<class-string> $allowed */
public function checkOnly(array $allowed): void
{
$this->allowed = $allowed;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Doctrine\Common\EventSubscriber;
use Doctrine\ODM\MongoDB\APM\CommandLogger;
use Doctrine\ODM\MongoDB\Event\LifecycleEventArgs;
use Doctrine\ODM\MongoDB\Events;
use Doctrine\ODM\MongoDB\LockException;
use Doctrine\ODM\MongoDB\PersistentCollection\PersistentCollectionInterface;
Expand Down Expand Up @@ -160,6 +161,9 @@ public function getSubscribedEvents(): array
];
}

/**
* @param array{LifecycleEventArgs} $args
*/
public function __call(string $eventName, array $args): void
{
$document = $args[0]->getDocument();
Expand Down
Loading

0 comments on commit 0981d3d

Please sign in to comment.