Skip to content

Commit

Permalink
[type-declaration] Add typed property, if traits do not duplicate the…
Browse files Browse the repository at this point in the history
… property (#6663)

* [type-declaration] Add typed property using trait test fixture

* Add typed property, if traits do not duplicate the property
  • Loading branch information
TomasVotruba authored Jan 9, 2025
1 parent c59c83a commit 8da1bfe
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace Rector\Tests\TypeDeclaration\Rector\Property\TypedPropertyFromStrictConstructorRector\Fixture;

use Doctrine\ORM\EntityManagerInterface;
use Rector\Tests\TypeDeclaration\Rector\Property\TypedPropertyFromStrictConstructorRector\Source\TraitUsingEntityManager;

final class IncludeTraitAsWell
{
use TraitUsingEntityManager;

/**
* @var EntityManagerInterface
*/
private $entityManager;

public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
}

?>
-----
<?php

namespace Rector\Tests\TypeDeclaration\Rector\Property\TypedPropertyFromStrictConstructorRector\Fixture;

use Doctrine\ORM\EntityManagerInterface;
use Rector\Tests\TypeDeclaration\Rector\Property\TypedPropertyFromStrictConstructorRector\Source\TraitUsingEntityManager;

final class IncludeTraitAsWell
{
use TraitUsingEntityManager;

private \Doctrine\ORM\EntityManagerInterface $entityManager;

public function __construct(EntityManagerInterface $entityManager)
{
$this->entityManager = $entityManager;
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace Rector\Tests\TypeDeclaration\Rector\Property\TypedPropertyFromStrictConstructorRector\Source;

trait TraitUsingEntityManager
{
public function run()
{
$this->entityManager->flush();
}
}
2 changes: 1 addition & 1 deletion rules/Php74/Guard/PropertyTypeChangeGuard.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public function isLegal(

$propertyName = $this->nodeNameResolver->getName($property);

if ($this->propertyManipulator->isUsedByTrait($classReflection, $propertyName)) {
if ($this->propertyManipulator->hasTraitWithSamePropertyOrWritten($classReflection, $propertyName)) {
return false;
}

Expand Down
6 changes: 1 addition & 5 deletions scoper.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,11 +137,7 @@ static function (string $filePath, string $prefix, string $content): string {
return $content;
}

return str_replace(
"'" . $prefix . "\\",
"'\\",
$content
);
return str_replace("'" . $prefix . '\\', "'\\", $content);
},

static function (string $filePath, string $prefix, string $content): string {
Expand Down
18 changes: 18 additions & 0 deletions src/NodeAnalyzer/PropertyFetchAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,24 @@ public function containsLocalPropertyFetchName(Trait_ $trait, string $propertyNa
);
}

public function containsWrittenPropertyFetchName(Trait_ $trait, string $propertyName): bool
{
if ($trait->getProperty($propertyName) instanceof Property) {
return true;
}

return (bool) $this->betterNodeFinder->findFirst(
$trait,
function (Node $node) use ($propertyName): bool {
if (! $node instanceof Assign) {
return false;
}

return $this->isLocalPropertyFetchName($node->var, $propertyName);
}
);
}

/**
* @phpstan-assert-if-true PropertyFetch|StaticPropertyFetch $node
*/
Expand Down
22 changes: 22 additions & 0 deletions src/NodeManipulator/PropertyManipulator.php
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,28 @@ public function isUsedByTrait(ClassReflection $classReflection, string $property
return false;
}

public function hasTraitWithSamePropertyOrWritten(ClassReflection $classReflection, string $propertyName): bool
{
foreach ($classReflection->getTraits() as $traitUse) {
if ($traitUse->hasProperty($propertyName)) {
return true;
}

$trait = $this->astResolver->resolveClassFromClassReflection($traitUse);
if (! $trait instanceof Trait_) {
continue;
}

// is property written to
if ($this->propertyFetchAnalyzer->containsWrittenPropertyFetchName($trait, $propertyName)) {
return true;
}

}

return false;
}

private function isPropertyAssignedOnlyInConstructor(
Class_ $class,
string $propertyName,
Expand Down

0 comments on commit 8da1bfe

Please sign in to comment.