Fix WrapEncapsedVariableInCurlyBracesRector reporting (#6220)

Co-authored-by: kaizen-ci <info@kaizen-ci.org>
This commit is contained in:
Tomas Votruba 2021-04-23 21:32:59 +02:00 committed by GitHub
parent a3ec81fe1f
commit f9dc93cb1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 162 additions and 66 deletions

View File

@ -19,6 +19,7 @@ final class AttributeKey
public const SCOPE = 'scope';
/**
* @deprecated
* @var string
*/
public const USE_NODES = 'useNodes';

View File

@ -1,21 +1,11 @@
<?php
namespace Rector\Tests\CodingStyle\Rector\Encapsed\WrapEncapsedVariableInCurlyBracesRector\Fixture;
function run($world)
{
return "Hello $world!";
}
return "Hello $world!";
?>
-----
<?php
namespace Rector\Tests\CodingStyle\Rector\Encapsed\WrapEncapsedVariableInCurlyBracesRector\Fixture;
function run($world)
{
return "Hello {$world}!";
}
return "Hello {$world}!";
?>

View File

@ -12,6 +12,7 @@ use PHPStan\Type\Type;
use Rector\CodeQuality\NodeAnalyzer\ClassLikeAnalyzer;
use Rector\CodeQuality\NodeAnalyzer\LocalPropertyAnalyzer;
use Rector\CodeQuality\NodeFactory\MissingPropertiesFactory;
use Rector\Core\NodeAnalyzer\ClassAnalyzer;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
@ -45,16 +46,23 @@ final class CompleteDynamicPropertiesRector extends AbstractRector
*/
private $reflectionProvider;
/**
* @var ClassAnalyzer
*/
private $classAnalyzer;
public function __construct(
MissingPropertiesFactory $missingPropertiesFactory,
LocalPropertyAnalyzer $localPropertyAnalyzer,
ClassLikeAnalyzer $classLikeAnalyzer,
ReflectionProvider $reflectionProvider
ReflectionProvider $reflectionProvider,
ClassAnalyzer $classAnalyzer
) {
$this->missingPropertiesFactory = $missingPropertiesFactory;
$this->localPropertyAnalyzer = $localPropertyAnalyzer;
$this->classLikeAnalyzer = $classLikeAnalyzer;
$this->reflectionProvider = $reflectionProvider;
$this->classAnalyzer = $classAnalyzer;
}
public function getRuleDefinition(): RuleDefinition

View File

@ -61,7 +61,6 @@ CODE_SAMPLE
if ($previousNodeEndTokenPosition + 1 === $nodePart->getStartTokenPos()) {
$hasVariableBeenWrapped = true;
$node->parts[$index] = new Variable($nodePart->name);
}
}

View File

@ -9,6 +9,7 @@ use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\Core\NodeAnalyzer\ClassAnalyzer;
use Rector\Core\NodeManipulator\ClassMethodManipulator;
use Rector\Core\Rector\AbstractRector;
use Rector\NodeCollector\ScopeResolver\ParentClassScopeResolver;
@ -31,12 +32,19 @@ final class RemoveParentCallWithoutParentRector extends AbstractRector
*/
private $parentClassScopeResolver;
/**
* @var ClassAnalyzer
*/
private $classAnalyzer;
public function __construct(
ClassMethodManipulator $classMethodManipulator,
ParentClassScopeResolver $parentClassScopeResolver
ParentClassScopeResolver $parentClassScopeResolver,
ClassAnalyzer $classAnalyzer
) {
$this->classMethodManipulator = $classMethodManipulator;
$this->parentClassScopeResolver = $parentClassScopeResolver;
$this->classAnalyzer = $classAnalyzer;
}
public function getRuleDefinition(): RuleDefinition

View File

@ -13,6 +13,7 @@ use PhpParser\Node\Stmt;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Function_;
use PhpParser\Node\Stmt\Namespace_;
use Rector\Core\NodeAnalyzer\ClassAnalyzer;
use Rector\Core\Rector\AbstractRector;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
@ -28,6 +29,16 @@ final class DowngradeAnonymousClassRector extends AbstractRector
*/
private const CLASS_NAME = 'AnonymousFor_';
/**
* @var ClassAnalyzer
*/
private $classAnalyzer;
public function __construct(ClassAnalyzer $classAnalyzer)
{
$this->classAnalyzer = $classAnalyzer;
}
/**
* @return array<class-string<Node>>
*/

View File

@ -6,6 +6,7 @@ namespace Rector\Privatization\Rector\Class_;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use Rector\Core\NodeAnalyzer\ClassAnalyzer;
use Rector\Core\NodeManipulator\ClassManipulator;
use Rector\Core\Rector\AbstractRector;
use Rector\Privatization\NodeAnalyzer\PropertyFetchByMethodAnalyzer;
@ -33,14 +34,21 @@ final class ChangeLocalPropertyToVariableRector extends AbstractRector
*/
private $propertyFetchByMethodAnalyzer;
/**
* @var ClassAnalyzer
*/
private $classAnalyzer;
public function __construct(
ClassManipulator $classManipulator,
PropertyFetchWithVariableReplacer $propertyFetchWithVariableReplacer,
PropertyFetchByMethodAnalyzer $propertyFetchByMethodAnalyzer
PropertyFetchByMethodAnalyzer $propertyFetchByMethodAnalyzer,
ClassAnalyzer $classAnalyzer
) {
$this->classManipulator = $classManipulator;
$this->propertyFetchWithVariableReplacer = $propertyFetchWithVariableReplacer;
$this->propertyFetchByMethodAnalyzer = $propertyFetchByMethodAnalyzer;
$this->classAnalyzer = $classAnalyzer;
}
public function getRuleDefinition(): RuleDefinition

View File

@ -6,6 +6,7 @@ namespace Rector\Privatization\Rector\Class_;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use Rector\Core\NodeAnalyzer\ClassAnalyzer;
use Rector\Core\Rector\AbstractRector;
use Symplify\RuleDocGenerator\ValueObject\CodeSample\CodeSample;
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
@ -15,6 +16,16 @@ use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
*/
final class FinalizeClassesWithoutChildrenRector extends AbstractRector
{
/**
* @var ClassAnalyzer
*/
private $classAnalyzer;
public function __construct(ClassAnalyzer $classAnalyzer)
{
$this->classAnalyzer = $classAnalyzer;
}
public function getRuleDefinition(): RuleDefinition
{
return new RuleDefinition('Finalize every class that has no children', [

View File

@ -9,6 +9,7 @@ use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\Property;
use PHPStan\Type\ObjectType;
use Rector\Core\NodeAnalyzer\ClassAnalyzer;
use Rector\Core\Rector\AbstractRector;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\VendorLocker\NodeVendorLocker\PropertyVisibilityVendorLockResolver;
@ -41,14 +42,22 @@ final class PrivatizeLocalPropertyToPrivatePropertyRector extends AbstractRector
*/
private $excludedObjectTypes = [];
public function __construct(PropertyVisibilityVendorLockResolver $propertyVisibilityVendorLockResolver)
{
/**
* @var ClassAnalyzer
*/
private $classAnalyzer;
public function __construct(
PropertyVisibilityVendorLockResolver $propertyVisibilityVendorLockResolver,
ClassAnalyzer $classAnalyzer
) {
$this->propertyVisibilityVendorLockResolver = $propertyVisibilityVendorLockResolver;
$this->excludedObjectTypes = [
new ObjectType('PHPUnit\Framework\TestCase'),
new ObjectType('PHP_CodeSniffer\Sniffs\Sniff'),
];
$this->classAnalyzer = $classAnalyzer;
}
public function getRuleDefinition(): RuleDefinition

View File

@ -7,6 +7,7 @@ namespace Rector\Transform\Rector\Class_;
use PhpParser\Node;
use PhpParser\Node\Expr\StaticPropertyFetch;
use PhpParser\Node\Stmt\Class_;
use Rector\Core\NodeAnalyzer\ClassAnalyzer;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\ValueObject\MethodName;
use Rector\Transform\NodeAnalyzer\SingletonClassMethodAnalyzer;
@ -27,9 +28,17 @@ final class ChangeSingletonToServiceRector extends AbstractRector
*/
private $singletonClassMethodAnalyzer;
public function __construct(SingletonClassMethodAnalyzer $singletonClassMethodAnalyzer)
{
/**
* @var ClassAnalyzer
*/
private $classAnalyzer;
public function __construct(
SingletonClassMethodAnalyzer $singletonClassMethodAnalyzer,
ClassAnalyzer $classAnalyzer
) {
$this->singletonClassMethodAnalyzer = $singletonClassMethodAnalyzer;
$this->classAnalyzer = $classAnalyzer;
}
public function getRuleDefinition(): RuleDefinition

View File

@ -7,6 +7,7 @@ namespace Rector\Transform\Rector\Class_;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\NodeAnalyzer\ClassAnalyzer;
use Rector\Core\NodeManipulator\ClassInsertManipulator;
use Rector\Core\Rector\AbstractRector;
use Rector\Transform\ValueObject\ParentClassToTraits;
@ -38,9 +39,15 @@ final class ParentClassToTraitsRector extends AbstractRector implements Configur
*/
private $classInsertManipulator;
public function __construct(ClassInsertManipulator $classInsertManipulator)
/**
* @var ClassAnalyzer
*/
private $classAnalyzer;
public function __construct(ClassInsertManipulator $classInsertManipulator, ClassAnalyzer $classAnalyzer)
{
$this->classInsertManipulator = $classInsertManipulator;
$this->classAnalyzer = $classAnalyzer;
}
public function getRuleDefinition(): RuleDefinition

View File

@ -13,6 +13,7 @@ use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassLike;
use PHPStan\Type\ObjectType;
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
use Rector\Core\NodeAnalyzer\ClassAnalyzer;
use Rector\Core\Rector\AbstractRector;
use Rector\Naming\Naming\PropertyNaming;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -41,9 +42,15 @@ final class ServiceGetterToConstructorInjectionRector extends AbstractRector imp
*/
private $propertyNaming;
public function __construct(PropertyNaming $propertyNaming)
/**
* @var ClassAnalyzer
*/
private $classAnalyzer;
public function __construct(PropertyNaming $propertyNaming, ClassAnalyzer $classAnalyzer)
{
$this->propertyNaming = $propertyNaming;
$this->classAnalyzer = $classAnalyzer;
}
public function getRuleDefinition(): RuleDefinition

View File

@ -0,0 +1,54 @@
<?php
declare(strict_types=1);
namespace Rector\Core\NodeAnalyzer;
use PhpParser\Node;
use PhpParser\Node\Name;
use PhpParser\Node\Scalar\Encapsed;
use Rector\Core\PhpParser\Comparing\NodeComparator;
use Rector\NodeTypeResolver\Node\AttributeKey;
final class ChangedNodeAnalyzer
{
/**
* @var NodeComparator
*/
private $nodeComparator;
public function __construct(NodeComparator $nodeComparator)
{
$this->nodeComparator = $nodeComparator;
}
public function hasNodeChanged(Node $originalNode, Node $node): bool
{
if ($this->isNameIdentical($node, $originalNode)) {
return false;
}
// @see https://github.com/rectorphp/rector/issues/6169 - special check, as php-parser skips brackets
if ($node instanceof Encapsed) {
foreach ($node->parts as $encapsedPart) {
$originalEncapsedPart = $encapsedPart->getAttribute(AttributeKey::ORIGINAL_NODE);
if ($originalEncapsedPart === null) {
return true;
}
}
}
return ! $this->nodeComparator->areNodesEqual($originalNode, $node);
}
private function isNameIdentical(Node $node, Node $originalNode): bool
{
if (! $originalNode instanceof Name) {
return false;
}
// names are the same
$originalName = $originalNode->getAttribute(AttributeKey::ORIGINAL_NAME);
return $this->nodeComparator->areNodesEqual($originalName, $node);
}
}

View File

@ -28,7 +28,7 @@ use Rector\Core\Contract\Rector\PhpRectorInterface;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\Exclusion\ExclusionManager;
use Rector\Core\Logging\CurrentRectorProvider;
use Rector\Core\NodeAnalyzer\ClassAnalyzer;
use Rector\Core\NodeAnalyzer\ChangedNodeAnalyzer;
use Rector\Core\Php\PhpVersionProvider;
use Rector\Core\PhpParser\Comparing\NodeComparator;
use Rector\Core\PhpParser\Node\BetterNodeFinder;
@ -62,7 +62,6 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
* @var string[]
*/
private const ATTRIBUTES_TO_MIRROR = [
AttributeKey::PARENT_NODE,
AttributeKey::CLASS_NODE,
AttributeKey::CLASS_NAME,
AttributeKey::METHOD_NODE,
@ -136,11 +135,6 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
*/
protected $betterNodeFinder;
/**
* @var ClassAnalyzer
*/
protected $classAnalyzer;
/**
* @var NodeRemover
*/
@ -216,6 +210,11 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
*/
private $currentFileProvider;
/**
* @var ChangedNodeAnalyzer
*/
private $changedNodeAnalyzer;
/**
* @required
*/
@ -239,14 +238,14 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
StaticTypeMapper $staticTypeMapper,
ParameterProvider $parameterProvider,
CurrentRectorProvider $currentRectorProvider,
ClassAnalyzer $classAnalyzer,
CurrentNodeProvider $currentNodeProvider,
Skipper $skipper,
ValueResolver $valueResolver,
NodeRepository $nodeRepository,
BetterNodeFinder $betterNodeFinder,
NodeComparator $nodeComparator,
CurrentFileProvider $currentFileProvider
CurrentFileProvider $currentFileProvider,
ChangedNodeAnalyzer $changedNodeAnalyzer
): void {
$this->nodesToRemoveCollector = $nodesToRemoveCollector;
$this->nodesToAddCollector = $nodesToAddCollector;
@ -267,7 +266,6 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
$this->staticTypeMapper = $staticTypeMapper;
$this->parameterProvider = $parameterProvider;
$this->currentRectorProvider = $currentRectorProvider;
$this->classAnalyzer = $classAnalyzer;
$this->currentNodeProvider = $currentNodeProvider;
$this->skipper = $skipper;
$this->valueResolver = $valueResolver;
@ -275,6 +273,7 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
$this->betterNodeFinder = $betterNodeFinder;
$this->nodeComparator = $nodeComparator;
$this->currentFileProvider = $currentFileProvider;
$this->changedNodeAnalyzer = $changedNodeAnalyzer;
}
/**
@ -327,9 +326,7 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
}
// changed!
if ($this->hasNodeChanged($originalNode, $node)) {
$this->updateAttributes($node);
if ($this->changedNodeAnalyzer->hasNodeChanged($originalNode, $node)) {
$rectorWithLineChange = new RectorWithLineChange($this, $node->getLine());
$this->file->addRectorClassWithLine($rectorWithLineChange);
@ -438,17 +435,17 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
}
/**
* @param Arg[] $newArgs
* @param Arg[] $currentArgs
* @param Arg[] $appendingArgs
* @return Arg[]
*/
protected function appendArgs(array $newArgs, array $appendingArgs): array
protected function appendArgs(array $currentArgs, array $appendingArgs): array
{
foreach ($appendingArgs as $appendingArg) {
$newArgs[] = new Arg($appendingArg->value);
$currentArgs[] = new Arg($appendingArg->value);
}
return $newArgs;
return $currentArgs;
}
protected function unwrapExpression(Stmt $stmt): Node
@ -560,20 +557,15 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
$this->previousAppliedClass = static::class;
}
private function hasNodeChanged(Node $originalNode, Node $node): bool
{
if ($this->isNameIdentical($node, $originalNode)) {
return false;
}
return ! $this->nodeComparator->areNodesEqual($originalNode, $node);
}
/**
* @param array<string, mixed> $originalAttributes
*/
private function mirrorAttributes(array $originalAttributes, Node $newNode): void
{
if ($newNode instanceof Name) {
$newNode->setAttribute(AttributeKey::RESOLVED_NAME, $newNode->toString());
}
foreach ($originalAttributes as $attributeName => $oldAttributeValue) {
if (! in_array($attributeName, self::ATTRIBUTES_TO_MIRROR, true)) {
continue;
@ -583,24 +575,6 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
}
}
private function updateAttributes(Node $node): void
{
// update Resolved name attribute if name is changed
if ($node instanceof Name) {
$node->setAttribute(AttributeKey::RESOLVED_NAME, $node->toString());
}
}
private function isNameIdentical(Node $node, Node $originalNode): bool
{
if (! $originalNode instanceof Name) {
return false;
}
// names are the same
return $this->nodeComparator->areNodesEqual($originalNode->getAttribute(AttributeKey::ORIGINAL_NAME), $node);
}
private function connectParentNodes(Node $node): void
{
$nodeTraverser = new NodeTraverser();