Skip to content

Commit 813296e

Browse files
committed
Merge remote-tracking branch 'origin/1.5.x' into 2.0.x
2 parents f36d43f + 4e9c77f commit 813296e

File tree

8 files changed

+236
-1
lines changed

8 files changed

+236
-1
lines changed

Diff for: extension.neon

-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ parameters:
3232
- stubs/Persistence/ObjectRepository.stub
3333
- stubs/RepositoryFactory.stub
3434
- stubs/Collections/ArrayCollection.stub
35-
- stubs/Collections/ReadableCollection.stub
3635
- stubs/Collections/Selectable.stub
3736
- stubs/ORM/AbstractQuery.stub
3837
- stubs/ORM/Exception/ORMException.stub

Diff for: src/Stubs/Doctrine/StubFilesExtensionLoader.php

+2
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,10 @@ public function getFiles(): array
6363
$collectionVersion = null;
6464
}
6565
if ($collectionVersion !== null && strpos($collectionVersion, '1.') === 0) {
66+
$files[] = $stubsDir . '/Collections/ReadableCollection1.stub';
6667
$files[] = $stubsDir . '/Collections/Collection1.stub';
6768
} else {
69+
$files[] = $stubsDir . '/Collections/ReadableCollection.stub';
6870
$files[] = $stubsDir . '/Collections/Collection.stub';
6971
}
7072

Diff for: stubs/Collections/ArrayCollection.stub

+31
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
namespace Doctrine\Common\Collections;
44

5+
use Closure;
6+
57
/**
68
* @template TKey of array-key
79
* @template T
@@ -11,4 +13,33 @@ namespace Doctrine\Common\Collections;
1113
class ArrayCollection implements Collection, Selectable
1214
{
1315

16+
/**
17+
* @param-immediately-invoked-callable $p
18+
*
19+
* @param Closure(T, TKey):bool $p
20+
*
21+
* @return static<TKey, T>
22+
*/
23+
public function filter(Closure $p);
24+
25+
/**
26+
* @param-immediately-invoked-callable $func
27+
*
28+
* @param Closure(T):U $func
29+
*
30+
* @return static<TKey, U>
31+
*
32+
* @template U
33+
*/
34+
public function map(Closure $func);
35+
36+
/**
37+
* @param-immediately-invoked-callable $p
38+
*
39+
* @param Closure(TKey, T):bool $p
40+
*
41+
* @return array{0: static<TKey, T>, 1: static<TKey, T>}
42+
*/
43+
public function partition(Closure $p);
44+
1445
}

Diff for: stubs/Collections/Collection.stub

+30
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Doctrine\Common\Collections;
44

55
use ArrayAccess;
6+
use Closure;
67
use Countable;
78
use IteratorAggregate;
89

@@ -43,4 +44,33 @@ interface Collection extends Countable, IteratorAggregate, ArrayAccess, Readable
4344
*/
4445
public function removeElement($element) {}
4546

47+
/**
48+
* @param-immediately-invoked-callable $p
49+
*
50+
* @param Closure(T, TKey):bool $p
51+
*
52+
* @return Collection<TKey, T>
53+
*/
54+
public function filter(Closure $p);
55+
56+
/**
57+
* @param-immediately-invoked-callable $func
58+
*
59+
* @param Closure(T):U $func
60+
*
61+
* @return Collection<TKey, U>
62+
*
63+
* @template U
64+
*/
65+
public function map(Closure $func);
66+
67+
/**
68+
* @param-immediately-invoked-callable $p
69+
*
70+
* @param Closure(TKey, T):bool $p
71+
*
72+
* @return array{0: Collection<TKey, T>, 1: Collection<TKey, T>}
73+
*/
74+
public function partition(Closure $p);
75+
4676
}

Diff for: stubs/Collections/Collection1.stub

+30
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Doctrine\Common\Collections;
44

55
use ArrayAccess;
6+
use Closure;
67
use Countable;
78
use IteratorAggregate;
89

@@ -43,4 +44,33 @@ interface Collection extends Countable, IteratorAggregate, ArrayAccess, Readable
4344
*/
4445
public function removeElement($element) {}
4546

47+
/**
48+
* @param-immediately-invoked-callable $p
49+
*
50+
* @param Closure(T, TKey):bool $p
51+
*
52+
* @return Collection<TKey, T>
53+
*/
54+
public function filter(Closure $p);
55+
56+
/**
57+
* @param-immediately-invoked-callable $func
58+
*
59+
* @param Closure(T):U $func
60+
*
61+
* @return Collection<TKey, U>
62+
*
63+
* @template U
64+
*/
65+
public function map(Closure $func);
66+
67+
/**
68+
* @param-immediately-invoked-callable $p
69+
*
70+
* @param Closure(TKey, T):bool $p
71+
*
72+
* @return array{0: Collection<TKey, T>, 1: Collection<TKey, T>}
73+
*/
74+
public function partition(Closure $p);
75+
4676
}

Diff for: stubs/Collections/ReadableCollection1.stub

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
3+
namespace Doctrine\Common\Collections;
4+
5+
use Closure;
6+
use Countable;
7+
use IteratorAggregate;
8+
9+
/**
10+
* @template TKey of array-key
11+
* @template-covariant T
12+
* @extends IteratorAggregate<TKey, T>
13+
*/
14+
interface ReadableCollection extends Countable, IteratorAggregate
15+
{
16+
17+
/**
18+
* @param-immediately-invoked-callable $p
19+
*
20+
* @param Closure(TKey, T):bool $p
21+
*
22+
* @return bool
23+
*/
24+
public function exists(Closure $p);
25+
26+
/**
27+
* @param-immediately-invoked-callable $p
28+
*
29+
* @param Closure(T, TKey):bool $p
30+
*
31+
* @return ReadableCollection<TKey, T>
32+
*/
33+
public function filter(Closure $p);
34+
35+
/**
36+
* @param-immediately-invoked-callable $func
37+
*
38+
* @param Closure(T):U $func
39+
*
40+
* @return Collection<TKey, U>
41+
*
42+
* @template U
43+
*/
44+
public function map(Closure $func);
45+
46+
/**
47+
* @param-immediately-invoked-callable $p
48+
*
49+
* @param Closure(TKey, T):bool $p
50+
*
51+
* @return array{0: ReadableCollection<TKey, T>, 1: ReadableCollection<TKey, T>}
52+
*/
53+
public function partition(Closure $p);
54+
55+
/**
56+
* @param-immediately-invoked-callable $p
57+
*
58+
* @param Closure(TKey, T):bool $p
59+
*
60+
* @return bool TRUE, if the predicate yields TRUE for all elements, FALSE otherwise.
61+
*/
62+
public function forAll(Closure $p);
63+
64+
/**
65+
* @param-immediately-invoked-callable $p
66+
*
67+
* @param Closure(TKey, T):bool $p
68+
*
69+
* @return T|null
70+
*/
71+
public function findFirst(Closure $p);
72+
73+
/**
74+
* @param-immediately-invoked-callable $func
75+
*
76+
* @param Closure(TReturn|TInitial, T):TReturn $func
77+
* @param TInitial $initial
78+
*
79+
* @return TReturn|TInitial
80+
*
81+
* @template TReturn
82+
* @template TInitial
83+
*/
84+
public function reduce(Closure $func, mixed $initial = null);
85+
86+
}

Diff for: tests/DoctrineIntegration/TypeInferenceTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ public function dataFileAsserts(): iterable
1414
{
1515
yield from $this->gatherAssertTypes(__DIR__ . '/data/getRepository.php');
1616
yield from $this->gatherAssertTypes(__DIR__ . '/data/isEmpty.php');
17+
yield from $this->gatherAssertTypes(__DIR__ . '/data/Collection.php');
1718
}
1819

1920
/**

Diff for: tests/DoctrineIntegration/data/Collection.php

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<?php
2+
3+
namespace Bug621;
4+
5+
use Doctrine\Common\Collections\ArrayCollection;
6+
use Doctrine\Common\Collections\Collection;
7+
use function PHPStan\Testing\assertType;
8+
9+
class Foo
10+
{
11+
12+
/** @var Collection<int, Item> */
13+
private $items;
14+
15+
public function __construct()
16+
{
17+
/** @var ArrayCollection<int, int> $numbers */
18+
$numbers = new ArrayCollection([1, 2, 3]);
19+
20+
$filteredNumbers = $numbers->filter(function (int $number): bool {
21+
return $number % 2 === 1;
22+
});
23+
assertType('Doctrine\Common\Collections\ArrayCollection<int, int>', $filteredNumbers);
24+
25+
$items = $filteredNumbers->map(static function (int $number): Item {
26+
return new Item();
27+
});
28+
assertType('Doctrine\Common\Collections\ArrayCollection<int, Bug621\Item>', $items);
29+
30+
$this->items = $items;
31+
}
32+
33+
public function removeOdd(): void
34+
{
35+
$this->items = $this->items->filter(function (Item $item, int $idx): bool {
36+
return $idx % 2 === 1;
37+
});
38+
assertType('Doctrine\Common\Collections\Collection<int, Bug621\Item>', $this->items);
39+
}
40+
41+
public function __clone()
42+
{
43+
$this->items = $this->items->map(
44+
static function (Item $item): Item {
45+
return clone $item;
46+
}
47+
);
48+
assertType('Doctrine\Common\Collections\Collection<int, Bug621\Item>', $this->items);
49+
}
50+
51+
}
52+
53+
class Item
54+
{
55+
56+
}

0 commit comments

Comments
 (0)