diff --git a/src/Rules/Doctrine/ORM/EntityColumnRule.php b/src/Rules/Doctrine/ORM/EntityColumnRule.php index 75aa1ae6..5b54cd81 100644 --- a/src/Rules/Doctrine/ORM/EntityColumnRule.php +++ b/src/Rules/Doctrine/ORM/EntityColumnRule.php @@ -12,8 +12,10 @@ use PHPStan\Type\Constant\ConstantStringType; use PHPStan\Type\Doctrine\DescriptorNotRegisteredException; use PHPStan\Type\Doctrine\DescriptorRegistry; +use PHPStan\Type\Doctrine\Descriptors\SmallIntType; use PHPStan\Type\Doctrine\ObjectMetadataResolver; use PHPStan\Type\ErrorType; +use PHPStan\Type\IntegerRangeType; use PHPStan\Type\MixedType; use PHPStan\Type\NeverType; use PHPStan\Type\ObjectType; @@ -177,6 +179,10 @@ public function processNode(Node $node, Scope $scope): array $writableToDatabaseType = $unionType; } } + } elseif ($descriptor instanceof SmallIntType) { + $writableToPropertyType = ($fieldMapping['options']['unsigned'] ?? false) === true + ? IntegerRangeType::fromInterval(0, 65535) + : IntegerRangeType::fromInterval(-32768, 32767); } $identifiers = []; diff --git a/tests/Rules/Doctrine/ORM/EntityColumnRuleTest.php b/tests/Rules/Doctrine/ORM/EntityColumnRuleTest.php index ded1a78d..1f33350f 100644 --- a/tests/Rules/Doctrine/ORM/EntityColumnRuleTest.php +++ b/tests/Rules/Doctrine/ORM/EntityColumnRuleTest.php @@ -25,6 +25,7 @@ use PHPStan\Type\Doctrine\Descriptors\Ramsey\UuidTypeDescriptor as RamseyUuidTypeDescriptor; use PHPStan\Type\Doctrine\Descriptors\ReflectionDescriptor; use PHPStan\Type\Doctrine\Descriptors\SimpleArrayType; +use PHPStan\Type\Doctrine\Descriptors\SmallIntType; use PHPStan\Type\Doctrine\Descriptors\StringType; use PHPStan\Type\Doctrine\Descriptors\Symfony\UlidTypeDescriptor as SymfonyUlidTypeDescriptor; use PHPStan\Type\Doctrine\Descriptors\Symfony\UuidTypeDescriptor as SymfonyUuidTypeDescriptor; @@ -101,6 +102,7 @@ protected function getRule(): Rule new JsonType(), new IntegerType(), new NumberType(), + new SmallIntType(), new StringType(), new SimpleArrayType(), new EnumType(), @@ -480,6 +482,25 @@ public function testBug306(?string $objectManagerLoader): void ]); } + /** + * @dataProvider dataObjectManagerLoader + */ + public function testBug672(?string $objectManagerLoader): void + { + $this->allowNullablePropertyForRequiredField = false; + $this->objectManagerLoader = $objectManagerLoader; + $this->analyse([__DIR__ . '/data/bug-672.php'], [ + [ + 'Property PHPStan\Rules\Doctrine\ORM\Bug672\SmallIntEntity::$signedAsUnsigned type mapping mismatch: database can contain int<-32768, 32767> but property expects int<0, 65535>.', + 54, + ], + [ + 'Property PHPStan\Rules\Doctrine\ORM\Bug672\SmallIntEntity::$unsignedAsSigned type mapping mismatch: database can contain int<0, 65535> but property expects int<-32768, 32767>.', + 60, + ], + ]); + } + /** * @dataProvider dataObjectManagerLoader */ diff --git a/tests/Rules/Doctrine/ORM/data/bug-672.php b/tests/Rules/Doctrine/ORM/data/bug-672.php new file mode 100644 index 00000000..2f23ecfc --- /dev/null +++ b/tests/Rules/Doctrine/ORM/data/bug-672.php @@ -0,0 +1,62 @@ + + */ + private $signed; + + /** + * @ORM\Column(type="smallint", options={"unsigned": false}) + * @var int<-32768, 32767> + */ + private $explicitlySigned; + + /** + * @ORM\Column(type="smallint", options={"unsigned": true}) + * @var int<0, 65535> + */ + private $unsigned; + + /** + * @ORM\Column(type="smallint") + * @var int + */ + private $int; + + /** + * @ORM\Column(type="smallint", nullable=true) + * @var int<-32768, 32767>|null + */ + private $nullable; + + /** + * @ORM\Column(type="smallint") + * @var int<0, 65535> + */ + private $signedAsUnsigned; + + /** + * @ORM\Column(type="smallint", options={"unsigned": true}) + * @var int<-32768, 32767> + */ + private $unsignedAsSigned; + +}