Skip to content

Commit ed1214f

Browse files
authored
Merge branch 'main' into fix-entity-query-type-cache
2 parents 22d9ab0 + 2d2f7b4 commit ed1214f

File tree

9 files changed

+30
-25
lines changed

9 files changed

+30
-25
lines changed

.github/workflows/phpstan-dev.yml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@ jobs:
1313
strategy:
1414
matrix:
1515
phpstan:
16-
- '1.8.x-dev'
17-
- '1.7.x-dev'
18-
- '1.6.x-dev'
16+
- '1.9.x-dev'
1917
steps:
2018
- name: "Checkout"
2119
uses: "actions/checkout@v2"

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"require": {
1313
"php": "^7.4 || ^8.0",
1414
"symfony/finder": "~3.4.5 ||^4.2 || ^5.0 || ^6.0",
15-
"phpstan/phpstan": "^1.6.0",
15+
"phpstan/phpstan": "^1.9.0",
1616
"symfony/yaml": "~3.4.5 || ^4.2|| ^5.0 || ^6.0",
1717
"webflo/drupal-finder": "^1.2"
1818
},

src/Drupal/ExtensionDiscovery.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -376,7 +376,7 @@ protected function scanDirectory($dir): array
376376
// Determine extension type from info file.
377377
$type = false;
378378
$file = $fileinfo->openFile('r');
379-
while (!$type && !$file->eof()) {
379+
while ($type === false && !$file->eof()) {
380380
if ($line = $file->fgets()) {
381381
preg_match('@^type:\s*(\'|")?(\w+)\1?\s*$@', $line, $matches);
382382
if (isset($matches[2])) {

src/Rules/Drupal/GlobalDrupalDependencyInjectionRule.php

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ public function processNode(Node $node, Scope $scope): array
2828
return [];
2929
}
3030
$scopeClassReflection = $scope->getClassReflection();
31-
if ($scopeClassReflection === null) {
32-
throw new ShouldNotHappenException();
33-
}
3431

3532
$allowed_list = [
3633
// Ignore tests.

src/Rules/Drupal/PluginManager/PluginManagerSetsCacheBackendRule.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,6 @@ public function processNode(Node $node, Scope $scope): array
3838

3939
$scopeClassReflection = $scope->getClassReflection();
4040

41-
if ($scopeClassReflection === null) {
42-
throw new ShouldNotHappenException();
43-
}
44-
4541
if (!$this->isPluginManager($scopeClassReflection)) {
4642
return [];
4743
}

src/Rules/Drupal/RenderCallbackRule.php

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,6 @@ public function processNode(Node $node, Scope $scope): array
6868
if ($keyChecked === '#lazy_builder') {
6969
if ($scope->isInClass()) {
7070
$classReflection = $scope->getClassReflection();
71-
// @todo why doesn't isInClass assert this isn't null?
72-
assert($classReflection !== null);
7371
$classType = new ObjectType($classReflection->getName());
7472
// These classes use #lazy_builder in array_intersect_key. With
7573
// PHPStan 1.6, nodes do not track their parent/next/prev which
@@ -162,22 +160,21 @@ private function doProcessNode(Node\Expr $node, Scope $scope, string $keyChecked
162160
sprintf("%s callback %s at key '%s' is not callable.", $keyChecked, $type->describe(VerbosityLevel::value()), $pos)
163161
)->line($errorLine)->build();
164162
}
165-
$typeAndMethodName = $type->findTypeAndMethodName();
166-
if ($typeAndMethodName === null) {
163+
$typeAndMethodNames = $type->findTypeAndMethodNames();
164+
if ($typeAndMethodNames === []) {
167165
throw new \PHPStan\ShouldNotHappenException();
168166
}
169167

170-
if (!$trustedCallbackType->isSuperTypeOf($typeAndMethodName->getType())->yes()) {
171-
return RuleErrorBuilder::message(
172-
sprintf("%s callback class '%s' at key '%s' does not implement Drupal\Core\Security\TrustedCallbackInterface.", $keyChecked, $typeAndMethodName->getType()->describe(VerbosityLevel::value()), $pos)
173-
)->line($errorLine)->tip('Change record: https://www.drupal.org/node/2966725.')->build();
168+
foreach ($typeAndMethodNames as $typeAndMethodName) {
169+
if (!$trustedCallbackType->isSuperTypeOf($typeAndMethodName->getType())->yes()) {
170+
return RuleErrorBuilder::message(
171+
sprintf("%s callback class '%s' at key '%s' does not implement Drupal\Core\Security\TrustedCallbackInterface.", $keyChecked, $typeAndMethodName->getType()->describe(VerbosityLevel::value()), $pos)
172+
)->line($errorLine)->tip('Change record: https://www.drupal.org/node/2966725.')->build();
173+
}
174174
}
175175
} elseif ($type instanceof ClosureType) {
176176
if ($scope->isInClass()) {
177177
$classReflection = $scope->getClassReflection();
178-
if ($classReflection === null) {
179-
throw new \PHPStan\ShouldNotHappenException();
180-
}
181178
$classType = new ObjectType($classReflection->getName());
182179
$formType = new ObjectType('\Drupal\Core\Form\FormInterface');
183180
if ($formType->isSuperTypeOf($classType)->yes()) {
@@ -224,7 +221,7 @@ private function getType(Node\Expr $node, Scope $scope): Type
224221
}
225222
}
226223
} elseif ($type instanceof ConstantStringType) {
227-
if ($type->isClassString()) {
224+
if ($type->isClassStringType()->yes()) {
228225
return $type;
229226
}
230227
// Covers \Drupal\Core\Controller\ControllerResolver::createController.
@@ -245,7 +242,7 @@ private function getType(Node\Expr $node, Scope $scope): Type
245242
}
246243
// @see \PHPStan\Type\Constant\ConstantStringType::isCallable
247244
preg_match('#^([a-zA-Z_\\x7f-\\xff\\\\][a-zA-Z0-9_\\x7f-\\xff\\\\]*)::([a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*)\\z#', $type->getValue(), $matches);
248-
if ($matches !== null && count($matches) > 0) {
245+
if (count($matches) > 0) {
249246
return new ConstantArrayType(
250247
[new ConstantIntegerType(0), new ConstantIntegerType(1)],
251248
[

stubs/Drupal/Core/Field/EntityReferenceFieldItemListInterface.stub

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,9 @@ use Drupal\Core\Field\Plugin\Field\FieldType\EntityReferenceItem;
1313
*/
1414
interface EntityReferenceFieldItemListInterface extends FieldItemListInterface {
1515

16+
/**
17+
* @return array<int, T>
18+
*/
19+
public function referencedEntities();
20+
1621
}

tests/fixtures/drupal/modules/phpstan_fixtures/src/Entity/ReflectionEntityTest.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
/**
1111
* @property \Drupal\Core\Field\EntityReferenceFieldItemListInterface $user_id
12+
* @property \Drupal\Core\Field\EntityReferenceFieldItemListInterface<\Drupal\entity_test\Entity\EntityTest> $related
1213
*/
1314
final class ReflectionEntityTest extends ContentEntityBase {
1415

@@ -34,6 +35,14 @@ public static function baseFieldDefinitions(EntityTypeInterface $entity_type)
3435
'placeholder' => '',
3536
],
3637
]);
38+
39+
$fields['related'] = BaseFieldDefinition::create('entity_reference')
40+
->setLabel(t('Related entities'))
41+
->setDescription(t('The IDs of the related entities.'))
42+
->setSetting('target_type', 'entity_test')
43+
->setSetting('handler', 'default')
44+
->setTranslatable(TRUE)
45+
->setDisplayConfigurable('form', FALSE);
3746
return $fields;
3847
}
3948

tests/src/Type/data/entity-properties.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,6 @@
1111

1212
$entity = ReflectionEntityTest::create();
1313
assertType('Drupal\Core\Field\EntityReferenceFieldItemListInterface', $entity->user_id);
14+
assertType('Drupal\Core\Field\EntityReferenceFieldItemListInterface<Drupal\entity_test\Entity\EntityTest>', $entity->related);
15+
// Value of array is derived from 'related' generic.
16+
assertType('array<int, Drupal\entity_test\Entity\EntityTest>', $entity->related->referencedEntities());

0 commit comments

Comments
 (0)