mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-01 17:00:51 +00:00
re-use param in constructor (#3913)
This commit is contained in:
parent
93905cb64c
commit
5e0dfbd77a
|
@ -21,7 +21,7 @@
|
|||
"nikic/php-parser": "^4.7",
|
||||
"ondram/ci-detector": "^3.4",
|
||||
"phpstan/phpdoc-parser": "^0.4.8",
|
||||
"phpstan/phpstan": "^0.12.35",
|
||||
"phpstan/phpstan": "^0.12.36",
|
||||
"phpstan/phpstan-phpunit": "^0.12.10",
|
||||
"psr/simple-cache": "^1.0",
|
||||
"sebastian/diff": "^3.0|^4.0",
|
||||
|
|
|
@ -8,7 +8,10 @@ use PhpParser\Node\Expr;
|
|||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\FunctionLike;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Function_;
|
||||
use PHPStan\Analyser\Scope;
|
||||
use PHPStan\Reflection\ClassReflection;
|
||||
use PHPStan\Reflection\ParametersAcceptorSelector;
|
||||
|
@ -18,6 +21,9 @@ use PHPStan\Type\MixedType;
|
|||
use PHPStan\Type\Type;
|
||||
use PHPStan\Type\TypeWithClassName;
|
||||
use PHPStan\Type\UnionType;
|
||||
use Rector\Core\ValueObject\MethodName;
|
||||
use Rector\Naming\Naming\PropertyNaming;
|
||||
use Rector\NodeNameResolver\NodeNameResolver;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Rector\PHPStanStaticTypeMapper\Utils\TypeUnwrapper;
|
||||
|
||||
|
@ -33,16 +39,33 @@ final class TypeProvidingExprFromClassResolver
|
|||
*/
|
||||
private $reflectionProvider;
|
||||
|
||||
public function __construct(TypeUnwrapper $typeUnwrapper, ReflectionProvider $reflectionProvider)
|
||||
{
|
||||
/**
|
||||
* @var NodeNameResolver
|
||||
*/
|
||||
private $nodeNameResolver;
|
||||
|
||||
/**
|
||||
* @var PropertyNaming
|
||||
*/
|
||||
private $propertyNaming;
|
||||
|
||||
public function __construct(
|
||||
TypeUnwrapper $typeUnwrapper,
|
||||
ReflectionProvider $reflectionProvider,
|
||||
NodeNameResolver $nodeNameResolver,
|
||||
PropertyNaming $propertyNaming
|
||||
) {
|
||||
$this->typeUnwrapper = $typeUnwrapper;
|
||||
$this->reflectionProvider = $reflectionProvider;
|
||||
$this->nodeNameResolver = $nodeNameResolver;
|
||||
$this->propertyNaming = $propertyNaming;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MethodCall|PropertyFetch|null
|
||||
* @param ClassMethod|Function_ $functionLike
|
||||
* @return MethodCall|PropertyFetch|Variable|null
|
||||
*/
|
||||
public function resolveTypeProvidingExprFromClass(Class_ $class, string $type): ?Expr
|
||||
public function resolveTypeProvidingExprFromClass(Class_ $class, FunctionLike $functionLike, string $type): ?Expr
|
||||
{
|
||||
$className = $class->getAttribute(AttributeKey::CLASS_NAME);
|
||||
if ($className === null) {
|
||||
|
@ -62,7 +85,13 @@ final class TypeProvidingExprFromClassResolver
|
|||
return null;
|
||||
}
|
||||
|
||||
return $this->resolvePropertyFetchProvidingType($classReflection, $scope, $type);
|
||||
$propertyFetch = $this->resolvePropertyFetchProvidingType($classReflection, $scope, $type);
|
||||
if ($propertyFetch !== null) {
|
||||
return $propertyFetch;
|
||||
}
|
||||
|
||||
// C. param in constructor?
|
||||
return $this->resolveConstructorParamProvidingType($functionLike, $type);
|
||||
}
|
||||
|
||||
private function resolveMethodCallProvidingType(ClassReflection $classReflection, string $type): ?MethodCall
|
||||
|
@ -118,4 +147,18 @@ final class TypeProvidingExprFromClassResolver
|
|||
|
||||
return $readableType->getClassName() === $type;
|
||||
}
|
||||
|
||||
private function resolveConstructorParamProvidingType(FunctionLike $functionLike, string $type): ?Variable
|
||||
{
|
||||
if (! $functionLike instanceof ClassMethod) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $this->nodeNameResolver->isName($functionLike, MethodName::CONSTRUCT)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$variableName = $this->propertyNaming->fqnToVariableName($type);
|
||||
return new Variable($variableName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,10 @@ use PhpParser\Node\Expr;
|
|||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\FunctionLike;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Function_;
|
||||
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\Generic\NodeTypeAnalyzer\TypeProvidingExprFromClassResolver;
|
||||
|
@ -39,12 +42,21 @@ abstract class AbstractToMethodCallRector extends AbstractRector implements Conf
|
|||
}
|
||||
|
||||
/**
|
||||
* @return MethodCall|PropertyFetch
|
||||
* @param ClassMethod|Function_ $functionLike
|
||||
* @return MethodCall|PropertyFetch|Variable
|
||||
*/
|
||||
protected function matchTypeProvidingExpr(Class_ $class, string $type): Expr
|
||||
protected function matchTypeProvidingExpr(Class_ $class, FunctionLike $functionLike, string $type): Expr
|
||||
{
|
||||
$expr = $this->typeProvidingExprFromClassResolver->resolveTypeProvidingExprFromClass($class, $type);
|
||||
$expr = $this->typeProvidingExprFromClassResolver->resolveTypeProvidingExprFromClass(
|
||||
$class,
|
||||
$functionLike,
|
||||
$type
|
||||
);
|
||||
if ($expr !== null) {
|
||||
if ($expr instanceof Variable) {
|
||||
$this->addClassMethodParamForVariable($expr, $type, $functionLike);
|
||||
}
|
||||
|
||||
return $expr;
|
||||
}
|
||||
|
||||
|
@ -66,4 +78,18 @@ abstract class AbstractToMethodCallRector extends AbstractRector implements Conf
|
|||
|
||||
return new PropertyFetch($thisVariable, $propertyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClassMethod|Function_ $functionLike
|
||||
*/
|
||||
private function addClassMethodParamForVariable(Variable $variable, string $type, FunctionLike $functionLike): void
|
||||
{
|
||||
/** @var string $variableName */
|
||||
$variableName = $this->getName($variable);
|
||||
|
||||
// add variable to __construct as dependency
|
||||
$param = $this->nodeFactory->createParamFromNameAndType($variableName, new FullyQualifiedObjectType($type));
|
||||
|
||||
$functionLike->params[] = $param;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,16 +98,16 @@ CODE_SAMPLE
|
|||
return null;
|
||||
}
|
||||
|
||||
foreach ($this->functionToClassToMethod as $function => $classMethod) {
|
||||
foreach ($this->functionToClassToMethod as $function => $classMethodName) {
|
||||
if (! $this->isName($node->name, $function)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @var string $type */
|
||||
/** @var string $method */
|
||||
[$type, $method] = $classMethod;
|
||||
[$type, $method] = $classMethodName;
|
||||
|
||||
$expr = $this->matchTypeProvidingExpr($classLike, $type);
|
||||
$expr = $this->matchTypeProvidingExpr($classLike, $classMethod, $type);
|
||||
return $this->createMethodCall($expr, $method, $node->args);
|
||||
}
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ PHP
|
|||
return $this->refactorToInstanceCall($node, $staticCallToMethodCall);
|
||||
}
|
||||
|
||||
$expr = $this->matchTypeProvidingExpr($classLike, $staticCallToMethodCall->getClassType());
|
||||
$expr = $this->matchTypeProvidingExpr($classLike, $classMethod, $staticCallToMethodCall->getClassType());
|
||||
return new MethodCall($expr, $staticCallToMethodCall->getMethodName(), $node->args);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace Rector\Injection\Tests\Rector\StaticCall\StaticCallToMethodCallRector\Fixture;
|
||||
|
||||
use Nette\Utils\FileSystem;
|
||||
|
||||
class InConstructor
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
return FileSystem::write('file', 'content');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace Rector\Injection\Tests\Rector\StaticCall\StaticCallToMethodCallRector\Fixture;
|
||||
|
||||
use Nette\Utils\FileSystem;
|
||||
|
||||
class InConstructor
|
||||
{
|
||||
public function __construct(\Symplify\SmartFileSystem\SmartFileSystem $smartFileSystem)
|
||||
{
|
||||
return $smartFileSystem->dumpFile('file', 'content');
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
Loading…
Reference in New Issue
Block a user