mirror of
https://github.com/rectorphp/rector.git
synced 2025-02-21 01:41:00 +01:00
191 lines
4.7 KiB
PHP
191 lines
4.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Rector\Privatization\NodeManipulator;
|
|
|
|
use PhpParser\Node;
|
|
use PhpParser\Node\Stmt;
|
|
use PhpParser\Node\Stmt\Class_;
|
|
use PhpParser\Node\Stmt\ClassConst;
|
|
use PhpParser\Node\Stmt\ClassMethod;
|
|
use PhpParser\Node\Stmt\Property;
|
|
use Rector\Core\Exception\InvalidNodeTypeException;
|
|
use Rector\Core\ValueObject\Visibility;
|
|
use Webmozart\Assert\Assert;
|
|
|
|
final class VisibilityManipulator
|
|
{
|
|
/**
|
|
* @var array<class-string<Stmt>>
|
|
*/
|
|
private const ALLOWED_NODE_TYPES = [ClassMethod::class, Property::class, ClassConst::class, Class_::class];
|
|
|
|
/**
|
|
* @param ClassMethod|Property|ClassConst $node
|
|
*/
|
|
public function makeStatic(Node $node): void
|
|
{
|
|
$this->addVisibilityFlag($node, Visibility::STATIC);
|
|
}
|
|
|
|
/**
|
|
* @param ClassMethod|Class_ $node
|
|
*/
|
|
public function makeAbstract(Node $node): void
|
|
{
|
|
$this->addVisibilityFlag($node, Visibility::ABSTRACT);
|
|
}
|
|
|
|
/**
|
|
* @param ClassMethod|Property $node
|
|
*/
|
|
public function makeNonStatic(Node $node): void
|
|
{
|
|
if (! $node->isStatic()) {
|
|
return;
|
|
}
|
|
|
|
$node->flags -= Class_::MODIFIER_STATIC;
|
|
}
|
|
|
|
/**
|
|
* @param Class_|ClassMethod $node
|
|
*/
|
|
public function makeFinal(Node $node): void
|
|
{
|
|
$this->addVisibilityFlag($node, Visibility::FINAL);
|
|
}
|
|
|
|
/**
|
|
* @param Class_|ClassMethod $node
|
|
*/
|
|
public function makeNonFinal(Node $node): void
|
|
{
|
|
if (! $node->isFinal()) {
|
|
return;
|
|
}
|
|
|
|
$node->flags -= Class_::MODIFIER_FINAL;
|
|
}
|
|
|
|
/**
|
|
* This way "abstract", "static", "final" are kept
|
|
*
|
|
* @param ClassMethod|Property|ClassConst $node
|
|
*/
|
|
public function removeVisibility(Node $node): void
|
|
{
|
|
$this->ensureIsClassMethodOrProperty($node, __METHOD__);
|
|
|
|
// no modifier
|
|
if ($node->flags === 0) {
|
|
return;
|
|
}
|
|
|
|
if ($node->isPublic()) {
|
|
$node->flags -= Class_::MODIFIER_PUBLIC;
|
|
}
|
|
|
|
if ($node->isProtected()) {
|
|
$node->flags -= Class_::MODIFIER_PROTECTED;
|
|
}
|
|
|
|
if ($node->isPrivate()) {
|
|
$node->flags -= Class_::MODIFIER_PRIVATE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param ClassMethod|Property|ClassConst $node
|
|
*/
|
|
public function changeNodeVisibility(Node $node, int $visibility): void
|
|
{
|
|
Assert::oneOf($visibility, [
|
|
Visibility::PUBLIC,
|
|
Visibility::PROTECTED,
|
|
Visibility::PRIVATE,
|
|
Visibility::STATIC,
|
|
Visibility::ABSTRACT,
|
|
Visibility::FINAL,
|
|
]);
|
|
|
|
$this->replaceVisibilityFlag($node, $visibility);
|
|
}
|
|
|
|
/**
|
|
* @param ClassMethod|Property|ClassConst $node
|
|
*/
|
|
public function makePublic(Node $node): void
|
|
{
|
|
$this->replaceVisibilityFlag($node, Visibility::PUBLIC);
|
|
}
|
|
|
|
/**
|
|
* @param ClassMethod|Property|ClassConst $node
|
|
*/
|
|
public function makeProtected(Node $node): void
|
|
{
|
|
$this->replaceVisibilityFlag($node, Visibility::PROTECTED);
|
|
}
|
|
|
|
/**
|
|
* @param ClassMethod|Property|ClassConst $node
|
|
*/
|
|
public function makePrivate(Node $node): void
|
|
{
|
|
$this->replaceVisibilityFlag($node, Visibility::PRIVATE);
|
|
}
|
|
|
|
public function removeFinal(Class_ $class): void
|
|
{
|
|
$class->flags -= Class_::MODIFIER_FINAL;
|
|
}
|
|
|
|
/**
|
|
* @param Class_|ClassMethod|Property|ClassConst $node
|
|
*/
|
|
private function addVisibilityFlag(Node $node, int $visibility): void
|
|
{
|
|
$this->ensureIsClassMethodOrProperty($node, __METHOD__);
|
|
$node->flags |= $visibility;
|
|
}
|
|
|
|
private function ensureIsClassMethodOrProperty(Node $node, string $location): void
|
|
{
|
|
foreach (self::ALLOWED_NODE_TYPES as $allowedNodeType) {
|
|
if (is_a($node, $allowedNodeType, true)) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
throw new InvalidNodeTypeException(sprintf(
|
|
'"%s" only accepts "%s" types. "%s" given.',
|
|
$location,
|
|
implode('", "', self::ALLOWED_NODE_TYPES),
|
|
get_class($node)
|
|
));
|
|
}
|
|
|
|
/**
|
|
* @param ClassMethod|Property|ClassConst $node
|
|
*/
|
|
private function replaceVisibilityFlag(Node $node, int $visibility): void
|
|
{
|
|
$isStatic = $node instanceof ClassMethod && $node->isStatic();
|
|
if ($isStatic) {
|
|
$this->removeVisibility($node);
|
|
}
|
|
|
|
if ($visibility !== Visibility::STATIC && $visibility !== Visibility::ABSTRACT && $visibility !== Visibility::FINAL) {
|
|
$this->removeVisibility($node);
|
|
}
|
|
|
|
$this->addVisibilityFlag($node, $visibility);
|
|
|
|
if ($isStatic) {
|
|
$this->makeStatic($node);
|
|
}
|
|
}
|
|
}
|