Skip to content

Commit

Permalink
[TypeDeclaration] Improve param by caller types (#5786)
Browse files Browse the repository at this point in the history
  • Loading branch information
TomasVotruba authored Mar 6, 2021
1 parent 031deda commit 3fea742
Show file tree
Hide file tree
Showing 13 changed files with 122 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,32 @@

use PhpParser\Node;
use PhpParser\Node\Expr\Cast;
use PhpParser\Node\Expr\Cast\Array_;
use PhpParser\Node\Expr\Cast\Bool_;
use PhpParser\Node\Expr\Cast\Double;
use PhpParser\Node\Expr\Cast\Int_;
use PhpParser\Node\Expr\Cast\String_;
use PHPStan\Type\ArrayType;
use PHPStan\Type\BooleanType;
use PHPStan\Type\FloatType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\MixedType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use Rector\Core\Exception\NotImplementedYetException;
use Rector\NodeTypeResolver\Contract\NodeTypeResolverInterface;
use Rector\NodeTypeResolver\NodeTypeResolver;

final class CastTypeResolver implements NodeTypeResolverInterface
{
/**
* @var NodeTypeResolver
* @var array<class-string<Node>, class-string<Type>>
*/
private $nodeTypeResolver;

/**
* @required
*/
public function autowireCastTypeResolver(NodeTypeResolver $nodeTypeResolver): void
{
$this->nodeTypeResolver = $nodeTypeResolver;
}
private const CAST_CLASS_TO_TYPE_MAP = [
Bool_::class => BooleanType::class,
String_::class => StringType::class,
Int_::class => IntegerType::class,
Double::class => FloatType::class,
];

/**
* @return array<class-string<Node>>
Expand All @@ -38,6 +46,16 @@ public function getNodeClasses(): array
*/
public function resolve(Node $node): Type
{
return $this->nodeTypeResolver->resolve($node->expr);
foreach (self::CAST_CLASS_TO_TYPE_MAP as $castClass => $typeClass) {
if (is_a($node, $castClass, true)) {
return new $typeClass();
}
}

if ($node instanceof Array_) {
return new ArrayType(new MixedType(), new MixedType());
}

throw new NotImplementedYetException(get_class($node));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@

use PhpParser\Node;
use PhpParser\Node\Expr\ClassConstFetch;
use PHPStan\Type\Generic\GenericClassStringType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use Rector\NodeNameResolver\NodeNameResolver;
use Rector\NodeTypeResolver\Contract\NodeTypeResolverInterface;
use Rector\NodeTypeResolver\NodeTypeResolver;

Expand All @@ -18,11 +21,20 @@ final class ClassConstFetchTypeResolver implements NodeTypeResolverInterface
private $nodeTypeResolver;

/**
* @var NodeNameResolver
*/
private $nodeNameResolver;

/**
* To avoid cricular references
* @required
*/
public function autowireClassConstFetchTypeResolver(NodeTypeResolver $nodeTypeResolver): void
{
public function autowireClassConstFetchTypeResolver(
NodeTypeResolver $nodeTypeResolver,
NodeNameResolver $nodeNameResolver
): void {
$this->nodeTypeResolver = $nodeTypeResolver;
$this->nodeNameResolver = $nodeNameResolver;
}

/**
Expand All @@ -38,6 +50,13 @@ public function getNodeClasses(): array
*/
public function resolve(Node $node): Type
{
if ($this->nodeNameResolver->isName($node->name, 'class')) {
$className = $this->nodeNameResolver->getName($node->class);
if ($className !== null) {
return new GenericClassStringType(new ObjectType($className));
}
}

return $this->nodeTypeResolver->resolve($node->class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,6 @@

final class PHPStanStaticTypeMapper
{
/**
* @var string
*/
public const KIND_PARAM = 'param';

/**
* @var string
*/
public const KIND_PROPERTY = 'property';

/**
* @var string
*/
public const KIND_RETURN = 'return';

/**
* @var TypeMapperInterface[]
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
use PHPStan\Type\VerbosityLevel;
use Rector\AttributeAwarePhpDoc\Ast\Type\AttributeAwareIdentifierTypeNode;
use Rector\PHPStanStaticTypeMapper\Contract\TypeMapperInterface;
use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper;
use Rector\PHPStanStaticTypeMapper\ValueObject\TypeKind;

final class NullTypeMapper implements TypeMapperInterface
{
Expand All @@ -37,7 +37,7 @@ public function mapToPHPStanPhpDocTypeNode(Type $type): TypeNode
*/
public function mapToPhpParserNode(Type $type, ?string $kind = null): ?Node
{
if ($kind !== PHPStanStaticTypeMapper::KIND_PROPERTY) {
if ($kind !== TypeKind::KIND_PROPERTY) {
return null;
}

Expand Down
23 changes: 23 additions & 0 deletions packages/phpstan-static-type-mapper/src/ValueObject/TypeKind.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

namespace Rector\PHPStanStaticTypeMapper\ValueObject;

final class TypeKind
{
/**
* @var string
*/
public const KIND_PROPERTY = 'property';

/**
* @var string
*/
public const KIND_RETURN = 'return';

/**
* @var string
*/
public const KIND_PARAM = 'param';
}
4 changes: 2 additions & 2 deletions rules/php74/src/Rector/Property/TypedPropertyRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\DeadDocBlock\TagRemover\VarTagRemover;
use Rector\PHPStanStaticTypeMapper\DoctrineTypeAnalyzer;
use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper;
use Rector\PHPStanStaticTypeMapper\ValueObject\TypeKind;
use Rector\TypeDeclaration\TypeInferer\PropertyTypeInferer;
use Rector\VendorLocker\VendorLockResolver;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
Expand Down Expand Up @@ -151,7 +151,7 @@ public function refactor(Node $node): ?Node

$propertyTypeNode = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode(
$varType,
PHPStanStaticTypeMapper::KIND_PROPERTY
TypeKind::KIND_PROPERTY
);

if ($propertyTypeNode === null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,25 +39,12 @@ public function getRuleDefinition(): RuleDefinition
<<<'CODE_SAMPLE'
$container = new SomeContainer;
isset($container["someKey"]);
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
$container = new SomeContainer;
$container->hasService("someKey");
CODE_SAMPLE
,
[
self::ISSET_UNSET_TO_METHOD_CALL => [$unsetAndIssetToMethodCall],
]
),
new ConfiguredCodeSample(
<<<'CODE_SAMPLE'
$container = new SomeContainer;
unset($container["someKey"]);
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
$container = new SomeContainer;
$container->hasService("someKey");
$container->removeService("someKey");
CODE_SAMPLE
,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ final class ToStringToMethodCallRector extends AbstractRector implements Configu
public const METHOD_NAMES_BY_TYPE = 'method_names_by_type';

/**
* @var string[]
* @var array<string, string>
*/
private $methodNamesByType = [];

Expand Down Expand Up @@ -75,6 +75,9 @@ public function refactor(Node $node): ?Node
return $this->processMethodCall($node);
}

/**
* @param array<string, array<string, string>> $configuration
*/
public function configure(array $configuration): void
{
$this->methodNamesByType = $configuration[self::METHOD_NAMES_BY_TYPE] ?? [];
Expand All @@ -83,7 +86,7 @@ public function configure(array $configuration): void
private function processStringNode(String_ $string): ?Node
{
foreach ($this->methodNamesByType as $type => $methodName) {
if (! $this->isObjectType($string, new ObjectType($type))) {
if (! $this->isObjectType($string->expr, new ObjectType($type))) {
continue;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\DeadDocBlock\TagRemover\ParamTagRemover;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper;
use Rector\PHPStanStaticTypeMapper\ValueObject\TypeKind;
use Rector\TypeDeclaration\ChildPopulator\ChildParamPopulator;
use Rector\TypeDeclaration\NodeTypeAnalyzer\TraitTypeAnalyzer;
use Rector\TypeDeclaration\TypeInferer\ParamTypeInferer;
Expand Down Expand Up @@ -185,7 +185,7 @@ private function refactorParam(Param $param, FunctionLike $functionLike, int $po

$paramTypeNode = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode(
$inferedType,
PHPStanStaticTypeMapper::KIND_PARAM
TypeKind::KIND_PARAM
);

if ($paramTypeNode === null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
use Rector\Core\Rector\AbstractRector;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper;
use Rector\PHPStanStaticTypeMapper\ValueObject\TypeKind;
use Rector\TypeDeclaration\ChildPopulator\ChildReturnPopulator;
use Rector\TypeDeclaration\PhpDocParser\NonInformativeReturnTagRemover;
use Rector\TypeDeclaration\PhpParserTypeAnalyzer;
Expand Down Expand Up @@ -174,7 +174,7 @@ private function processType(Node $node, Type $inferedType): ?Node
{
$inferredReturnNode = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode(
$inferedType,
PHPStanStaticTypeMapper::KIND_RETURN
TypeKind::KIND_RETURN
);

// nothing to change in PHP code
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use Rector\Core\Rector\AbstractRector;
use Rector\Core\ValueObject\PhpVersionFeature;
use Rector\DeadDocBlock\TagRemover\VarTagRemover;
use Rector\PHPStanStaticTypeMapper\PHPStanStaticTypeMapper;
use Rector\PHPStanStaticTypeMapper\ValueObject\TypeKind;
use Rector\TypeDeclaration\TypeInferer\PropertyTypeInferer\ConstructorPropertyTypeInferer;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
Expand Down Expand Up @@ -99,7 +99,7 @@ public function refactor(Node $node): ?Node

$propertyTypeNode = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode(
$varType,
PHPStanStaticTypeMapper::KIND_PROPERTY
TypeKind::KIND_PROPERTY
);

if ($propertyTypeNode === null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

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

final class SkipBooleanCast
{
public function run()
{
$this->setValue((bool) 1);
}

public function setValue(bool $isValue)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

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

use Rector\Core\Contract\Rector\PhpRectorInterface;

final class SkipByClassString
{
public function run()
{
$this->provideByType(PhpRectorInterface::class);
}

public function provideByType(string $type)
{
}
}

0 comments on commit 3fea742

Please sign in to comment.