Skip to content

Commit

Permalink
[TypeDeclaration] Add TypedPropertyFromStrictGetterMethodReturnTypeRe…
Browse files Browse the repository at this point in the history
…ctor (#1048)
  • Loading branch information
TomasVotruba committed Oct 23, 2021
1 parent 341da79 commit fd5edff
Show file tree
Hide file tree
Showing 67 changed files with 539 additions and 262 deletions.
5 changes: 4 additions & 1 deletion config/set/type-declaration-strict.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Rector\TypeDeclaration\Rector\Closure\AddClosureReturnTypeRector;
use Rector\TypeDeclaration\Rector\Param\ParamTypeFromStrictTypedPropertyRector;
use Rector\TypeDeclaration\Rector\Property\TypedPropertyFromStrictConstructorRector;
use Rector\TypeDeclaration\Rector\Property\TypedPropertyFromStrictGetterMethodReturnTypeRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;

return static function (ContainerConfigurator $containerConfigurator): void {
Expand All @@ -20,6 +21,8 @@
$services->set(ParamTypeFromStrictTypedPropertyRector::class);
$services->set(ReturnTypeFromStrictTypedCallRector::class);
$services->set(AddVoidReturnTypeWhereNoReturnRector::class);
// $services->set(AddMethodCallBasedStrictParamTypeRector::class);
$services->set(ReturnTypeFromReturnNewRector::class);

$services->set(TypedPropertyFromStrictGetterMethodReturnTypeRector::class);
$services->set(AddMethodCallBasedStrictParamTypeRector::class);
};
2 changes: 0 additions & 2 deletions config/set/type-declaration.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use Rector\TypeDeclaration\Rector\ClassMethod\AddArrayParamDocTypeRector;
use Rector\TypeDeclaration\Rector\ClassMethod\AddArrayReturnDocTypeRector;
use Rector\TypeDeclaration\Rector\ClassMethod\AddParamTypeFromCallersRector;
use Rector\TypeDeclaration\Rector\ClassMethod\ParamTypeByMethodCallTypeRector;
use Rector\TypeDeclaration\Rector\ClassMethod\ParamTypeByParentCallTypeRector;
use Rector\TypeDeclaration\Rector\Closure\AddClosureReturnTypeRector;
Expand All @@ -21,7 +20,6 @@
$services->set(AddClosureReturnTypeRector::class);
$services->set(AddArrayParamDocTypeRector::class);
$services->set(AddArrayReturnDocTypeRector::class);
// $services->set(AddParamTypeFromCallersRector::class);
$services->set(ParamTypeByParentCallTypeRector::class);
$services->set(ParamTypeByMethodCallTypeRector::class);
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Rector\BetterPhpDocParser\ValueObject\Parser\BetterTokenIterator;
use Rector\BetterPhpDocParser\ValueObject\PhpDocAttributeKey;
use Rector\BetterPhpDocParser\ValueObject\StartAndEnd;
use Rector\Core\Exception\ShouldNotHappenException;
use Symplify\PackageBuilder\Reflection\PrivatesCaller;

/**
Expand Down Expand Up @@ -64,11 +65,12 @@ public function parse(TokenIterator $tokenIterator): PhpDocNode
return $phpDocNode;
}

/**
* @param BetterTokenIterator $tokenIterator
*/
public function parseTag(TokenIterator $tokenIterator): PhpDocTagNode
{
if (! $tokenIterator instanceof BetterTokenIterator) {
throw new ShouldNotHappenException();
}

$tag = $this->resolveTag($tokenIterator);

$phpDocTagValueNode = $this->parseTagValue($tokenIterator, $tag);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@
namespace Rector\BetterPhpDocParser\PhpDocParser;

use PhpParser\Node;
use PhpParser\Node\ComplexType;
use PhpParser\Node\Expr\Closure;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Function_;
Expand Down Expand Up @@ -98,7 +101,7 @@ public function decorateReturnWithSpecificType(
return true;
}

private function isTypeMatch(Node $typeNode, Type $requireType): bool
private function isTypeMatch(ComplexType|Identifier|Name $typeNode, Type $requireType): bool
{
$returnType = $this->staticTypeMapper->mapPhpParserNodePHPStanType($typeNode);

Expand Down
8 changes: 4 additions & 4 deletions packages/NodeNameResolver/NodeNameResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -210,13 +210,13 @@ public function matchNameFromMap(Node $node, array $renameMap): ?string
return $renameMap[$name] ?? null;
}

private function isCallOrIdentifier(Node $node): bool
private function isCallOrIdentifier(Expr|Identifier $node): bool
{
if (! $node instanceof Expr) {
return $node instanceof Identifier;
if ($node instanceof Expr) {
return $this->callAnalyzer->isObjectCall($node);
}

return $this->callAnalyzer->isObjectCall($node);
return true;
}

private function isSingleName(Node $node, string $name): bool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public function enterNode(Node $node): ?Node
$node,
$this->currentPhpParserNode
);

if (! $staticType instanceof FullyQualifiedObjectType) {
return null;
}
Expand All @@ -79,6 +80,10 @@ public function enterNode(Node $node): ?Node
return null;
}

if ($this->currentPhpParserNode === null) {
throw new ShouldNotHappenException();
}

return $this->processFqnNameImport($this->currentPhpParserNode, $node, $staticType, $file);
}

Expand Down Expand Up @@ -180,10 +185,15 @@ private function shouldSkipShortClassName(FullyQualifiedObjectType $fullyQualifi
private function processDoctrineAnnotationTagValueNode(
DoctrineAnnotationTagValueNode $doctrineAnnotationTagValueNode
): void {
$currentPhpParserNode = $this->currentPhpParserNode;
if (! $currentPhpParserNode instanceof PhpParserNode) {
throw new ShouldNotHappenException();
}

$identifierTypeNode = $doctrineAnnotationTagValueNode->identifierTypeNode;
$staticType = $this->staticTypeMapper->mapPHPStanPhpDocTypeNodeToPHPStanType(
$identifierTypeNode,
$this->currentPhpParserNode
$currentPhpParserNode
);

if (! $staticType instanceof FullyQualifiedObjectType) {
Expand All @@ -200,7 +210,7 @@ private function processDoctrineAnnotationTagValueNode(
}

$shortentedIdentifierTypeNode = $this->processFqnNameImport(
$this->currentPhpParserNode,
$currentPhpParserNode,
$identifierTypeNode,
$staticType,
$file
Expand Down Expand Up @@ -229,9 +239,14 @@ private function enterSpacelessPhpDocTagNode(
$attributeClass = ltrim($spacelessPhpDocTagNode->name, '@\\');
$identifierTypeNode = new IdentifierTypeNode($attributeClass);

$currentPhpParserNode = $this->currentPhpParserNode;
if (! $currentPhpParserNode instanceof PhpParserNode) {
throw new ShouldNotHappenException();
}

$staticType = $this->staticTypeMapper->mapPHPStanPhpDocTypeNodeToPHPStanType(
new IdentifierTypeNode($attributeClass),
$this->currentPhpParserNode
$currentPhpParserNode
);

if (! $staticType instanceof FullyQualifiedObjectType) {
Expand All @@ -248,7 +263,7 @@ private function enterSpacelessPhpDocTagNode(
}

$importedName = $this->processFqnNameImport(
$this->currentPhpParserNode,
$currentPhpParserNode,
$identifierTypeNode,
$staticType,
$file
Expand Down
18 changes: 18 additions & 0 deletions packages/StaticTypeMapper/ValueObject/Type/AliasedObjectType.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
use PhpParser\Node\Stmt\Use_;
use PhpParser\Node\Stmt\UseUse;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\TypeWithClassName;
use Rector\NodeTypeResolver\Node\AttributeKey;

final class AliasedObjectType extends ObjectType
Expand Down Expand Up @@ -53,4 +55,20 @@ public function getFunctionUseNode(): Use_

return $use;
}

public function equals(Type $type): bool
{
// compare with FQN classes
if ($type instanceof TypeWithClassName) {
if ($type instanceof self && $this->fullyQualifiedClass === $type->getFullyQualifiedClass()) {
return true;
}

if ($this->fullyQualifiedClass === $type->getClassName()) {
return true;
}
}

return parent::equals($type);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

namespace Rector\VendorLocker\NodeVendorLocker;

use PhpParser\Node;
use PhpParser\Node\Stmt\Property;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ClassReflection;
Expand Down Expand Up @@ -68,9 +67,9 @@ public function isChildLockedProperty(Property $property): bool
return false;
}

private function resolveClassReflection(Node $node): ?ClassReflection
private function resolveClassReflection(Property $property): ?ClassReflection
{
$scope = $node->getAttribute(AttributeKey::SCOPE);
$scope = $property->getAttribute(AttributeKey::SCOPE);
if (! $scope instanceof Scope) {
return null;
}
Expand Down
11 changes: 6 additions & 5 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -336,9 +336,10 @@ parameters:
- '#Parameter (.*?) expects PhpParser\\Node, PhpParser\\Node\|null given#'

-
message: '#Class cognitive complexity is \d+, keep it under 50#'
message: '#Class cognitive complexity is \d+, keep it under \d+#'
paths:
- packages/PHPStanStaticTypeMapper/TypeMapper/UnionTypeMapper.php
- src/Rector/AbstractRector.php

- '#Cognitive complexity for "Rector\\PHPStanStaticTypeMapper\\TypeMapper\\UnionTypeMapper\:\:mapToPhpParserNode\(\)" is 10, keep it under 9#'

Expand Down Expand Up @@ -372,10 +373,6 @@ parameters:

- '#Cognitive complexity for "Rector\\Core\\Rector\\AbstractRector\:\:enterNode\(\)" is \d+, keep it under 9#'

-
message: '#Class cognitive complexity is 34, keep it under 30#'
path: src/Rector/AbstractRector.php

# deserves better architecture
-
message: '#Do not use chained method calls#'
Expand Down Expand Up @@ -532,3 +529,7 @@ parameters:
-
message: '#Instead of "new ClassReflection\(\)" use ReflectionProvider service or "\(new PHPStan\\Reflection\\ClassReflection\(<desired_type\>\)\)" for static reflection to work#'
path: packages/NodeTypeResolver/PHPStan/Scope/PHPStanNodeScopeResolver.php #164

-
message: '#Instead of "instanceof/is_a\(\)" use ReflectionProvider service or "\(new ObjectType\(<desired_type\>\)\)\-\>isSuperTypeOf\(<element_type\>\)" for static reflection to work#'
path: packages/StaticTypeMapper/ValueObject/Type/AliasedObjectType.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace Rector\Tests\CodeQuality\Rector\If_\CombineIfRector\Fixture;

use PhpParser\Node\Expr\Assign;

final class SkipNestedType
{
public function run($expr)
{
if ($this->isAssign($expr)) {
/** @var Assign $expr */
if ($expr->var) {
return true;
}
}

return false;
}

private function isAssign($expr)
{
if ($expr instanceof Assign) {
return true;
}

return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\AddMethodCallBasedStrictParamTypeRector\Fixture;

use PhpParser\Node as PhpParserNode;

final class SkipAlias
{
public function run(PhpParserNode $node)
{
$this->getById($node);
}

private function getById(PhpParserNode $node)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace Rector\Tests\TypeDeclaration\Rector\ClassMethod\AddMethodCallBasedStrictParamTypeRector\Fixture;

use PhpParser\Node;
use PhpParser\Node\Scalar\String_;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;

final class SkipContractDoc extends AbstractRector
{
public function getRuleDefinition(): RuleDefinition
{
}

public function getNodeTypes(): array
{
}

/**
* @param String_ $node
*/
public function refactor(Node $node)
{
$this->processString($node);
return null;
}

private function processString(String_ $string)
{
}
}

This file was deleted.

This file was deleted.

0 comments on commit fd5edff

Please sign in to comment.