rector/src/NodeAnalyzer/ExprAnalyzer.php
Tomas Votruba 8187757e86 Updated Rector to commit 3820e0075152c72f618226ff213faf847e3d39f7
3820e00751 [CodeQuality] Skip static::class on InlineConstructorDefaultToPropertyRector (#2899)
2022-09-03 06:21:38 +00:00

114 lines
3.9 KiB
PHP

<?php
declare (strict_types=1);
namespace Rector\Core\NodeAnalyzer;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Expr\ConstFetch;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\FunctionLike;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Scalar;
use PhpParser\Node\Scalar\Encapsed;
use PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory;
use Rector\Core\Enum\ObjectReference;
use Rector\Core\NodeManipulator\ArrayManipulator;
use Rector\Core\PhpParser\Comparing\NodeComparator;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
use Rector\NodeNameResolver\NodeNameResolver;
final class ExprAnalyzer
{
/**
* @readonly
* @var \Rector\Core\PhpParser\Comparing\NodeComparator
*/
private $nodeComparator;
/**
* @readonly
* @var \Rector\Core\PhpParser\Node\BetterNodeFinder
*/
private $betterNodeFinder;
/**
* @readonly
* @var \Rector\BetterPhpDocParser\PhpDocInfo\PhpDocInfoFactory
*/
private $phpDocInfoFactory;
/**
* @readonly
* @var \Rector\NodeNameResolver\NodeNameResolver
*/
private $nodeNameResolver;
/**
* @readonly
* @var \Rector\Core\NodeManipulator\ArrayManipulator
*/
private $arrayManipulator;
public function __construct(NodeComparator $nodeComparator, BetterNodeFinder $betterNodeFinder, PhpDocInfoFactory $phpDocInfoFactory, NodeNameResolver $nodeNameResolver, ArrayManipulator $arrayManipulator)
{
$this->nodeComparator = $nodeComparator;
$this->betterNodeFinder = $betterNodeFinder;
$this->phpDocInfoFactory = $phpDocInfoFactory;
$this->nodeNameResolver = $nodeNameResolver;
$this->arrayManipulator = $arrayManipulator;
}
public function isNonTypedFromParam(Expr $expr) : bool
{
if (!$expr instanceof Variable) {
return \false;
}
$functionLike = $this->betterNodeFinder->findParentType($expr, FunctionLike::class);
if (!$functionLike instanceof FunctionLike) {
return \false;
}
$phpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($functionLike);
$params = $functionLike->getParams();
foreach ($params as $param) {
if (!$this->nodeComparator->areNodesEqual($param->var, $expr)) {
continue;
}
$paramName = $this->nodeNameResolver->getName($param->var);
if ($paramName === null) {
continue;
}
$paramTag = $phpDocInfo->getParamTagValueByName($paramName);
return $paramTag instanceof ParamTagValueNode && $param->type === null;
}
return \false;
}
public function isDynamicExpr(Expr $expr) : bool
{
if (!$expr instanceof Array_) {
if ($expr instanceof Scalar) {
// string interpolation is true, otherwise false
return $expr instanceof Encapsed;
}
return !$this->isAllowedConstFetchOrClassConstFetch($expr);
}
return $this->arrayManipulator->isDynamicArray($expr);
}
private function isAllowedConstFetchOrClassConstFetch(Expr $expr) : bool
{
if ($expr instanceof ConstFetch) {
return \true;
}
if ($expr instanceof ClassConstFetch) {
if (!$expr->class instanceof Name) {
return \false;
}
if (!$expr->name instanceof Identifier) {
return \false;
}
if ($expr->name->toString() !== 'class') {
return \true;
}
// static::class cannot be used for compile-time class name resolution
return $expr->class->toString() !== ObjectReference::STATIC;
}
return \false;
}
}