mirror of
https://github.com/rectorphp/rector.git
synced 2025-01-18 22:08:00 +01:00
[PHP] Add ReservedObjectRector
This commit is contained in:
parent
0c65b0e09a
commit
2ffb04a229
@ -1,2 +1,5 @@
|
||||
services:
|
||||
Rector\Php\Rector\BinaryOp\IsIterableRector: ~
|
||||
Rector\Php\Rector\Name\ReservedObjectRector:
|
||||
$reservedKeywordsToReplacements:
|
||||
Object: 'BaseObject'
|
||||
|
110
packages/Php/src/Rector/Name/ReservedObjectRector.php
Normal file
110
packages/Php/src/Rector/Name/ReservedObjectRector.php
Normal file
@ -0,0 +1,110 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Php\Rector\Name;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Stmt\Namespace_;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
use Rector\RectorDefinition\RectorDefinition;
|
||||
|
||||
/**
|
||||
* @see https://wiki.php.net/rfc/object-typehint
|
||||
*
|
||||
* @see https://github.com/cebe/yii2/commit/9548a212ecf6e50fcdb0e5ba6daad88019cfc544
|
||||
*/
|
||||
final class ReservedObjectRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $reservedKeywordsToReplacements = [];
|
||||
|
||||
/**
|
||||
* @param string[] $reservedKeywordsToReplacements
|
||||
*/
|
||||
public function __construct(array $reservedKeywordsToReplacements)
|
||||
{
|
||||
$this->reservedKeywordsToReplacements = $reservedKeywordsToReplacements;
|
||||
}
|
||||
|
||||
public function getDefinition(): RectorDefinition
|
||||
{
|
||||
return new RectorDefinition(
|
||||
'Changes reserved "Object" name to "<Smart>Object" where <Smart> can be configured',
|
||||
[
|
||||
new CodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
class Object
|
||||
{
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
<<<'CODE_SAMPLE'
|
||||
class SmartObject
|
||||
{
|
||||
}
|
||||
CODE_SAMPLE
|
||||
),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [Identifier::class, Name::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Identifier|Name $node
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
if ($node instanceof Identifier) {
|
||||
return $this->processIdentifier($node);
|
||||
}
|
||||
|
||||
if ($node instanceof Name) {
|
||||
return $this->processName($node);
|
||||
}
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
private function processIdentifier(Identifier $identifierNode): Identifier
|
||||
{
|
||||
foreach ($this->reservedKeywordsToReplacements as $reservedKeyword => $replacement) {
|
||||
if (strtolower($identifierNode->name) === strtolower($reservedKeyword)) {
|
||||
$identifierNode->name = $replacement;
|
||||
}
|
||||
}
|
||||
|
||||
return $identifierNode;
|
||||
}
|
||||
|
||||
private function processName(Name $nameNode): Name
|
||||
{
|
||||
// we look for "extends <Name>"
|
||||
$parentNode = $nameNode->getAttribute(Attribute::PARENT_NODE);
|
||||
// "Object" can part of namespace name
|
||||
if ($parentNode instanceof Namespace_) {
|
||||
return $nameNode;
|
||||
}
|
||||
|
||||
// process lass part
|
||||
foreach ($this->reservedKeywordsToReplacements as $reservedKeyword => $replacement) {
|
||||
if (strtolower($nameNode->getLast()) === strtolower($reservedKeyword)) {
|
||||
$nameNode->parts[count($nameNode->parts) - 1] = $replacement;
|
||||
$nameNode->setAttribute(Attribute::ORIGINAL_NODE, null);
|
||||
}
|
||||
}
|
||||
|
||||
return $nameNode;
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Php\Tests\Rector\Name\ReservedObjectRector\Wrong;
|
||||
|
||||
class SmartObject
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
class ChildObject extends \Rector\Php\Tests\Rector\Name\ReservedObjectRector\Wrong\SmartObject
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
$some = new ChildObject();
|
||||
if ($some instanceof \Rector\Php\Tests\Rector\Name\ReservedObjectRector\Wrong\SmartObject) {
|
||||
return;
|
||||
}
|
||||
|
||||
is_subclass_of($some, \Rector\Php\Tests\Rector\Name\ReservedObjectRector\Wrong\SmartObject::class);
|
||||
|
||||
is_a($some, \Rector\Php\Tests\Rector\Name\ReservedObjectRector\Wrong\SmartObject::class);
|
||||
|
||||
function someFunction(\Rector\Php\Tests\Rector\Name\ReservedObjectRector\Wrong\SmartObject $reservedObject): \Rector\Php\Tests\Rector\Name\ReservedObjectRector\Wrong\SmartObject {
|
||||
return $reservedObject;
|
||||
}
|
||||
|
||||
$someObject = new \Rector\Php\Tests\Rector\Name\ReservedObjectRector\Wrong\SmartObject;
|
@ -0,0 +1,31 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Php\Tests\Rector\Name\ReservedObjectRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
|
||||
/**
|
||||
* @covers \Rector\Php\Rector\Name\ReservedObjectRector
|
||||
*/
|
||||
final class ReservedObjectRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideWrongToFixedFiles()
|
||||
*/
|
||||
public function test(string $wrong, string $fixed): void
|
||||
{
|
||||
$this->doTestFileMatchesExpectedContent($wrong, $fixed);
|
||||
}
|
||||
|
||||
public function provideWrongToFixedFiles(): Iterator
|
||||
{
|
||||
// it needs to have different name, since in PHP 7.1 it already reserved
|
||||
yield [__DIR__ . '/Wrong/ReservedObject.php', __DIR__ . '/Correct/correct.php.inc'];
|
||||
}
|
||||
|
||||
protected function provideConfig(): string
|
||||
{
|
||||
return __DIR__ . '/config.yml';
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Php\Tests\Rector\Name\ReservedObjectRector\Wrong;
|
||||
|
||||
class ReservedObject
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
class ChildObject extends ReservedObject
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
$some = new ChildObject();
|
||||
if ($some instanceof ReservedObject) {
|
||||
return;
|
||||
}
|
||||
|
||||
is_subclass_of($some, ReservedObject::class);
|
||||
|
||||
is_a($some, ReservedObject::class);
|
||||
|
||||
function someFunction(ReservedObject $reservedObject): ReservedObject {
|
||||
return $reservedObject;
|
||||
}
|
||||
|
||||
$someObject = new ReservedObject;
|
@ -0,0 +1,5 @@
|
||||
services:
|
||||
Rector\Php\Rector\Name\ReservedObjectRector:
|
||||
# todo make work even without these explicit variables
|
||||
$reservedKeywordsToReplacements:
|
||||
'ReservedObject': 'SmartObject'
|
Loading…
x
Reference in New Issue
Block a user