mirror of
https://github.com/rectorphp/rector.git
synced 2024-05-31 16:30:51 +00:00
[Removing] Add RemoveNamespaceRector (#2013)
Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
parent
08a3243799
commit
be530c5e2f
|
@ -1,4 +1,4 @@
|
|||
# 508 Rules Overview
|
||||
# 509 Rules Overview
|
||||
|
||||
<br>
|
||||
|
||||
|
@ -76,7 +76,7 @@
|
|||
|
||||
- [Privatization](#privatization) (10)
|
||||
|
||||
- [Removing](#removing) (6)
|
||||
- [Removing](#removing) (7)
|
||||
|
||||
- [RemovingStatic](#removingstatic) (1)
|
||||
|
||||
|
@ -9160,6 +9160,37 @@ return static function (ContainerConfigurator $containerConfigurator): void {
|
|||
|
||||
<br>
|
||||
|
||||
### RemoveNamespaceRector
|
||||
|
||||
Remove namespace by configured namespace names
|
||||
|
||||
:wrench: **configure it!**
|
||||
|
||||
- class: [`Rector\Removing\Rector\Namespace_\RemoveNamespaceRector`](../rules/Removing/Rector/Namespace_/RemoveNamespaceRector.php)
|
||||
|
||||
```php
|
||||
use Rector\Removing\Rector\Namespace_\RemoveNamespaceRector;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
|
||||
$services->set(RemoveNamespaceRector::class)
|
||||
->configure(['App']);
|
||||
};
|
||||
```
|
||||
|
||||
↓
|
||||
|
||||
```diff
|
||||
-namespace App;
|
||||
class SomeClass
|
||||
{
|
||||
}
|
||||
```
|
||||
|
||||
<br>
|
||||
|
||||
### RemoveParentRector
|
||||
|
||||
Removes extends class by name
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
class Fixture
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
class Fixture
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace App
|
||||
{
|
||||
class HasNextNamespace
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
echo 'test';
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace {
|
||||
class HasNextNamespace
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
echo 'test';
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace App
|
||||
{
|
||||
use stdClass;
|
||||
class HasNextNamespaceNonCompount
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
echo 'test';
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace {
|
||||
class HasNextNamespaceNonCompount
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
echo 'test';
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace
|
||||
{
|
||||
echo 'test';
|
||||
}
|
||||
|
||||
namespace App
|
||||
{
|
||||
class HasPrevNamespace
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
namespace
|
||||
{
|
||||
echo 'test';
|
||||
}
|
||||
|
||||
namespace {
|
||||
class HasPrevNamespace
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use A\B\C, stdClass, D\E\F;
|
||||
|
||||
class RemoveNamespaceCombineCompountNonCompount
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
use A\B\C, D\E\F;
|
||||
class RemoveNamespaceCombineCompountNonCompount
|
||||
{
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use A\B\C;
|
||||
|
||||
class RemoveNamespaceUseCompountuse
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
use A\B\C;
|
||||
class RemoveNamespaceUseCompountuse
|
||||
{
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use stdClass;
|
||||
|
||||
class RemoveNamespaceUseNonCompountuse
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
class RemoveNamespaceUseNonCompountuse
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace App;
|
||||
|
||||
use stdClass as std;
|
||||
|
||||
class RemoveNamespaceUseNonCompountuseWithAlias
|
||||
{
|
||||
}
|
||||
|
||||
?>
|
||||
-----
|
||||
<?php
|
||||
|
||||
use stdClass as std;
|
||||
class RemoveNamespaceUseNonCompountuseWithAlias
|
||||
{
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
namespace DifferentNamespace;
|
||||
|
||||
class SkipDifferentNamespace
|
||||
{
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
<?php
|
||||
|
||||
class NoNamespace{}
|
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
namespace
|
||||
{
|
||||
class NullNamespace
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Tests\Removing\Rector\Namespace_\RemoveNamespaceRector;
|
||||
|
||||
use Iterator;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
use Symplify\SmartFileSystem\SmartFileInfo;
|
||||
|
||||
final class RemoveNamespaceRectorTest extends AbstractRectorTestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider provideData()
|
||||
*/
|
||||
public function test(SmartFileInfo $fileInfo): void
|
||||
{
|
||||
$this->doTestFileInfo($fileInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Iterator<SmartFileInfo>
|
||||
*/
|
||||
public function provideData(): Iterator
|
||||
{
|
||||
return $this->yieldFilesFromDirectory(__DIR__ . '/Fixture');
|
||||
}
|
||||
|
||||
public function provideConfigFilePath(): string
|
||||
{
|
||||
return __DIR__ . '/config/configured_rule.php';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Rector\Removing\Rector\Namespace_\RemoveNamespaceRector;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
|
||||
|
||||
return static function (ContainerConfigurator $containerConfigurator): void {
|
||||
$services = $containerConfigurator->services();
|
||||
$services->set(RemoveNamespaceRector::class)
|
||||
->configure(['App']);
|
||||
};
|
155
rules/Removing/Rector/Namespace_/RemoveNamespaceRector.php
Normal file
155
rules/Removing/Rector/Namespace_/RemoveNamespaceRector.php
Normal file
|
@ -0,0 +1,155 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Rector\Removing\Rector\Namespace_;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Stmt;
|
||||
use PhpParser\Node\Stmt\Namespace_;
|
||||
use PhpParser\Node\Stmt\Use_;
|
||||
use Rector\Core\Contract\Rector\ConfigurableRectorInterface;
|
||||
use Rector\Core\Rector\AbstractRector;
|
||||
use Rector\NodeTypeResolver\Node\AttributeKey;
|
||||
use Symplify\RuleDocGenerator\ValueObject\CodeSample\ConfiguredCodeSample;
|
||||
use Symplify\RuleDocGenerator\ValueObject\RuleDefinition;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
/**
|
||||
* @see \Rector\Tests\Removing\Rector\Namespace_\RemoveNamespaceRector\RemoveNamespaceRectorTest
|
||||
*/
|
||||
final class RemoveNamespaceRector extends AbstractRector implements ConfigurableRectorInterface
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private array $removeNamespaces = [];
|
||||
|
||||
public function getRuleDefinition(): RuleDefinition
|
||||
{
|
||||
return new RuleDefinition('Remove namespace by configured namespace names', [
|
||||
new ConfiguredCodeSample(
|
||||
<<<'CODE_SAMPLE'
|
||||
namespace App;
|
||||
class SomeClass
|
||||
{
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
<<<'CODE_SAMPLE'
|
||||
class SomeClass
|
||||
{
|
||||
}
|
||||
CODE_SAMPLE
|
||||
,
|
||||
['App']
|
||||
),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<class-string<Node>>
|
||||
*/
|
||||
public function getNodeTypes(): array
|
||||
{
|
||||
return [Namespace_::class];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Namespace_ $node
|
||||
* @return Stmt[]|Node|null
|
||||
*/
|
||||
public function refactor(Node $node): array|Node|null
|
||||
{
|
||||
$namespaceName = $this->nodeNameResolver->getName($node);
|
||||
|
||||
if ($namespaceName === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
foreach ($this->removeNamespaces as $removeNamespace) {
|
||||
if ($removeNamespace !== $namespaceName) {
|
||||
continue;
|
||||
}
|
||||
|
||||
return $this->processRemoveNamespace($node);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $configuration
|
||||
*/
|
||||
public function configure(array $configuration): void
|
||||
{
|
||||
Assert::allString($configuration);
|
||||
$this->removeNamespaces = $configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Stmt[]|Namespace_
|
||||
*/
|
||||
private function processRemoveNamespace(Namespace_ $namespace): array|Namespace_
|
||||
{
|
||||
$stmts = $this->cleanNonCompoundUseName($namespace->stmts);
|
||||
|
||||
// has prev or next namespace should just clean namespace name to avoid error
|
||||
// `Namespace declaration statement has to be the very first statement` ref https://3v4l.org/qUMfb
|
||||
// or `No code may exist outside of namespace {}` ref https://3v4l.org/ct7SR
|
||||
if ($this->hasMultipleNamespaces($namespace)) {
|
||||
return new Namespace_(null, $stmts);
|
||||
}
|
||||
|
||||
if ($stmts === []) {
|
||||
$this->removeNode($namespace);
|
||||
return $namespace;
|
||||
}
|
||||
|
||||
return $stmts;
|
||||
}
|
||||
|
||||
private function hasMultipleNamespaces(Namespace_ $namespace): bool
|
||||
{
|
||||
$prev = $namespace->getAttribute(AttributeKey::PREVIOUS_STATEMENT);
|
||||
$next = $namespace->getAttribute(AttributeKey::NEXT_NODE);
|
||||
|
||||
return $prev instanceof Namespace_ || $next instanceof Namespace_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Stmt[] $stmts
|
||||
* @return Stmt[]
|
||||
*/
|
||||
private function cleanNonCompoundUseName(array $stmts): array
|
||||
{
|
||||
foreach ($stmts as $key => $stmt) {
|
||||
if (! $stmt instanceof Use_) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$uses = $stmt->uses;
|
||||
foreach ($uses as $keyUse => $use) {
|
||||
if ($use->alias instanceof Identifier) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$useName = ltrim($use->name->toString(), '\\');
|
||||
if (! str_contains($useName, '\\')) {
|
||||
unset($uses[$keyUse]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($uses === []) {
|
||||
unset($stmts[$key]);
|
||||
continue;
|
||||
}
|
||||
|
||||
$uses = array_values($uses);
|
||||
$stmt->uses = $uses;
|
||||
}
|
||||
|
||||
return $stmts;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user