Skip to content

Commit

Permalink
Merge pull request #379 from mglaman/377
Browse files Browse the repository at this point in the history
resolveFromStorage does not respect default phpDoc for generic storage interface
  • Loading branch information
mglaman authored Apr 6, 2022
2 parents 82d08d6 + ec36772 commit b934beb
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 19 deletions.
5 changes: 4 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@
"autoload-dev": {
"psr-4": {
"mglaman\\PHPStanDrupal\\Tests\\": "tests/src/"
}
},
"classmap": [
"tests/src/Type/data"
]
},
"extra": {
"branch-alias": {
Expand Down
12 changes: 12 additions & 0 deletions src/Drupal/EntityDataRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace mglaman\PHPStanDrupal\Drupal;

use Drupal\Core\Config\Entity\ConfigEntityStorageInterface;
use Drupal\Core\Entity\ContentEntityStorageInterface;
use Drupal\Core\Entity\EntityStorageInterface;
use PHPStan\Type\ObjectType;

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

public function resolveFromStorage(ObjectType $callerType): ?EntityData
{
if ($callerType->equals(new ObjectType(EntityStorageInterface::class))) {
return null;
}
if ($callerType->equals(new ObjectType(ConfigEntityStorageInterface::class))) {
return null;
}
if ($callerType->equals(new ObjectType(ContentEntityStorageInterface::class))) {
return null;
}
foreach ($this->entityData as $entityData) {
$storageType = $entityData->getStorageType();
if ($storageType !== null && $callerType->isSuperTypeOf($storageType)->yes()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ final class EntityTypeManagerGetStorageDynamicReturnTypeExtensionTest extends Ty
public function dataFileAsserts(): iterable
{
yield from $this->gatherAssertTypes(__DIR__ . '/data/entity-type-manager.php');
yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-377.php');
}

/**
Expand Down
50 changes: 50 additions & 0 deletions tests/src/Type/data/bug-377.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace bug377;

use Drupal\Core\Config\Entity\ConfigEntityStorageInterface;
use Drupal\Core\Entity\ContentEntityStorageInterface;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\node\NodeStorageInterface;
use function PHPStan\Testing\assertType;

class Foo {
private EntityTypeManagerInterface $entityTypeManager;
private EntityStorageInterface $myEntityStorage;
private ConfigEntityStorageInterface $configEntityStorage;
private ContentEntityStorageInterface $contentEntityStorage;
private NodeStorageInterface $nodeStorage;

public function __construct(EntityTypeManagerInterface $entityTypeManager)
{
$this->entityTypeManager = $entityTypeManager;
$this->myEntityStorage = $entityTypeManager->getStorage('node');
$this->configEntityStorage = $entityTypeManager->getStorage('block');
$this->contentEntityStorage = $entityTypeManager->getStorage('node');
$this->nodeStorage = $entityTypeManager->getStorage('node');
}

public function storageType() {
// @todo property typing overrides our internal typing to determine entity storage type.
assertType(EntityStorageInterface::class, $this->myEntityStorage);
assertType('Drupal\node\NodeStorage', $this->entityTypeManager->getStorage('node'));
assertType(ConfigEntityStorageInterface::class, $this->configEntityStorage);
assertType(ContentEntityStorageInterface::class, $this->contentEntityStorage);
assertType(NodeStorageInterface::class, $this->nodeStorage);
}

public function entityType() {
$entity = $this->myEntityStorage->load('123');
assertType('Drupal\Core\Entity\EntityInterface|null', $entity);
$entity = $this->configEntityStorage->load('123');
// @todo this can safely say it is ConfigEntityInterface as return type.
assertType('Drupal\Core\Entity\EntityInterface|null', $entity);
$entity = $this->contentEntityStorage->load('123');
// @todo this can safely say it is ConfigEntityInterface as return type.
assertType('Drupal\Core\Entity\EntityInterface|null', $entity);
$entity = $this->nodeStorage->load('123');
assertType('Drupal\node\Entity\Node|null', $entity);
}

}
18 changes: 10 additions & 8 deletions tests/src/Type/data/container.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@
use Drupal\service_map\Override;
use function PHPStan\Testing\assertType;

$container = \Drupal::getContainer();
function test(): void {
$container = \Drupal::getContainer();

assertType(MyService::class, $container->get('service_map.my_service'));
assertType('true', $container->has('service_map.my_service'));
assertType('false', $container->has('unknown_service'));
assertType(MyService::class, $container->get('service_map.concrete_service'));
assertType(MyService::class, $container->get('service_map.concrete_service_with_a_parent_which_has_a_parent'));
assertType(Override::class, $container->get('service_map.concrete_service_overriding_definition_of_its_parent'));
assertType(Concrete::class, $container->get('service_map.concrete_overriding_its_parent_which_has_a_parent'));
assertType(MyService::class, $container->get('service_map.my_service'));
assertType('true', $container->has('service_map.my_service'));
assertType('false', $container->has('unknown_service'));
assertType(MyService::class, $container->get('service_map.concrete_service'));
assertType(MyService::class, $container->get('service_map.concrete_service_with_a_parent_which_has_a_parent'));
assertType(Override::class, $container->get('service_map.concrete_service_overriding_definition_of_its_parent'));
assertType(Concrete::class, $container->get('service_map.concrete_overriding_its_parent_which_has_a_parent'));
}
18 changes: 10 additions & 8 deletions tests/src/Type/data/drupal-class-resolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@

class Foo {}

assertType(Foo::class, (new ClassResolver())->getInstanceFromDefinition(Foo::class));
assertType(Foo::class, \Drupal::service('class_resolver')->getInstanceFromDefinition(Foo::class));
assertType(Foo::class, \Drupal::classResolver()->getInstanceFromDefinition(Foo::class));
assertType(Foo::class, \Drupal::classResolver(Foo::class));
assertType(MyService::class, (new ClassResolver())->getInstanceFromDefinition('service_map.my_service'));
assertType(MyService::class, \Drupal::service('class_resolver')->getInstanceFromDefinition('service_map.my_service'));
assertType(MyService::class, \Drupal::classResolver()->getInstanceFromDefinition('service_map.my_service'));
assertType(MyService::class, \Drupal::classResolver('service_map.my_service'));
function test(): void {
assertType(Foo::class, (new ClassResolver())->getInstanceFromDefinition(Foo::class));
assertType(Foo::class, \Drupal::service('class_resolver')->getInstanceFromDefinition(Foo::class));
assertType(Foo::class, \Drupal::classResolver()->getInstanceFromDefinition(Foo::class));
assertType(Foo::class, \Drupal::classResolver(Foo::class));
assertType(MyService::class, (new ClassResolver())->getInstanceFromDefinition('service_map.my_service'));
assertType(MyService::class, \Drupal::service('class_resolver')->getInstanceFromDefinition('service_map.my_service'));
assertType(MyService::class, \Drupal::classResolver()->getInstanceFromDefinition('service_map.my_service'));
assertType(MyService::class, \Drupal::classResolver('service_map.my_service'));
}
4 changes: 3 additions & 1 deletion tests/src/Type/data/drupal-service-static.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@
use Drupal\service_map\MyService;
use function PHPStan\Testing\assertType;

assertType(MyService::class, \Drupal::service('service_map.my_service'));
function test(): void {
assertType(MyService::class, \Drupal::service('service_map.my_service'));
}
1 change: 0 additions & 1 deletion tests/src/Type/data/entity-type-manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
namespace EntityTypeManagerGetStorage;

use function PHPStan\Testing\assertType;
use function PHPUnit\Framework\assertInstanceOf;

$etm = \Drupal::entityTypeManager();

Expand Down

0 comments on commit b934beb

Please sign in to comment.