Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config/set/dead-code/dead-code.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ services:
Rector\DeadCode\Rector\Instanceof_\RemoveDuplicatedInstanceOfRector: ~
Rector\DeadCode\Rector\Switch_\RemoveDuplicatedCaseInSwitchRector: ~
Rector\DeadCode\Rector\Class_\RemoveUnusedDoctrineEntityMethodAndPropertyRector: ~
Rector\DeadCode\Rector\Class_\RemoveSetterOnlyPropertyAndMethodCallRector: ~
7 changes: 0 additions & 7 deletions packages/Architecture/src/Cleaner/ClassMethodCleaner.php

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,6 @@ final class Attribute
*/
public const HAS_DESCRIPTION_WITH_ORIGINAL_SPACES = 'has_description_with_restored_spaces';

/**
* Fully-qualified name
*
* @var string
*/
public const FQN_NAME = 'fqn_name';

/**
* @var string
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ private function createInArrayFunction(Node $node, BinaryOp $binaryOp, Foreach_
*/
private function combineCommentsToNode(Node $originalNode, Node $newNode): void
{
$this->traverseNodesWithCallable([$originalNode], function (Node $node): void {
$this->traverseNodesWithCallable($originalNode, function (Node $node): void {
if ($node->hasAttribute('comments')) {
$this->comments = array_merge($this->comments, $node->getComments());
}
Expand Down
2 changes: 1 addition & 1 deletion packages/CodingStyle/src/Node/ConcatManipulator.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public function removeFirstItemFromConcat(Concat $concat): Node
$newConcat = clone $concat;
$firstConcatItem = $this->getFirstConcatItem($concat);

$this->callableNodeTraverser->traverseNodesWithCallable([$newConcat], function (Node $node) use (
$this->callableNodeTraverser->traverseNodesWithCallable($newConcat, function (Node $node) use (
$firstConcatItem
): ?Expr {
if (! $node instanceof Concat) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Rector\RectorDefinition\RectorDefinition;

/**
* @sponsor Thanks https://spaceflow.io/ for sponsoring this rule - visit them on https://github.com/SpaceFlow-app
* @see \Rector\CodingStyle\Tests\Rector\String_\ManualJsonStringToJsonEncodeArrayRector\ManualJsonStringToJsonEncodeArrayRectorTest
*/
final class ManualJsonStringToJsonEncodeArrayRector extends AbstractRector
Expand Down Expand Up @@ -190,7 +191,7 @@ private function createAndReturnJsonEncodeFromArray(Assign $assign, Array_ $json
private function replaceNodeObjectHashPlaceholdersWithNodes(Array_ $array, array $placeholderNodes): void
{
// traverse and replace placeholdes by original nodes
$this->traverseNodesWithCallable([$array], function (Node $node) use ($placeholderNodes): ?Expr {
$this->traverseNodesWithCallable($array, function (Node $node) use ($placeholderNodes): ?Expr {
if (! $node instanceof String_) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ private function resolveTraitUseNames(Node $searchNode): void

private function resolveDocPossibleAliases(Node $searchNode): void
{
$this->traverseNodesWithCallable([$searchNode], function (Node $node): void {
$this->traverseNodesWithCallable($searchNode, function (Node $node): void {
if ($node->getDocComment() === null) {
return;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
<?php declare(strict_types=1);

namespace Rector\DeadCode\Rector\Class_;

use PhpParser\Node;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use Rector\NodeContainer\ParsedNodesByType;
use Rector\PhpParser\Node\Manipulator\ClassManipulator;
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;

/**
* @sponsor Thanks https://spaceflow.io/ for sponsoring this rule - visit them on https://github.com/SpaceFlow-app
* @see \Rector\DeadCode\Tests\Rector\Class_\RemoveSetterOnlyPropertyAndMethodCallRector\RemoveSetterOnlyPropertyAndMethodCallRectorTest
*/
final class RemoveSetterOnlyPropertyAndMethodCallRector extends AbstractRector
{
/**
* @var ClassManipulator
*/
private $classManipulator;

/**
* @var ParsedNodesByType
*/
private $parsedNodesByType;

/**
* @var string[]
*/
private $methodCallNamesToBeRemoved = [];

public function __construct(ClassManipulator $classManipulator, ParsedNodesByType $parsedNodesByType)
{
$this->classManipulator = $classManipulator;
$this->parsedNodesByType = $parsedNodesByType;
}

public function getDefinition(): RectorDefinition
{
return new RectorDefinition('Removes method that set values that are never used', [
new CodeSample(
<<<'CODE_SAMPLE'
class SomeClass
{
private $name;

public function setName($name)
{
$this->name = $name;
}
}

class ActiveOnlySetter
{
public function run()
{
$someClass = new SomeClass();
$someClass->setName('Tom');
}
}
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
class SomeClass
{
}

class ActiveOnlySetter
{
public function run()
{
$someClass = new SomeClass();
}
}
CODE_SAMPLE
),
]);
}

/**
* @return string[]
*/
public function getNodeTypes(): array
{
return [Class_::class];
}

/**
* @param Class_ $node
*/
public function refactor(Node $node): ?Node
{
$this->methodCallNamesToBeRemoved = [];

// 1. get assign only private properties
$assignOnlyPrivatePropertyNames = $this->classManipulator->getAssignOnlyPrivatePropertyNames($node);
$this->classManipulator->removeProperties($node, $assignOnlyPrivatePropertyNames);

// 2. remove assigns + class methods with only setter assign
$this->removePropertyAssigns($node, $assignOnlyPrivatePropertyNames);

// 3. remove setter method calls
$this->removeSetterMethodCalls($node);

return $node;
}

/**
* @param string[] $assignOnlyPrivatePropertyNames
*/
private function removePropertyAssigns(Class_ $class, array $assignOnlyPrivatePropertyNames): void
{
$this->traverseNodesWithCallable($class, function (Node $node) use ($assignOnlyPrivatePropertyNames): void {
if ($this->isClassMethodWithSinglePropertyAssignOfNames($node, $assignOnlyPrivatePropertyNames)) {
/** @var string $classMethodName */
$classMethodName = $this->getName($node);
$this->methodCallNamesToBeRemoved[] = $classMethodName;

$this->removeNode($node);
return;
}

if ($this->isPropertyAssignWithPropertyNames($node, $assignOnlyPrivatePropertyNames)) {
$this->removeNode($node);
}
});
}

private function removeSetterMethodCalls(Node $node): void
{
/** @var string $className */
$className = $this->getName($node);
$methodCallsByMethodName = $this->parsedNodesByType->findMethodCallsOnClass($className);

/** @var string $methodName */
foreach ($methodCallsByMethodName as $methodName => $classMethodCalls) {
if (! in_array($methodName, $this->methodCallNamesToBeRemoved, true)) {
continue;
}

foreach ($classMethodCalls as $classMethodCall) {
$this->removeNode($classMethodCall);
}
}
}

/**
* Looks for:
*
* public function <someMethod>($value)
* {
* $this->value = $value
* }
*
* @param string[] $propertyNames
*/
private function isClassMethodWithSinglePropertyAssignOfNames(Node $node, array $propertyNames): bool
{
if (! $node instanceof ClassMethod) {
return false;
}

if ($this->isName($node, '__construct')) {
return false;
}

if (count((array) $node->stmts) !== 1) {
return false;
}

if (! $node->stmts[0] instanceof Expression) {
return false;
}

/** @var Expression $onlyExpression */
$onlyExpression = $node->stmts[0];

$onlyStmt = $onlyExpression->expr;

return $this->isPropertyAssignWithPropertyNames($onlyStmt, $propertyNames);
}

/**
* Is: "$this->value = <$value>"
*
* @param string[] $propertyNames
*/
private function isPropertyAssignWithPropertyNames(Node $node, array $propertyNames): bool
{
if (! $node instanceof Assign) {
return false;
}

if (! $node->var instanceof PropertyFetch) {
return false;
}

$propertyFetch = $node->var;
if (! $this->isName($propertyFetch->var, 'this')) {
return false;
}

return $this->isNames($propertyFetch->name, $propertyNames);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Rector\RectorDefinition\RectorDefinition;

/**
* @sponsor Thanks https://spaceflow.io/ for sponsoring this rule - visit them on https://github.com/SpaceFlow-app
* @see \Rector\DeadCode\Tests\Rector\Class_\RemoveUnusedDoctrineEntityMethodAndPropertyRector\RemoveUnusedDoctrineEntityMethodAndPropertyRectorTest
*/
final class RemoveUnusedDoctrineEntityMethodAndPropertyRector extends AbstractRector
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

namespace Rector\DeadCode\Tests\Rector\Class_\RemoveSetterOnlyPropertyAndMethodCallRector\Fixture;

class SomeClass
{
private $name;

public function setName($name)
{
$this->name = $name;
}
}

class ActiveOnlySetter
{
public function run()
{
$someClass = new SomeClass();
$someClass->setName('Tom');
}
}

?>
-----
<?php

namespace Rector\DeadCode\Tests\Rector\Class_\RemoveSetterOnlyPropertyAndMethodCallRector\Fixture;

class SomeClass
{
}

class ActiveOnlySetter
{
public function run()
{
$someClass = new SomeClass();
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Rector\DeadCode\Tests\Rector\Class_\RemoveSetterOnlyPropertyAndMethodCallRector\Fixture;

class InConstructor
{
private $name;

public function __construct($name)
{
$this->name = $name;
}
}

?>
-----
<?php

namespace Rector\DeadCode\Tests\Rector\Class_\RemoveSetterOnlyPropertyAndMethodCallRector\Fixture;

class InConstructor
{
public function __construct($name)
{
}
}

?>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace Rector\DeadCode\Tests\Rector\Class_\RemoveSetterOnlyPropertyAndMethodCallRector\Fixture;

class KeepPublicProperty
{
public $application;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Rector\DeadCode\Tests\Rector\Class_\RemoveSetterOnlyPropertyAndMethodCallRector\Fixture;

use JMS\Serializer\Annotation as Serializer;

final class KeepSerialiazableObject
{
/**
* @var string
* @Serializer\Type("string")
*/
private $id;

public function __construct(string $id)
{
$this->id = $id;
}
}
Loading