Skip to content

Commit

Permalink
add promoted property support
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba committed Feb 15, 2024
1 parent 001b5fa commit 11ed994
Show file tree
Hide file tree
Showing 15 changed files with 74 additions and 20 deletions.
5 changes: 5 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,8 @@ parameters:
paths:
- src/NodeManipulator/ColumnPropertyTypeResolver.php
- src/NodeManipulator/NullabilityColumnPropertyTypeResolver.php

# false positive
-
message: '#PHPDoc tag @return contains unresolvable type#'
path: rules/CodeQuality/Contract/PropertyAttributeTransformerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer;

use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Property;
use Rector\Doctrine\CodeQuality\Contract\PropertyAttributeTransformerInterface;
use Rector\Doctrine\CodeQuality\Enum\EntityMappingKey;
Expand All @@ -19,7 +20,7 @@ public function __construct(
) {
}

public function transform(EntityMapping $entityMapping, Property $property): void
public function transform(EntityMapping $entityMapping, Property|Param $property): void
{
$propertyMapping = $entityMapping->matchFieldPropertyMapping($property);
if ($propertyMapping === null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer;

use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Property;
use Rector\Doctrine\CodeQuality\Contract\PropertyAttributeTransformerInterface;
use Rector\Doctrine\CodeQuality\Helper\NodeValueNormalizer;
Expand All @@ -19,7 +20,7 @@ public function __construct(
) {
}

public function transform(EntityMapping $entityMapping, Property $property): void
public function transform(EntityMapping $entityMapping, Property|Param $property): void
{
$propertyMapping = $entityMapping->matchEmbeddedPropertyMapping($property);
if ($propertyMapping === null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer;

use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Property;
use Rector\Doctrine\CodeQuality\Contract\PropertyAttributeTransformerInterface;
use Rector\Doctrine\CodeQuality\NodeFactory\AttributeFactory;
Expand All @@ -18,7 +19,7 @@ public function __construct(
) {
}

public function transform(EntityMapping $entityMapping, Property $property): void
public function transform(EntityMapping $entityMapping, Property|Param $property): void
{
$fieldPropertyMapping = $entityMapping->matchFieldPropertyMapping($property);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer;

use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Property;
use Rector\Doctrine\CodeQuality\Contract\PropertyAttributeTransformerInterface;
use Rector\Doctrine\CodeQuality\NodeFactory\AttributeFactory;
Expand All @@ -12,7 +13,7 @@

final class IdAttributeTransformer implements PropertyAttributeTransformerInterface
{
public function transform(EntityMapping $entityMapping, Property $property): void
public function transform(EntityMapping $entityMapping, Property|Param $property): void
{
$idMapping = $entityMapping->matchIdPropertyMapping($property);
if (! is_array($idMapping)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer;

use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Property;
use Rector\Doctrine\CodeQuality\Contract\PropertyAttributeTransformerInterface;
use Rector\Doctrine\CodeQuality\NodeFactory\AttributeFactory;
Expand All @@ -12,7 +13,7 @@

final class IdColumnAttributeTransformer implements PropertyAttributeTransformerInterface
{
public function transform(EntityMapping $entityMapping, Property $property): void
public function transform(EntityMapping $entityMapping, Property|Param $property): void
{
$idMapping = $entityMapping->matchIdPropertyMapping($property);
if (! is_array($idMapping)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer;

use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Property;
use Rector\Doctrine\CodeQuality\Contract\PropertyAttributeTransformerInterface;
use Rector\Doctrine\CodeQuality\Enum\EntityMappingKey;
Expand All @@ -26,7 +27,7 @@ public function __construct(
) {
}

public function transform(EntityMapping $entityMapping, Property $property): void
public function transform(EntityMapping $entityMapping, Property|Param $property): void
{
$idMapping = $entityMapping->matchIdPropertyMapping($property);
if (! is_array($idMapping)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer;

use PhpParser\Node\AttributeGroup;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Property;
use Rector\Doctrine\CodeQuality\Contract\PropertyAttributeTransformerInterface;
use Rector\Doctrine\CodeQuality\NodeFactory\AttributeFactory;
Expand All @@ -19,7 +20,7 @@ public function __construct(
) {
}

public function transform(EntityMapping $entityMapping, Property $property): void
public function transform(EntityMapping $entityMapping, Property|Param $property): void
{
$manyToOnePropertyMapping = $entityMapping->matchManyToOnePropertyMapping($property);
if (! is_array($manyToOnePropertyMapping)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer;

use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Property;
use Rector\Doctrine\CodeQuality\Contract\PropertyAttributeTransformerInterface;
use Rector\Doctrine\CodeQuality\Enum\EntityMappingKey;
Expand All @@ -20,7 +21,7 @@ public function __construct(
) {
}

public function transform(EntityMapping $entityMapping, Property $property): void
public function transform(EntityMapping $entityMapping, Property|Param $property): void
{
$manyToOneMapping = $entityMapping->matchManyToOnePropertyMapping($property);
if (! is_array($manyToOneMapping)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer;

use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Property;
use Rector\Doctrine\CodeQuality\Contract\PropertyAttributeTransformerInterface;
use Rector\Doctrine\CodeQuality\Enum\EntityMappingKey;
Expand All @@ -20,7 +21,7 @@ public function __construct(
) {
}

public function transform(EntityMapping $entityMapping, Property $property): void
public function transform(EntityMapping $entityMapping, Property|Param $property): void
{
$oneToManyMapping = $entityMapping->matchOneToManyPropertyMapping($property);
if (! is_array($oneToManyMapping)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Rector\Doctrine\CodeQuality\AttributeTransformer\PropertyAttributeTransformer;

use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Property;
use Rector\Doctrine\CodeQuality\Contract\PropertyAttributeTransformerInterface;
use Rector\Doctrine\CodeQuality\Enum\EntityMappingKey;
Expand All @@ -19,7 +20,7 @@ public function __construct(
) {
}

public function transform(EntityMapping $entityMapping, Property $property): void
public function transform(EntityMapping $entityMapping, Property|Param $property): void
{
$oneToManyMapping = $entityMapping->matchOneToManyPropertyMapping($property);
if (! is_array($oneToManyMapping)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@

namespace Rector\Doctrine\CodeQuality\AttributeTransformer;

use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Property;
use Rector\Doctrine\CodeQuality\Contract\ClassAttributeTransformerInterface;
use Rector\Doctrine\CodeQuality\Contract\PropertyAttributeTransformerInterface;
use Rector\Doctrine\CodeQuality\ValueObject\EntityMapping;
use Rector\ValueObject\MethodName;

final readonly class YamlToAttributeTransformer
{
Expand Down Expand Up @@ -50,9 +53,30 @@ private function transformProperties(Class_ $class, EntityMapping $entityMapping
$propertyAttributeTransformer->transform($entityMapping, $property);
}
}

// handle promoted properties
$constructorClassMethod = $class->getMethod(MethodName::CONSTRUCT);
if (! $constructorClassMethod instanceof ClassMethod) {
return;
}

foreach ($constructorClassMethod->getParams() as $param) {
// is promoted property?
if ($param->flags === 0) {
continue;
}

foreach ($this->propertyAttributeTransformers as $propertyAttributeTransformer) {
if ($this->hasAttribute($param, $propertyAttributeTransformer->getClassName())) {
continue;
}

$propertyAttributeTransformer->transform($entityMapping, $param);
}
}
}

private function hasAttribute(Class_|Property $stmt, string $attributeClassName): bool
private function hasAttribute(Class_|Property|Param $stmt, string $attributeClassName): bool
{
foreach ($stmt->attrGroups as $attrGroup) {
foreach ($attrGroup->attrs as $attr) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Rector\Doctrine\CodeQuality\Contract;

use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Property;
use Rector\Doctrine\CodeQuality\ValueObject\EntityMapping;

Expand All @@ -14,5 +15,5 @@ interface PropertyAttributeTransformerInterface
*/
public function getClassName(): string;

public function transform(EntityMapping $entityMapping, Property $property): void;
public function transform(EntityMapping $entityMapping, Property|Param $property): void;
}
27 changes: 20 additions & 7 deletions rules/CodeQuality/ValueObject/EntityMapping.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

namespace Rector\Doctrine\CodeQuality\ValueObject;

use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Property;
use Rector\Exception\ShouldNotHappenException;
use Webmozart\Assert\Assert;

final class EntityMapping
Expand Down Expand Up @@ -33,7 +36,7 @@ public function getClassName(): string
/**
* @return mixed[]|null
*/
public function matchFieldPropertyMapping(Property $property): ?array
public function matchFieldPropertyMapping(Property|Param $property): ?array
{
$propertyName = $this->getPropertyName($property);

Expand All @@ -43,7 +46,7 @@ public function matchFieldPropertyMapping(Property $property): ?array
/**
* @return mixed[]|null
*/
public function matchEmbeddedPropertyMapping(Property $property): ?array
public function matchEmbeddedPropertyMapping(Property|Param $property): ?array
{
$propertyName = $this->getPropertyName($property);

Expand All @@ -53,7 +56,7 @@ public function matchEmbeddedPropertyMapping(Property $property): ?array
/**
* @return array<string, mixed>|null
*/
public function matchManyToOnePropertyMapping(Property $property): ?array
public function matchManyToOnePropertyMapping(Property|Param $property): ?array
{
$propertyName = $this->getPropertyName($property);
return $this->entityMapping['manyToOne'][$propertyName] ?? null;
Expand All @@ -62,7 +65,7 @@ public function matchManyToOnePropertyMapping(Property $property): ?array
/**
* @return array<string, mixed>|null
*/
public function matchOneToManyPropertyMapping(Property $property): ?array
public function matchOneToManyPropertyMapping(Property|Param $property): ?array
{
$propertyName = $this->getPropertyName($property);
return $this->entityMapping['oneToMany'][$propertyName] ?? null;
Expand All @@ -83,15 +86,25 @@ public function getClassMapping(): array
/**
* @return array<string, mixed>|null
*/
public function matchIdPropertyMapping(Property $property): ?array
public function matchIdPropertyMapping(Property|Param $property): ?array
{
$propertyName = $this->getPropertyName($property);

return $this->entityMapping['id'][$propertyName] ?? null;
}

private function getPropertyName(Property $property): string
private function getPropertyName(Property|Param $property): string
{
return $property->props[0]->name->toString();
if ($property instanceof Property) {
return $property->props[0]->name->toString();
}

if ($property->var instanceof Variable) {
$paramName = $property->var->name;
Assert::string($paramName);
return $paramName;
}

throw new ShouldNotHappenException();
}
}
3 changes: 2 additions & 1 deletion src/NodeManipulator/ToManyRelationPropertyTypeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace Rector\Doctrine\NodeManipulator;

use PhpParser\Node\Param;
use PhpParser\Node\Expr;
use PhpParser\Node\Stmt\Property;
use PHPStan\Type\Type;
Expand Down Expand Up @@ -87,7 +88,7 @@ private function processToManyRelation(

private function resolveTypeFromTargetEntity(
Expr|string $targetEntity,
Property|\PhpParser\Node\Param $property
Property|Param $property
): Type {
if ($targetEntity instanceof Expr) {
$targetEntity = $this->valueResolver->getValue($targetEntity);
Expand Down

0 comments on commit 11ed994

Please sign in to comment.