Skip to content

Commit 4a8bbee

Browse files
committed
Fix IsEmptyTypeSpecifyingExtension for ReadableCollection
1 parent ed600bf commit 4a8bbee

File tree

4 files changed

+58
-4
lines changed

4 files changed

+58
-4
lines changed

extension.neon

+9
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,15 @@ services:
370370
# Doctrine Collection
371371
-
372372
class: PHPStan\Type\Doctrine\Collection\IsEmptyTypeSpecifyingExtension
373+
arguments:
374+
collectionClass: Doctrine\Common\Collections\Collection
375+
tags:
376+
- phpstan.typeSpecifier.methodTypeSpecifyingExtension
377+
378+
-
379+
class: PHPStan\Type\Doctrine\Collection\IsEmptyTypeSpecifyingExtension
380+
arguments:
381+
collectionClass: Doctrine\Common\Collections\ReadableCollection
373382
tags:
374383
- phpstan.typeSpecifier.methodTypeSpecifyingExtension
375384

src/Type/Doctrine/Collection/IsEmptyTypeSpecifyingExtension.php

+14-4
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,27 @@
1515
final class IsEmptyTypeSpecifyingExtension implements MethodTypeSpecifyingExtension, TypeSpecifierAwareExtension
1616
{
1717

18-
private const COLLECTION_CLASS = 'Doctrine\Common\Collections\Collection';
1918
private const IS_EMPTY_METHOD_NAME = 'isEmpty';
2019
private const FIRST_METHOD_NAME = 'first';
2120
private const LAST_METHOD_NAME = 'last';
2221

2322
/** @var TypeSpecifier */
2423
private $typeSpecifier;
2524

25+
/** @var class-string */
26+
private $collectionClass;
27+
28+
/**
29+
* @param class-string $collectionClass
30+
*/
31+
public function __construct(string $collectionClass)
32+
{
33+
$this->collectionClass = $collectionClass;
34+
}
35+
2636
public function getClass(): string
2737
{
28-
return self::COLLECTION_CLASS;
38+
return $this->collectionClass;
2939
}
3040

3141
public function isMethodSupported(
@@ -35,8 +45,8 @@ public function isMethodSupported(
3545
): bool
3646
{
3747
return (
38-
$methodReflection->getDeclaringClass()->getName() === self::COLLECTION_CLASS
39-
|| $methodReflection->getDeclaringClass()->isSubclassOf(self::COLLECTION_CLASS)
48+
$methodReflection->getDeclaringClass()->getName() === $this->collectionClass
49+
|| $methodReflection->getDeclaringClass()->isSubclassOf($this->collectionClass)
4050
)
4151
&& $methodReflection->getName() === self::IS_EMPTY_METHOD_NAME;
4252
}

tests/DoctrineIntegration/TypeInferenceTest.php

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class TypeInferenceTest extends TypeInferenceTestCase
1313
public function dataFileAsserts(): iterable
1414
{
1515
yield from $this->gatherAssertTypes(__DIR__ . '/data/getRepository.php');
16+
yield from $this->gatherAssertTypes(__DIR__ . '/data/isEmpty.php');
1617
}
1718

1819
/**
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
namespace Bug375;
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, Bar> */
13+
private Collection $shippingOptions;
14+
15+
public function __construct()
16+
{
17+
$this->shippingOptions = new ArrayCollection();
18+
}
19+
20+
public function doFoo(): void
21+
{
22+
if ($this->shippingOptions->isEmpty()) {
23+
return;
24+
}
25+
26+
assertType(Bar::class, $this->shippingOptions->first());
27+
}
28+
29+
}
30+
31+
class Bar
32+
{
33+
34+
}

0 commit comments

Comments
 (0)