Skip to content

Commit 96c457b

Browse files
Fix RenamePropertyToMatchTypeRector for non-docblocks properties (#3189)
Co-authored-by: GitHub Action <[email protected]>
1 parent 809467e commit 96c457b

File tree

14 files changed

+101
-64
lines changed

14 files changed

+101
-64
lines changed

packages-tests/BetterPhpDocParser/PhpDocParser/ClassAnnotationMatcher/ResolveTagToKnownFullyQualifiedNameTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ final class ResolveTagToKnownFullyQualifiedNameTest extends AbstractTestCase
2222

2323
private TestingParser $testingParser;
2424

25-
private BetterNodeFinder $nodeFinder;
25+
private BetterNodeFinder $betterNodeFinder;
2626

2727
private PhpDocInfoFactory $phpDocInfoFactory;
2828

@@ -34,7 +34,7 @@ protected function setUp(): void
3434

3535
$this->classAnnotationMatcher = $this->getService(ClassAnnotationMatcher::class);
3636
$this->testingParser = $this->getService(TestingParser::class);
37-
$this->nodeFinder = $this->getService(BetterNodeFinder::class);
37+
$this->betterNodeFinder = $this->getService(BetterNodeFinder::class);
3838
$this->phpDocInfoFactory = $this->getService(PhpDocInfoFactory::class);
3939
$this->nodeNameResolver = $this->getService(NodeNameResolver::class);
4040
}
@@ -45,7 +45,7 @@ protected function setUp(): void
4545
public function testResolvesClass(string $filePath): void
4646
{
4747
$nodes = $this->testingParser->parseFileToDecoratedNodes($filePath);
48-
$properties = $this->nodeFinder->findInstancesOf($nodes, [Property::class]);
48+
$properties = $this->betterNodeFinder->findInstancesOf($nodes, [Property::class]);
4949

5050
foreach ($properties as $property) {
5151
/** @var Property $property */

packages/BetterPhpDocParser/PhpDocInfo/PhpDocInfoFactory.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,9 @@ public function createFromNode(Node $node): ?PhpDocInfo
6666
$this->currentNodeProvider->setNode($node);
6767

6868
$docComment = $node->getDocComment();
69+
6970
if (! $docComment instanceof Doc) {
70-
if ($node->getComments() !== []) {
71+
if ($node->getComments() === []) {
7172
return null;
7273
}
7374

rules-tests/Naming/Naming/UseImportsResolver/UseImportsResolverTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,14 @@ final class UseImportsResolverTest extends AbstractTestCase
2121

2222
private TestingParser $testingParser;
2323

24-
private BetterNodeFinder $nodeFinder;
24+
private BetterNodeFinder $betterNodeFinder;
2525

2626
protected function setUp(): void
2727
{
2828
$this->boot();
2929
$this->useImportsResolver = $this->getService(UseImportsResolver::class);
3030
$this->testingParser = $this->getService(TestingParser::class);
31-
$this->nodeFinder = $this->getService(BetterNodeFinder::class);
31+
$this->betterNodeFinder = $this->getService(BetterNodeFinder::class);
3232
}
3333

3434
/**
@@ -38,7 +38,7 @@ public function testUsesFromProperty(string $filePath): void
3838
{
3939
$nodes = $this->testingParser->parseFileToDecoratedNodes($filePath);
4040

41-
$firstProperty = $this->nodeFinder->findFirstInstanceOf($nodes, Property::class);
41+
$firstProperty = $this->betterNodeFinder->findFirstInstanceOf($nodes, Property::class);
4242
$resolvedUses = $this->useImportsResolver->resolveForNode($firstProperty);
4343

4444
$stringUses = [];
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace Rector\Tests\Naming\Rector\Class_\RenamePropertyToMatchTypeRector\Fixture;
4+
5+
final class ChangeBareProperty
6+
{
7+
private ?\PDO $_pdo;
8+
}
9+
10+
?>
11+
-----
12+
<?php
13+
14+
namespace Rector\Tests\Naming\Rector\Class_\RenamePropertyToMatchTypeRector\Fixture;
15+
16+
final class ChangeBareProperty
17+
{
18+
private ?\PDO $pdo;
19+
}
20+
21+
?>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
namespace Rector\Tests\Naming\Rector\Class_\RenamePropertyToMatchTypeRector\Fixture;
4+
5+
use PhpParser\ParserFactory as NikicParserFactory;
6+
use Rector\Tests\Naming\Rector\Class_\RenamePropertyToMatchTypeRector\Source\GitWrapper;
7+
8+
final class PropertyTypeOverDocblock
9+
{
10+
/**
11+
* @var NikicParserFactory
12+
*/
13+
private GitWrapper $whatever;
14+
}
15+
16+
?>
17+
-----
18+
<?php
19+
20+
namespace Rector\Tests\Naming\Rector\Class_\RenamePropertyToMatchTypeRector\Fixture;
21+
22+
use PhpParser\ParserFactory as NikicParserFactory;
23+
use Rector\Tests\Naming\Rector\Class_\RenamePropertyToMatchTypeRector\Source\GitWrapper;
24+
25+
final class PropertyTypeOverDocblock
26+
{
27+
/**
28+
* @var NikicParserFactory
29+
*/
30+
private GitWrapper $gitWrapper;
31+
}
32+
33+
?>

rules-tests/Naming/Rector/Class_/RenamePropertyToMatchTypeRector/Fixture/skip_capital_numberz.php.inc

Lines changed: 0 additions & 14 deletions
This file was deleted.

rules-tests/Naming/Rector/Class_/RenamePropertyToMatchTypeRector/Source/PHP9Crawler.php

Lines changed: 0 additions & 10 deletions
This file was deleted.

rules-tests/Naming/ValueObjectFactory/PropertyRenameFactory/Fixture/skip_some_class.php.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace Rector\Tests\Naming\ValueObjectFactory\PropertyRenameFactory\Fixture;
66

77
use Rector\Tests\Naming\ValueObjectFactory\PropertyRenameFactory\Source\EliteManager;
88

9-
class SkipSomeClass
9+
final class SkipSomeClass
1010
{
1111
/**
1212
* @var EliteManager

rules-tests/Naming/ValueObjectFactory/PropertyRenameFactory/PropertyRenameFactoryTest.php

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55
namespace Rector\Tests\Naming\ValueObjectFactory\PropertyRenameFactory;
66

77
use Iterator;
8-
use PhpParser\Node\Stmt\Property;
9-
use Rector\Core\Exception\ShouldNotHappenException;
8+
use PhpParser\Node\Stmt\Class_;
109
use Rector\Core\PhpParser\Node\BetterNodeFinder;
1110
use Rector\FileSystemRector\Parser\FileInfoParser;
1211
use Rector\Naming\ExpectedNameResolver\MatchPropertyTypeExpectedNameResolver;
@@ -42,9 +41,14 @@ protected function setUp(): void
4241
*/
4342
public function test(string $filePathWithProperty, string $expectedName, string $currentName): void
4443
{
45-
$property = $this->getPropertyFromFilePath($filePathWithProperty);
44+
$nodes = $this->fileInfoParser->parseFileInfoToNodesAndDecorate($filePathWithProperty);
4645

47-
$expectedPropertyName = $this->matchPropertyTypeExpectedNameResolver->resolve($property);
46+
/** @var Class_ $class */
47+
$class = $this->betterNodeFinder->findFirstInstanceOf($nodes, Class_::class);
48+
49+
$property = $class->getProperty($currentName);
50+
51+
$expectedPropertyName = $this->matchPropertyTypeExpectedNameResolver->resolve($property, $class);
4852
if ($expectedPropertyName === null) {
4953
return;
5054
}
@@ -62,16 +66,4 @@ public function provideData(): Iterator
6266
{
6367
yield [__DIR__ . '/Fixture/skip_some_class.php.inc', 'eliteManager', 'eventManager'];
6468
}
65-
66-
private function getPropertyFromFilePath(string $filePath): Property
67-
{
68-
$nodes = $this->fileInfoParser->parseFileInfoToNodesAndDecorate($filePath);
69-
70-
$property = $this->betterNodeFinder->findFirstInstanceOf($nodes, Property::class);
71-
if (! $property instanceof Property) {
72-
throw new ShouldNotHappenException();
73-
}
74-
75-
return $property;
76-
}
7769
}

rules/Naming/ExpectedNameResolver/MatchPropertyTypeExpectedNameResolver.php

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,37 +5,37 @@
55
namespace Rector\Naming\ExpectedNameResolver;
66

77
use PhpParser\Node\Stmt\Class_;
8+
use PhpParser\Node\Stmt\ClassLike;
89
use PhpParser\Node\Stmt\Property;
910
use PHPStan\Reflection\ClassReflection;
11+
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfo;
1012
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
1113
use Rector\Core\NodeManipulator\PropertyManipulator;
12-
use Rector\Core\PhpParser\Node\BetterNodeFinder;
1314
use Rector\Core\Reflection\ReflectionResolver;
1415
use Rector\Naming\Naming\PropertyNaming;
1516
use Rector\Naming\ValueObject\ExpectedName;
1617
use Rector\NodeNameResolver\NodeNameResolver;
18+
use Rector\StaticTypeMapper\StaticTypeMapper;
1719

1820
final class MatchPropertyTypeExpectedNameResolver
1921
{
2022
public function __construct(
2123
private readonly PropertyNaming $propertyNaming,
2224
private readonly PhpDocInfoFactory $phpDocInfoFactory,
2325
private readonly NodeNameResolver $nodeNameResolver,
24-
private readonly BetterNodeFinder $betterNodeFinder,
2526
private readonly PropertyManipulator $propertyManipulator,
26-
private readonly ReflectionResolver $reflectionResolver
27+
private readonly ReflectionResolver $reflectionResolver,
28+
private readonly StaticTypeMapper $staticTypeMapper
2729
) {
2830
}
2931

30-
public function resolve(Property $property): ?string
32+
public function resolve(Property $property, ClassLike $classLike): ?string
3133
{
32-
$class = $this->betterNodeFinder->findParentType($property, Class_::class);
33-
if (! $class instanceof Class_) {
34+
if (! $classLike instanceof Class_) {
3435
return null;
3536
}
3637

3738
$classReflection = $this->reflectionResolver->resolveClassReflection($property);
38-
3939
if (! $classReflection instanceof ClassReflection) {
4040
return null;
4141
}
@@ -45,9 +45,7 @@ public function resolve(Property $property): ?string
4545
return null;
4646
}
4747

48-
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property);
49-
50-
$expectedName = $this->propertyNaming->getExpectedNameFromType($phpDocInfo->getVarType());
48+
$expectedName = $this->resolveExpectedName($property);
5149
if (! $expectedName instanceof ExpectedName) {
5250
return null;
5351
}
@@ -60,4 +58,21 @@ public function resolve(Property $property): ?string
6058

6159
return $expectedName->getName();
6260
}
61+
62+
private function resolveExpectedName(Property $property): ?ExpectedName
63+
{
64+
// property type first
65+
if ($property->type instanceof \PhpParser\Node) {
66+
$propertyType = $this->staticTypeMapper->mapPhpParserNodePHPStanType($property->type);
67+
return $this->propertyNaming->getExpectedNameFromType($propertyType);
68+
}
69+
70+
// fallback to docblock
71+
$phpDocInfo = $this->phpDocInfoFactory->createFromNode($property);
72+
if ($phpDocInfo instanceof PhpDocInfo) {
73+
return $this->propertyNaming->getExpectedNameFromType($phpDocInfo->getVarType());
74+
}
75+
76+
return null;
77+
}
6378
}

0 commit comments

Comments
 (0)