From eb861cccd7dbf8e014c7db4df559c4069f2ee412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20N=C3=A1pravn=C3=ADk?= Date: Wed, 12 Jul 2023 16:14:46 +0200 Subject: [PATCH 1/3] NullabilityColumnPropertyTypeResolver - default column nullable false --- src/NodeManipulator/NullabilityColumnPropertyTypeResolver.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NodeManipulator/NullabilityColumnPropertyTypeResolver.php b/src/NodeManipulator/NullabilityColumnPropertyTypeResolver.php index 8ce1e0df..82995da7 100644 --- a/src/NodeManipulator/NullabilityColumnPropertyTypeResolver.php +++ b/src/NodeManipulator/NullabilityColumnPropertyTypeResolver.php @@ -51,12 +51,12 @@ private function isNullableColumn(PhpDocInfo $phpDocInfo): bool { $doctrineAnnotationTagValueNode = $phpDocInfo->findOneByAnnotationClass(self::COLUMN_CLASS); if (! $doctrineAnnotationTagValueNode instanceof DoctrineAnnotationTagValueNode) { - return true; + return false; } $nullableValueArrayItemNode = $doctrineAnnotationTagValueNode->getValue('nullable'); if (! $nullableValueArrayItemNode instanceof ArrayItemNode) { - return true; + return false; } return $nullableValueArrayItemNode->value instanceof ConstExprTrueNode; From c3a0010a218f4e0a8172b9f7b86a3a9ec9d46547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20N=C3=A1pravn=C3=ADk?= Date: Wed, 12 Jul 2023 16:31:52 +0200 Subject: [PATCH 2/3] update tests --- .../Fixture/simple_column.php.inc | 2 +- .../Fixture/simple_column_attribute.php.inc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rules-tests/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector/Fixture/simple_column.php.inc b/rules-tests/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector/Fixture/simple_column.php.inc index 7a178643..185a5a14 100644 --- a/rules-tests/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector/Fixture/simple_column.php.inc +++ b/rules-tests/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector/Fixture/simple_column.php.inc @@ -25,7 +25,7 @@ class SimpleColumn /** * @ORM\Column(type="string") */ - private ?string $name = null; + private string $name; } ?> diff --git a/rules-tests/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector/Fixture/simple_column_attribute.php.inc b/rules-tests/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector/Fixture/simple_column_attribute.php.inc index c4c0aab6..ad2f7760 100644 --- a/rules-tests/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector/Fixture/simple_column_attribute.php.inc +++ b/rules-tests/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector/Fixture/simple_column_attribute.php.inc @@ -21,7 +21,7 @@ use Doctrine\ORM\Mapping as ORM; class SimpleColumnAttribute { #[ORM\Column(type: 'string')] - private ?string $name = null; + private string $name; } ?> From 899a32e1fa7776999253152e3630d6df1e522650 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20N=C3=A1pravn=C3=ADk?= Date: Fri, 14 Jul 2023 08:43:20 +0200 Subject: [PATCH 3/3] configurable defaultNullableColumn Revert "update tests" commit 49c6af91b9cea2c8f03e7919178c936ddc3c103f. --- docs/rector_rules_overview.md | 21 ++++++++++++ .../Fixture/simple_column.php.inc | 2 +- .../Fixture/simple_column_attribute.php.inc | 2 +- .../TypedPropertyFromColumnTypeRector.php | 32 ++++++++++++++----- .../NullabilityColumnPropertyTypeResolver.php | 10 +++--- 5 files changed, 52 insertions(+), 15 deletions(-) diff --git a/docs/rector_rules_overview.md b/docs/rector_rules_overview.md index bb2f8056..5f064031 100644 --- a/docs/rector_rules_overview.md +++ b/docs/rector_rules_overview.md @@ -284,6 +284,27 @@ Replace `Doctrine\ORM\Event\LifecycleEventArgs` with specific event classes base ## TypedPropertyFromColumnTypeRector + +:wrench: **configure it!** + +- class: [`Rector\Transform\Rector\Attribute\AttributeKeyToClassConstFetchRector`](../rules/Transform/Rector/Attribute/AttributeKeyToClassConstFetchRector.php) + +```php +ruleWithConfiguration(TypedPropertyFromColumnTypeRector::class, [ + TypedPropertyFromColumnTypeRector::DEFAULT_NULLABLE_COLUMN => true, + ]); +}; +``` + Complete `@var` annotations or types based on @ORM\Column - class: [`Rector\Doctrine\CodeQuality\Rector\Property\TypedPropertyFromColumnTypeRector`](../rules/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector.php) diff --git a/rules-tests/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector/Fixture/simple_column.php.inc b/rules-tests/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector/Fixture/simple_column.php.inc index 185a5a14..7a178643 100644 --- a/rules-tests/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector/Fixture/simple_column.php.inc +++ b/rules-tests/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector/Fixture/simple_column.php.inc @@ -25,7 +25,7 @@ class SimpleColumn /** * @ORM\Column(type="string") */ - private string $name; + private ?string $name = null; } ?> diff --git a/rules-tests/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector/Fixture/simple_column_attribute.php.inc b/rules-tests/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector/Fixture/simple_column_attribute.php.inc index ad2f7760..c4c0aab6 100644 --- a/rules-tests/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector/Fixture/simple_column_attribute.php.inc +++ b/rules-tests/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector/Fixture/simple_column_attribute.php.inc @@ -21,7 +21,7 @@ use Doctrine\ORM\Mapping as ORM; class SimpleColumnAttribute { #[ORM\Column(type: 'string')] - private string $name; + private ?string $name = null; } ?> diff --git a/rules/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector.php b/rules/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector.php index 25179ed1..3023c628 100644 --- a/rules/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector.php +++ b/rules/CodeQuality/Rector/Property/TypedPropertyFromColumnTypeRector.php @@ -10,24 +10,27 @@ use PHPStan\Type\Type; use PHPStan\Type\TypeCombinator; use PHPStan\Type\UnionType; -use Rector\BetterPhpDocParser\PhpDocManipulator\PhpDocTypeChanger; -use Rector\Core\Php\PhpVersionProvider; +use Rector\Core\Contract\Rector\AllowEmptyConfigurableRectorInterface; use Rector\Core\Rector\AbstractRector; -use Rector\Core\ValueObject\PhpVersion; use Rector\Core\ValueObject\PhpVersionFeature; use Rector\Doctrine\NodeManipulator\ColumnPropertyTypeResolver; use Rector\Doctrine\NodeManipulator\NullabilityColumnPropertyTypeResolver; use Rector\PHPStanStaticTypeMapper\Enum\TypeKind; use Rector\TypeDeclaration\NodeTypeAnalyzer\PropertyTypeDecorator; use Rector\VersionBonding\Contract\MinPhpVersionInterface; -use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample; +use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample; use Symplify\RuleDocGenerator\ValueObject\RuleDefinition; +use Webmozart\Assert\Assert; /** * @see \Rector\Doctrine\Tests\CodeQuality\Rector\Property\TypedPropertyFromColumnTypeRector\TypedPropertyFromColumnTypeRectorTest */ -final class TypedPropertyFromColumnTypeRector extends AbstractRector implements MinPhpVersionInterface +final class TypedPropertyFromColumnTypeRector extends AbstractRector implements MinPhpVersionInterface, AllowEmptyConfigurableRectorInterface { + public const DEFAULT_NULLABLE_COLUMN = 'default_nullable_column'; + + private bool $defaultNullableColumn = true; + public function __construct( private readonly PropertyTypeDecorator $propertyTypeDecorator, private readonly ColumnPropertyTypeResolver $columnPropertyTypeResolver, @@ -38,7 +41,7 @@ public function __construct( public function getRuleDefinition(): RuleDefinition { return new RuleDefinition('Complete @var annotations or types based on @ORM\Column', [ - new CodeSample( + new ConfiguredCodeSample( <<<'CODE_SAMPLE' use Doctrine\ORM\Mapping as ORM; @@ -62,7 +65,11 @@ class SimpleColumn private string|null $name = null; } CODE_SAMPLE - ), + , + [ + self::DEFAULT_NULLABLE_COLUMN => true, + ] + ), ]); } @@ -83,7 +90,7 @@ public function refactor(Node $node): Property|null return null; } - $isNullable = $this->nullabilityColumnPropertyTypeResolver->isNullable($node); + $isNullable = $this->nullabilityColumnPropertyTypeResolver->isNullable($node, $this->defaultNullableColumn); $propertyType = $this->columnPropertyTypeResolver->resolve($node, $isNullable); if (! $propertyType instanceof Type || $propertyType instanceof MixedType) { @@ -116,6 +123,15 @@ public function refactor(Node $node): Property|null return $node; } + + public function configure(array $configuration): void + { + $defaultNullableColumn = $configuration[self::DEFAULT_NULLABLE_COLUMN] ?? (bool) current($configuration); + Assert::boolean($defaultNullableColumn); + + $this->defaultNullableColumn = $defaultNullableColumn; + } + public function provideMinPhpVersion(): int { return PhpVersionFeature::TYPED_PROPERTIES; diff --git a/src/NodeManipulator/NullabilityColumnPropertyTypeResolver.php b/src/NodeManipulator/NullabilityColumnPropertyTypeResolver.php index 82995da7..399897c1 100644 --- a/src/NodeManipulator/NullabilityColumnPropertyTypeResolver.php +++ b/src/NodeManipulator/NullabilityColumnPropertyTypeResolver.php @@ -31,7 +31,7 @@ public function __construct( ) { } - public function isNullable(Property $property): bool + public function isNullable(Property $property, bool $defaultNullableColumn): bool { $nullableExpr = $this->attributeFinder->findAttributeByClassArgByName( $property, @@ -44,19 +44,19 @@ public function isNullable(Property $property): bool } $phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property); - return $this->isNullableColumn($phpDocInfo); + return $this->isNullableColumn($phpDocInfo, $defaultNullableColumn); } - private function isNullableColumn(PhpDocInfo $phpDocInfo): bool + private function isNullableColumn(PhpDocInfo $phpDocInfo, bool $defaultNullableColumn): bool { $doctrineAnnotationTagValueNode = $phpDocInfo->findOneByAnnotationClass(self::COLUMN_CLASS); if (! $doctrineAnnotationTagValueNode instanceof DoctrineAnnotationTagValueNode) { - return false; + return $defaultNullableColumn; } $nullableValueArrayItemNode = $doctrineAnnotationTagValueNode->getValue('nullable'); if (! $nullableValueArrayItemNode instanceof ArrayItemNode) { - return false; + return $defaultNullableColumn; } return $nullableValueArrayItemNode->value instanceof ConstExprTrueNode;