Skip to content

Commit b934beb

Browse files
authored
Merge pull request #379 from mglaman/377
resolveFromStorage does not respect default phpDoc for generic storage interface
2 parents 82d08d6 + ec36772 commit b934beb

8 files changed

+90
-19
lines changed

composer.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@
4646
"autoload-dev": {
4747
"psr-4": {
4848
"mglaman\\PHPStanDrupal\\Tests\\": "tests/src/"
49-
}
49+
},
50+
"classmap": [
51+
"tests/src/Type/data"
52+
]
5053
},
5154
"extra": {
5255
"branch-alias": {

src/Drupal/EntityDataRepository.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
namespace mglaman\PHPStanDrupal\Drupal;
44

5+
use Drupal\Core\Config\Entity\ConfigEntityStorageInterface;
6+
use Drupal\Core\Entity\ContentEntityStorageInterface;
7+
use Drupal\Core\Entity\EntityStorageInterface;
58
use PHPStan\Type\ObjectType;
69

710
final class EntityDataRepository
@@ -34,6 +37,15 @@ public function get(string $entityTypeId): EntityData
3437

3538
public function resolveFromStorage(ObjectType $callerType): ?EntityData
3639
{
40+
if ($callerType->equals(new ObjectType(EntityStorageInterface::class))) {
41+
return null;
42+
}
43+
if ($callerType->equals(new ObjectType(ConfigEntityStorageInterface::class))) {
44+
return null;
45+
}
46+
if ($callerType->equals(new ObjectType(ContentEntityStorageInterface::class))) {
47+
return null;
48+
}
3749
foreach ($this->entityData as $entityData) {
3850
$storageType = $entityData->getStorageType();
3951
if ($storageType !== null && $callerType->isSuperTypeOf($storageType)->yes()) {

tests/src/Type/EntityTypeManagerGetStorageDynamicReturnTypeExtensionTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ final class EntityTypeManagerGetStorageDynamicReturnTypeExtensionTest extends Ty
2121
public function dataFileAsserts(): iterable
2222
{
2323
yield from $this->gatherAssertTypes(__DIR__ . '/data/entity-type-manager.php');
24+
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-377.php');
2425
}
2526

2627
/**

tests/src/Type/data/bug-377.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
namespace bug377;
4+
5+
use Drupal\Core\Config\Entity\ConfigEntityStorageInterface;
6+
use Drupal\Core\Entity\ContentEntityStorageInterface;
7+
use Drupal\Core\Entity\EntityStorageInterface;
8+
use Drupal\Core\Entity\EntityTypeManagerInterface;
9+
use Drupal\node\NodeStorageInterface;
10+
use function PHPStan\Testing\assertType;
11+
12+
class Foo {
13+
private EntityTypeManagerInterface $entityTypeManager;
14+
private EntityStorageInterface $myEntityStorage;
15+
private ConfigEntityStorageInterface $configEntityStorage;
16+
private ContentEntityStorageInterface $contentEntityStorage;
17+
private NodeStorageInterface $nodeStorage;
18+
19+
public function __construct(EntityTypeManagerInterface $entityTypeManager)
20+
{
21+
$this->entityTypeManager = $entityTypeManager;
22+
$this->myEntityStorage = $entityTypeManager->getStorage('node');
23+
$this->configEntityStorage = $entityTypeManager->getStorage('block');
24+
$this->contentEntityStorage = $entityTypeManager->getStorage('node');
25+
$this->nodeStorage = $entityTypeManager->getStorage('node');
26+
}
27+
28+
public function storageType() {
29+
// @todo property typing overrides our internal typing to determine entity storage type.
30+
assertType(EntityStorageInterface::class, $this->myEntityStorage);
31+
assertType('Drupal\node\NodeStorage', $this->entityTypeManager->getStorage('node'));
32+
assertType(ConfigEntityStorageInterface::class, $this->configEntityStorage);
33+
assertType(ContentEntityStorageInterface::class, $this->contentEntityStorage);
34+
assertType(NodeStorageInterface::class, $this->nodeStorage);
35+
}
36+
37+
public function entityType() {
38+
$entity = $this->myEntityStorage->load('123');
39+
assertType('Drupal\Core\Entity\EntityInterface|null', $entity);
40+
$entity = $this->configEntityStorage->load('123');
41+
// @todo this can safely say it is ConfigEntityInterface as return type.
42+
assertType('Drupal\Core\Entity\EntityInterface|null', $entity);
43+
$entity = $this->contentEntityStorage->load('123');
44+
// @todo this can safely say it is ConfigEntityInterface as return type.
45+
assertType('Drupal\Core\Entity\EntityInterface|null', $entity);
46+
$entity = $this->nodeStorage->load('123');
47+
assertType('Drupal\node\Entity\Node|null', $entity);
48+
}
49+
50+
}

tests/src/Type/data/container.php

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@
88
use Drupal\service_map\Override;
99
use function PHPStan\Testing\assertType;
1010

11-
$container = \Drupal::getContainer();
11+
function test(): void {
12+
$container = \Drupal::getContainer();
1213

13-
assertType(MyService::class, $container->get('service_map.my_service'));
14-
assertType('true', $container->has('service_map.my_service'));
15-
assertType('false', $container->has('unknown_service'));
16-
assertType(MyService::class, $container->get('service_map.concrete_service'));
17-
assertType(MyService::class, $container->get('service_map.concrete_service_with_a_parent_which_has_a_parent'));
18-
assertType(Override::class, $container->get('service_map.concrete_service_overriding_definition_of_its_parent'));
19-
assertType(Concrete::class, $container->get('service_map.concrete_overriding_its_parent_which_has_a_parent'));
14+
assertType(MyService::class, $container->get('service_map.my_service'));
15+
assertType('true', $container->has('service_map.my_service'));
16+
assertType('false', $container->has('unknown_service'));
17+
assertType(MyService::class, $container->get('service_map.concrete_service'));
18+
assertType(MyService::class, $container->get('service_map.concrete_service_with_a_parent_which_has_a_parent'));
19+
assertType(Override::class, $container->get('service_map.concrete_service_overriding_definition_of_its_parent'));
20+
assertType(Concrete::class, $container->get('service_map.concrete_overriding_its_parent_which_has_a_parent'));
21+
}

tests/src/Type/data/drupal-class-resolver.php

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88

99
class Foo {}
1010

11-
assertType(Foo::class, (new ClassResolver())->getInstanceFromDefinition(Foo::class));
12-
assertType(Foo::class, \Drupal::service('class_resolver')->getInstanceFromDefinition(Foo::class));
13-
assertType(Foo::class, \Drupal::classResolver()->getInstanceFromDefinition(Foo::class));
14-
assertType(Foo::class, \Drupal::classResolver(Foo::class));
15-
assertType(MyService::class, (new ClassResolver())->getInstanceFromDefinition('service_map.my_service'));
16-
assertType(MyService::class, \Drupal::service('class_resolver')->getInstanceFromDefinition('service_map.my_service'));
17-
assertType(MyService::class, \Drupal::classResolver()->getInstanceFromDefinition('service_map.my_service'));
18-
assertType(MyService::class, \Drupal::classResolver('service_map.my_service'));
11+
function test(): void {
12+
assertType(Foo::class, (new ClassResolver())->getInstanceFromDefinition(Foo::class));
13+
assertType(Foo::class, \Drupal::service('class_resolver')->getInstanceFromDefinition(Foo::class));
14+
assertType(Foo::class, \Drupal::classResolver()->getInstanceFromDefinition(Foo::class));
15+
assertType(Foo::class, \Drupal::classResolver(Foo::class));
16+
assertType(MyService::class, (new ClassResolver())->getInstanceFromDefinition('service_map.my_service'));
17+
assertType(MyService::class, \Drupal::service('class_resolver')->getInstanceFromDefinition('service_map.my_service'));
18+
assertType(MyService::class, \Drupal::classResolver()->getInstanceFromDefinition('service_map.my_service'));
19+
assertType(MyService::class, \Drupal::classResolver('service_map.my_service'));
20+
}

tests/src/Type/data/drupal-service-static.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@
55
use Drupal\service_map\MyService;
66
use function PHPStan\Testing\assertType;
77

8-
assertType(MyService::class, \Drupal::service('service_map.my_service'));
8+
function test(): void {
9+
assertType(MyService::class, \Drupal::service('service_map.my_service'));
10+
}

tests/src/Type/data/entity-type-manager.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace EntityTypeManagerGetStorage;
44

55
use function PHPStan\Testing\assertType;
6-
use function PHPUnit\Framework\assertInstanceOf;
76

87
$etm = \Drupal::entityTypeManager();
98

0 commit comments

Comments
 (0)