Skip to content

Commit

Permalink
Fix support for type descriptors returning precise arrays
Browse files Browse the repository at this point in the history
The EntityColumnRule was transforming the property type to avoid
reporting errors for array types, to allow precising the types inside
those arrays on the PHP side. However, this was breaking checks when the
type descriptor was actually more precise.
  • Loading branch information
stof committed Apr 5, 2023
1 parent f637e4d commit 7dd1365
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 8 deletions.
13 changes: 7 additions & 6 deletions src/Rules/Doctrine/ORM/EntityColumnRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -160,13 +160,14 @@ public function processNode(Node $node, Scope $scope): array
return [];
}

$propertyTransformedType = TypeTraverser::map($propertyType, static function (Type $type, callable $traverse): Type {
// If the type descriptor does not precise the types inside the array, don't report errors if the field has a more precise type
$propertyTransformedType = $writableToPropertyType->equals(new ArrayType(new MixedType(), new MixedType())) ? TypeTraverser::map($propertyType, static function (Type $type, callable $traverse): Type {
if ($type instanceof ArrayType) {
return new ArrayType(new MixedType(), new MixedType());
}

return $traverse($type);
});
}) : $propertyType;

if (!$propertyTransformedType->isSuperTypeOf($writableToPropertyType)->yes()) {
$errors[] = sprintf(
Expand All @@ -181,16 +182,16 @@ public function processNode(Node $node, Scope $scope): array
if (
!$writableToDatabaseType->isSuperTypeOf(
$this->allowNullablePropertyForRequiredField || (in_array($propertyName, $identifiers, true) && !$nullable)
? TypeCombinator::removeNull($propertyTransformedType)
: $propertyTransformedType
? TypeCombinator::removeNull($propertyType)
: $propertyType
)->yes()
) {
$errors[] = sprintf(
'Property %s::$%s type mapping mismatch: property can contain %s but database expects %s.',
$className,
$propertyName,
$propertyTransformedType->describe(VerbosityLevel::getRecommendedLevelByType($writableToDatabaseType, $propertyTransformedType)),
$writableToDatabaseType->describe(VerbosityLevel::getRecommendedLevelByType($writableToDatabaseType, $propertyTransformedType))
$propertyTransformedType->describe(VerbosityLevel::getRecommendedLevelByType($writableToDatabaseType, $propertyType)),
$writableToDatabaseType->describe(VerbosityLevel::getRecommendedLevelByType($writableToDatabaseType, $propertyType))
);
}
return $errors;
Expand Down
12 changes: 10 additions & 2 deletions tests/Rules/Doctrine/ORM/EntityColumnRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,11 @@ public function testRule(?string $objectManagerLoader): void
156,
],
[
'Property PHPStan\Rules\Doctrine\ORM\MyBrokenEntity::$invalidSimpleArray type mapping mismatch: property can contain array but database expects array<string>.',
'Property PHPStan\Rules\Doctrine\ORM\MyBrokenEntity::$invalidSimpleArray type mapping mismatch: database can contain array<int, string> but property expects array<int>.',
162,
],
[
'Property PHPStan\Rules\Doctrine\ORM\MyBrokenEntity::$invalidSimpleArray type mapping mismatch: property can contain array<int> but database expects array<string>.',
162,
],
]);
Expand Down Expand Up @@ -218,7 +222,11 @@ public function testRuleWithAllowedNullableProperty(?string $objectManagerLoader
156,
],
[
'Property PHPStan\Rules\Doctrine\ORM\MyBrokenEntity::$invalidSimpleArray type mapping mismatch: property can contain array but database expects array<string>.',
'Property PHPStan\Rules\Doctrine\ORM\MyBrokenEntity::$invalidSimpleArray type mapping mismatch: database can contain array<int, string> but property expects array<int>.',
162,
],
[
'Property PHPStan\Rules\Doctrine\ORM\MyBrokenEntity::$invalidSimpleArray type mapping mismatch: property can contain array<int> but database expects array<string>.',
162,
],
]);
Expand Down

0 comments on commit 7dd1365

Please sign in to comment.