mirror of
https://github.com/rectorphp/rector.git
synced 2024-05-31 16:30:51 +00:00
commit
3053b30783
|
@ -9,6 +9,7 @@ $possibleAutoloadPaths = [__DIR__ . '/../vendor/autoload.php', __DIR__ . '/../..
|
|||
foreach ($possibleAutoloadPaths as $possibleAutoloadPath) {
|
||||
if (is_file($possibleAutoloadPath)) {
|
||||
require_once $possibleAutoloadPath;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,14 +25,14 @@
|
|||
"psr-4": {
|
||||
"Rector\\": "src",
|
||||
"Rector\\NodeTypeResolver\\": "packages/NodeTypeResolver/src",
|
||||
"Rector\\TriggerExtractor\\": "packages/TriggerExtractor/src"
|
||||
"Rector\\DeprecationExtractor\\": "packages/DeprecationExtractor/src"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Rector\\Tests\\": "tests",
|
||||
"Rector\\NodeTypeResolver\\Tests\\": "packages/NodeTypeResolver/tests",
|
||||
"Rector\\TriggerExtractor\\Tests\\": "packages/TriggerExtractor/tests"
|
||||
"Rector\\DeprecationExtractor\\Tests\\": "packages/DeprecationExtractor/tests"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
|
|
|
@ -30,6 +30,7 @@ checkers:
|
|||
extraAllowedClasses:
|
||||
- 'PhpParser\Node\*'
|
||||
- 'PhpParser\Comment\Doc'
|
||||
- SplObjectStorage # temporary before adding to Symplify\CodingStandard package
|
||||
|
||||
parameters:
|
||||
exclude_checkers:
|
||||
|
@ -47,3 +48,6 @@ parameters:
|
|||
PHP_CodeSniffer\Standards\Generic\Sniffs\Files\LineLengthSniff:
|
||||
# long FQN classes that might not exist
|
||||
- src/Rector/Contrib/Symfony/FrameworkBundleClassReplacementsRector.php
|
||||
Symplify\CodingStandard\Sniffs\Classes\EqualInterfaceImplementationSniff:
|
||||
# empty parent interface, disable for now
|
||||
- packages/DeprecationExtractor/src/Deprecation/ClassMethodDeprecation.php
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
# Trigger Extractor
|
||||
# Deprecation Extractor
|
||||
|
||||
This package extracts `trigger_error(*, E_USER_DEPRECATED)` from the code.
|
||||
This package extracts 2 cases:
|
||||
|
||||
- `@deprecate` annotation
|
||||
- `trigger_error(*, E_USER_DEPRECATED)` from the code.
|
||||
|
||||
It helps to generated automate rectors.
|
||||
It helps to generated automate rectors and identify BC changes purely from the code.
|
||||
|
||||
|
||||
## How it works?
|
||||
|
@ -22,4 +25,4 @@ vendor/bin/rector extract-deprecations vendor/nette
|
|||
|
||||
It will show you what changed and how.
|
||||
|
||||
Moreover, it will change the code for you.
|
||||
Moreover, it will change the code for you.
|
|
@ -1,8 +1,8 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\TriggerExtractor\Console\Command;
|
||||
namespace Rector\DeprecationExtractor\Console\Command;
|
||||
|
||||
use Rector\TriggerExtractor\TriggerExtractor;
|
||||
use Rector\DeprecationExtractor\DeprecationExtractor;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
@ -21,13 +21,13 @@ final class ExtractCommand extends Command
|
|||
private const ARGUMENT_SOURCE_NAME = 'source';
|
||||
|
||||
/**
|
||||
* @var TriggerExtractor
|
||||
* @var deprecationExtractor
|
||||
*/
|
||||
private $triggerExtractor;
|
||||
private $deprecationExtractor;
|
||||
|
||||
public function __construct(TriggerExtractor $triggerExtractor)
|
||||
public function __construct(deprecationExtractor $deprecationExtractor)
|
||||
{
|
||||
$this->triggerExtractor = $triggerExtractor;
|
||||
$this->deprecationExtractor = $deprecationExtractor;
|
||||
|
||||
parent::__construct();
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ final class ExtractCommand extends Command
|
|||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$source = $input->getArgument(self::ARGUMENT_SOURCE_NAME);
|
||||
$this->triggerExtractor->scanDirectories($source);
|
||||
$this->deprecationExtractor->scanDirectories($source);
|
||||
|
||||
// write found deprecations...
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\DeprecationExtractor\Contract\Deprecation;
|
||||
|
||||
interface DeprecationInterface
|
||||
{
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\DeprecationExtractor\Deprecation;
|
||||
|
||||
use Rector\DeprecationExtractor\Contract\Deprecation\DeprecationInterface;
|
||||
|
||||
final class ClassMethodDeprecation implements DeprecationInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $class;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $oldMethod;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $newMethod;
|
||||
|
||||
/**
|
||||
* @var mixed[]
|
||||
*/
|
||||
private $newArguments = [];
|
||||
|
||||
/**
|
||||
* @param mixed[] $newArguments
|
||||
*/
|
||||
public function __construct(string $class, string $oldMethod, string $newMethod, array $newArguments = [])
|
||||
{
|
||||
$this->class = $class;
|
||||
$this->oldMethod = $oldMethod;
|
||||
$this->newMethod = $newMethod;
|
||||
$this->newArguments = $newArguments;
|
||||
}
|
||||
|
||||
public function getClass(): string
|
||||
{
|
||||
return $this->class;
|
||||
}
|
||||
|
||||
public function getOldMethod(): string
|
||||
{
|
||||
return $this->oldMethod;
|
||||
}
|
||||
|
||||
public function getNewMethod(): string
|
||||
{
|
||||
return $this->newMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getNewArguments(): array
|
||||
{
|
||||
return $this->newArguments;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\DeprecationExtractor\Deprecation;
|
||||
|
||||
use PhpParser\Node\Arg;
|
||||
|
||||
final class DeprecationCollector
|
||||
{
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $deprecationMessages = [];
|
||||
|
||||
/**
|
||||
* @var Arg[]
|
||||
*/
|
||||
private $deprecationArgNodes = [];
|
||||
|
||||
public function addDeprecationMessage(string $deprecationMessage): void
|
||||
{
|
||||
$this->deprecationMessages[] = $deprecationMessage;
|
||||
}
|
||||
|
||||
public function addDeprecationArgNode(Arg $argNode): void
|
||||
{
|
||||
$this->deprecationArgNodes[] = $argNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
public function getDeprecationMessages(): array
|
||||
{
|
||||
return $this->deprecationMessages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Arg[]
|
||||
*/
|
||||
public function getDeprecationArgNodes(): array
|
||||
{
|
||||
return $this->deprecationArgNodes;
|
||||
}
|
||||
}
|
|
@ -1,15 +1,15 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\TriggerExtractor;
|
||||
namespace Rector\DeprecationExtractor;
|
||||
|
||||
use Rector\Contract\Parser\ParserInterface;
|
||||
use Rector\DeprecationExtractor\NodeVisitor\DeprecationDetector;
|
||||
use Rector\NodeTraverser\MainNodeTraverser;
|
||||
use Rector\NodeTraverser\StandaloneTraverseNodeTraverser;
|
||||
use Rector\TriggerExtractor\NodeVisitor\DeprecationDetector;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Component\Finder\SplFileInfo;
|
||||
|
||||
final class TriggerExtractor
|
||||
final class DeprecationExtractor
|
||||
{
|
||||
/**
|
||||
* @var ParserInterface
|
|
@ -0,0 +1,66 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\DeprecationExtractor\NodeAnalyzer;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr\ConstFetch;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Name;
|
||||
use SplObjectStorage;
|
||||
|
||||
final class TriggerErrorAnalyzer
|
||||
{
|
||||
/**
|
||||
* @var SplObjectStorage|Arg[]
|
||||
*/
|
||||
private $messageNodePerTriggerErrorNode;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->messageNodePerTriggerErrorNode = new SplObjectStorage;
|
||||
}
|
||||
|
||||
public function isUserDeprecation(Node $node): bool
|
||||
{
|
||||
if (! $this->isFunctionWithName($node, 'trigger_error')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @var FuncCall $node */
|
||||
if (count($node->args) !== 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->messageNodePerTriggerErrorNode[$node] = $node->args[0];
|
||||
|
||||
/** @var Arg $secondArgumentNode */
|
||||
$secondArgumentNode = $node->args[1];
|
||||
if (! $secondArgumentNode->value instanceof ConstFetch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @var ConstFetch $constFetchNode */
|
||||
$constFetchNode = $secondArgumentNode->value;
|
||||
|
||||
return $constFetchNode->name->toString() === 'E_USER_DEPRECATED';
|
||||
}
|
||||
|
||||
public function messageNodeForNode(FuncCall $triggerErrorFuncCallNode): Arg
|
||||
{
|
||||
return $this->messageNodePerTriggerErrorNode[$triggerErrorFuncCallNode];
|
||||
}
|
||||
|
||||
private function isFunctionWithName(Node $node, string $name): bool
|
||||
{
|
||||
if (! $node instanceof FuncCall) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $node->name instanceof Name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $node->name->toString() === $name;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\DeprecationExtractor\NodeVisitor;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\NodeVisitorAbstract;
|
||||
use Rector\DeprecationExtractor\Deprecation\DeprecationCollector;
|
||||
use Rector\DeprecationExtractor\NodeAnalyzer\TriggerErrorAnalyzer;
|
||||
use Rector\NodeAnalyzer\DocBlockAnalyzer;
|
||||
|
||||
/**
|
||||
* Inspired by https://github.com/sensiolabs-de/deprecation-detector/blob/master/src/Visitor/Deprecation/FindDeprecatedTagsVisitor.php
|
||||
*/
|
||||
final class DeprecationDetector extends NodeVisitorAbstract
|
||||
{
|
||||
/**
|
||||
* @var DeprecationCollector
|
||||
*/
|
||||
private $deprecationCollector;
|
||||
|
||||
/**
|
||||
* @var DocBlockAnalyzer
|
||||
*/
|
||||
private $docBlockAnalyzer;
|
||||
|
||||
/**
|
||||
* @var TriggerErrorAnalyzer
|
||||
*/
|
||||
private $triggerErrorAnalyzer;
|
||||
|
||||
public function __construct(
|
||||
DeprecationCollector $deprecationCollector,
|
||||
DocBlockAnalyzer $docBlockAnalyzer,
|
||||
TriggerErrorAnalyzer $triggerErrorAnalyzer
|
||||
) {
|
||||
$this->deprecationCollector = $deprecationCollector;
|
||||
$this->docBlockAnalyzer = $docBlockAnalyzer;
|
||||
$this->triggerErrorAnalyzer = $triggerErrorAnalyzer;
|
||||
}
|
||||
|
||||
public function enterNode(Node $node): void
|
||||
{
|
||||
if ($this->docBlockAnalyzer->hasAnnotation($node, 'deprecated')) {
|
||||
$this->processDocBlockDeprecation($node);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// @todo detect the elments it's realted to
|
||||
if ($this->triggerErrorAnalyzer->isUserDeprecation($node)) {
|
||||
/** @var FuncCall $node */
|
||||
$argNode = $this->triggerErrorAnalyzer->messageNodeForNode($node);
|
||||
$this->deprecationCollector->addDeprecationArgNode($argNode);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private function processDocBlockDeprecation(Node $node): void
|
||||
{
|
||||
$deprecation = $this->docBlockAnalyzer->getAnnotationFromNode($node, 'deprecated');
|
||||
$this->deprecationCollector->addDeprecationMessage($deprecation);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\DeprecationExtractor\Rector;
|
||||
|
||||
use Rector\Rector\AbstractChangeMethodNameRector;
|
||||
|
||||
final class ConfigurableChangeMethodNameRector extends AbstractChangeMethodNameRector
|
||||
{
|
||||
/**
|
||||
* @var string[][]
|
||||
*/
|
||||
private $perClassOldToNewMethod;
|
||||
|
||||
/**
|
||||
* @param string[][] $perClassOldToNewMethod
|
||||
*/
|
||||
public function setPerClassOldToNewMethods(array $perClassOldToNewMethod): void
|
||||
{
|
||||
$this->perClassOldToNewMethod = $perClassOldToNewMethod;
|
||||
}
|
||||
|
||||
public function getSetName(): string
|
||||
{
|
||||
return 'dynamic';
|
||||
}
|
||||
|
||||
public function sinceVersion(): float
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][] { class => [ oldMethod => newMethod ] }
|
||||
*/
|
||||
protected function getPerClassOldToNewMethods(): array
|
||||
{
|
||||
return $this->perClassOldToNewMethod;
|
||||
}
|
||||
}
|
68
packages/DeprecationExtractor/src/Rector/RectorFactory.php
Normal file
68
packages/DeprecationExtractor/src/Rector/RectorFactory.php
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\DeprecationExtractor\Rector;
|
||||
|
||||
use Rector\Contract\Rector\RectorInterface;
|
||||
use Rector\DeprecationExtractor\Contract\Deprecation\DeprecationInterface;
|
||||
use Rector\DeprecationExtractor\Deprecation\ClassMethodDeprecation;
|
||||
use Rector\DeprecationExtractor\Deprecation\DeprecationCollector;
|
||||
use Rector\Exception\NotImplementedException;
|
||||
|
||||
/**
|
||||
* Creates rectors with propper setup based on found deprecations.
|
||||
*/
|
||||
final class RectorFactory
|
||||
{
|
||||
/**
|
||||
* @var DeprecationCollector
|
||||
*/
|
||||
private $deprecationCollector;
|
||||
|
||||
/**
|
||||
* @var ConfigurableChangeMethodNameRector
|
||||
*/
|
||||
private $configurableChangeMethodNameRector;
|
||||
|
||||
public function __construct(
|
||||
DeprecationCollector $deprecationCollector,
|
||||
ConfigurableChangeMethodNameRector $configurableChangeMethodNameRector
|
||||
) {
|
||||
$this->deprecationCollector = $deprecationCollector;
|
||||
$this->configurableChangeMethodNameRector = $configurableChangeMethodNameRector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RectorInterface[]
|
||||
*/
|
||||
public function createRectors(): array
|
||||
{
|
||||
$rectors = [];
|
||||
|
||||
foreach ($this->deprecationCollector->getDeprecations() as $deprecation) {
|
||||
$rectors[] = $this->createRectorFromDeprecation($deprecation);
|
||||
}
|
||||
|
||||
return $rectors;
|
||||
}
|
||||
|
||||
public function createRectorFromDeprecation(DeprecationInterface $deprecation): RectorInterface
|
||||
{
|
||||
if ($deprecation instanceof ClassMethodDeprecation) {
|
||||
$configurableChangeMethodNameRector = clone $this->configurableChangeMethodNameRector;
|
||||
$configurableChangeMethodNameRector->setPerClassOldToNewMethods([
|
||||
$deprecation->getClass() => [
|
||||
$deprecation->getOldMethod() => $deprecation->getNewMethod(),
|
||||
],
|
||||
]);
|
||||
|
||||
return $configurableChangeMethodNameRector;
|
||||
}
|
||||
|
||||
throw new NotImplementedException(sprintf(
|
||||
'%s::%s() was unable to create a Rector based on "%s" Deprecation. Create a new method there.',
|
||||
self::class,
|
||||
__METHOD__,
|
||||
get_class($deprecation)
|
||||
));
|
||||
}
|
||||
}
|
|
@ -1,23 +1,31 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\TriggerExtractor;
|
||||
namespace Rector\DeprecationExtractor\Transformer;
|
||||
|
||||
use Nette\Utils\Strings;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr\BinaryOp\Concat;
|
||||
use PhpParser\Node\Scalar\MagicConst\Method;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use Rector\DeprecationExtractor\Contract\Deprecation\DeprecationInterface;
|
||||
use Rector\Exception\NotImplementedException;
|
||||
use Rector\Node\Attribute;
|
||||
|
||||
final class TriggerMessageResolver
|
||||
final class ArgumentToDeprecationTransformer
|
||||
{
|
||||
public function transform(Arg $argNode): DeprecationInterface
|
||||
{
|
||||
dump($argNode);
|
||||
die;
|
||||
}
|
||||
|
||||
/**
|
||||
* Probably resolve by recursion, similar too
|
||||
* @see \Rector\NodeTypeResolver\NodeVisitor\TypeResolver::__construct()
|
||||
*/
|
||||
public function resolve(Node $node): string
|
||||
public function createFromNode(Node $node, string $scope): DeprecationInterface
|
||||
{
|
||||
$message = '';
|
||||
if ($node instanceof Concat) {
|
||||
|
@ -25,10 +33,41 @@ final class TriggerMessageResolver
|
|||
$message .= $this->processConcatNode($node->right);
|
||||
}
|
||||
|
||||
return $message;
|
||||
return $this->createFromMesssage($message, $scope);
|
||||
}
|
||||
|
||||
private function processConcatNode(Node $node): string
|
||||
public function tryToCreateClassMethodDeprecation(string $oldMessage, string $newMessage): ?DeprecationInterface
|
||||
{
|
||||
// try to find "SomeClass::methodCall()"
|
||||
$matches = Strings::matchAll($oldMessage, self::CLASS_WITH_METHOD_PATTERN);
|
||||
if (isset($matches[0]['classMethod'])) {
|
||||
$oldClassWithMethod = $matches[0]['classMethod'];
|
||||
}
|
||||
|
||||
// try to find "SomeClass::methodCall()"
|
||||
$matches = Strings::matchAll($newMessage, self::CLASS_WITH_METHOD_PATTERN);
|
||||
if (isset($matches[0]['classMethod'])) {
|
||||
$newClassWithMethod = $matches[0]['classMethod'];
|
||||
}
|
||||
|
||||
if (isset($oldClassWithMethod, $newClassWithMethod)) {
|
||||
[$oldClass, $oldMethod] = explode('::', $oldClassWithMethod);
|
||||
[$newClass, $newMethod] = explode('::', $newClassWithMethod);
|
||||
|
||||
if ($oldClass === $newClass) {
|
||||
// simple method replacement
|
||||
return new ClassMethodDeprecation(
|
||||
$oldClass,
|
||||
rtrim($oldMethod, '()'),
|
||||
rtrim($newMethod, '()')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function processConcatNode(Node $node, string $scope): string
|
||||
{
|
||||
if ($node instanceof Method) {
|
||||
$classMethodNode = $this->findParentOfType($node, ClassMethod::class);
|
||||
|
@ -92,4 +131,25 @@ final class TriggerMessageResolver
|
|||
|
||||
return $word;
|
||||
}
|
||||
|
||||
private function createFromMesssage(string $message): DeprecationInterface
|
||||
{
|
||||
// format: don't use this, use that
|
||||
if (Strings::contains($message, ' use ')) {
|
||||
[$oldMessage, $newMessage] = explode(' use ', $message);
|
||||
|
||||
$deprecation = $this->tryToCreateClassMethodDeprecation($oldMessage, $newMessage);
|
||||
if ($deprecation) {
|
||||
return $deprecation;
|
||||
}
|
||||
}
|
||||
|
||||
throw new NotImplementedException(sprintf(
|
||||
'%s::%s() did not resolve %s messsage, so %s was not created. Implement it.',
|
||||
self::class,
|
||||
__METHOD__,
|
||||
$message,
|
||||
DeprecationInterface::class
|
||||
));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\DeprecationExtractor\Transformer;
|
||||
|
||||
use Rector\DeprecationExtractor\Contract\Deprecation\DeprecationInterface;
|
||||
|
||||
final class MessageToDeprecationTransformer
|
||||
{
|
||||
public function transform(string $message): DeprecationInterface
|
||||
{
|
||||
dump($message);
|
||||
die;
|
||||
}
|
||||
}
|
|
@ -3,5 +3,6 @@ services:
|
|||
autowire: true
|
||||
|
||||
# PSR-4 autodiscovery
|
||||
Rector\TriggerExtractor\:
|
||||
Rector\DeprecationExtractor\:
|
||||
resource: '../../src'
|
||||
exclude: '../../src/{Deprecation/ClassMethodDeprecation.php}'
|
|
@ -1,17 +1,17 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\TriggerExtractor\Tests;
|
||||
namespace Rector\DeprecationExtractor\Tests;
|
||||
|
||||
use Rector\DeprecationExtractor\Deprecation\DeprecationCollector;
|
||||
use Rector\DeprecationExtractor\DeprecationExtractor;
|
||||
use Rector\Tests\AbstractContainerAwareTestCase;
|
||||
use Rector\TriggerExtractor\Deprecation\DeprecationCollector;
|
||||
use Rector\TriggerExtractor\TriggerExtractor;
|
||||
|
||||
final class TriggerExtractorTest extends AbstractContainerAwareTestCase
|
||||
final class DeprecationExtractorTest extends AbstractContainerAwareTestCase
|
||||
{
|
||||
/**
|
||||
* @var TriggerExtractor
|
||||
* @var DeprecationExtractor
|
||||
*/
|
||||
private $triggerExtractor;
|
||||
private $deprecationExtractor;
|
||||
|
||||
/**
|
||||
* @var DeprecationCollector
|
||||
|
@ -20,26 +20,25 @@ final class TriggerExtractorTest extends AbstractContainerAwareTestCase
|
|||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->triggerExtractor = $this->container->get(TriggerExtractor::class);
|
||||
$this->deprecationExtractor = $this->container->get(DeprecationExtractor::class);
|
||||
$this->deprecationCollector = $this->container->get(DeprecationCollector::class);
|
||||
}
|
||||
|
||||
public function test(): void
|
||||
{
|
||||
$this->triggerExtractor->scanDirectories([__DIR__ . '/TriggerExtractorSource']);
|
||||
$this->deprecationExtractor->scanDirectories([__DIR__ . '/DeprecationExtractorSource']);
|
||||
$deprecations = $this->deprecationCollector->getDeprecations();
|
||||
|
||||
$this->assertCount(2, $deprecations);
|
||||
|
||||
$setClassToSetFacoryDeprecation = $deprecations[0];
|
||||
$injectMethodToTagDeprecation = $deprecations[1];
|
||||
|
||||
$this->assertSame(
|
||||
'Nette\DI\Definition::setClass() second parameter $args is deprecated,'
|
||||
. ' use Nette\DI\Definition::setFactory()',
|
||||
$setClassToSetFacoryDeprecation
|
||||
);
|
||||
|
||||
$injectMethodToTagDeprecation = $deprecations[1];
|
||||
$this->assertSame(
|
||||
'Nette\DI\Definition::setInject() is deprecated, use Nette\DI\Definition::addTag(\'inject\')',
|
||||
$injectMethodToTagDeprecation
|
|
@ -0,0 +1,51 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\DeprecationExtractor\Tests\Rector;
|
||||
|
||||
use PHPUnit\Framework\Assert;
|
||||
use Rector\DeprecationExtractor\DeprecationExtractor;
|
||||
use Rector\DeprecationExtractor\Rector\ConfigurableChangeMethodNameRector;
|
||||
use Rector\DeprecationExtractor\Rector\RectorFactory;
|
||||
use Rector\Tests\AbstractContainerAwareTestCase;
|
||||
|
||||
final class RectorFactoryTest extends AbstractContainerAwareTestCase
|
||||
{
|
||||
/**
|
||||
* @var RectorFactory
|
||||
*/
|
||||
private $rectorFactory;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->rectorFactory = $this->container->get(RectorFactory::class);
|
||||
|
||||
$DeprecationExtractor = $this->container->get(DeprecationExtractor::class);
|
||||
$DeprecationExtractor->scanDirectories([__DIR__ . '/../DeprecationExtractorSource']);
|
||||
}
|
||||
|
||||
public function test(): void
|
||||
{
|
||||
$rectors = $this->rectorFactory->createRectors();
|
||||
$this->assertCount(2, $rectors);
|
||||
|
||||
/** @var ConfigurableChangeMethodNameRector $firstRector */
|
||||
$firstRector = $rectors[0];
|
||||
$this->assertInstanceOf(ConfigurableChangeMethodNameRector::class, $firstRector);
|
||||
|
||||
$this->assertSame([
|
||||
'Nette\DI\Definition' => [
|
||||
'setClass' => 'setFactory',
|
||||
],
|
||||
], Assert::getObjectAttribute($firstRector, 'perClassOldToNewMethod'));
|
||||
|
||||
/** @var ConfigurableChangeMethodNameRector $secondRector */
|
||||
$secondRector = $rectors[1];
|
||||
$this->assertInstanceOf(ConfigurableChangeMethodNameRector::class, $secondRector);
|
||||
|
||||
$this->assertSame([
|
||||
'Nette\DI\Definition' => [
|
||||
'setInject' => 'addTag',
|
||||
],
|
||||
], Assert::getObjectAttribute($secondRector, 'perClassOldToNewMethod'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\DeprecationExtractor\Tests\Tranformer;
|
||||
|
||||
use Rector\DeprecationExtractor\Transformer\ArgumentToDeprecationTransformer;
|
||||
use Rector\Tests\AbstractContainerAwareTestCase;
|
||||
|
||||
final class ArgumentToDeprecationTransformerTest extends AbstractContainerAwareTestCase
|
||||
{
|
||||
/**
|
||||
* @var ArgumentToDeprecationTransformer
|
||||
*/
|
||||
private $argumentToDeprecationTransformer;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->argumentToDeprecationTransformer = $this->container->get(ArgumentToDeprecationTransformer::class);
|
||||
}
|
||||
|
||||
public function test(): void
|
||||
{
|
||||
// @todo
|
||||
$this->assertSame(1, 1);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\DeprecationExtractor\Tests\Tranformer;
|
||||
|
||||
use Rector\DeprecationExtractor\Deprecation\DeprecationCollector;
|
||||
use Rector\DeprecationExtractor\DeprecationExtractor;
|
||||
use Rector\DeprecationExtractor\Transformer\MessageToDeprecationTransformer;
|
||||
use Rector\Tests\AbstractContainerAwareTestCase;
|
||||
|
||||
final class MessageToDeprecationTransformerTest extends AbstractContainerAwareTestCase
|
||||
{
|
||||
/**
|
||||
* @var DeprecationExtractor
|
||||
*/
|
||||
private $deprecationExtractor;
|
||||
|
||||
/**
|
||||
* @var DeprecationCollector
|
||||
*/
|
||||
private $deprecationCollector;
|
||||
|
||||
/**
|
||||
* @var MessageToDeprecationTransformer
|
||||
*/
|
||||
private $messageToDeprecationTransformer;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->deprecationExtractor = $this->container->get(DeprecationExtractor::class);
|
||||
$this->deprecationCollector = $this->container->get(DeprecationCollector::class);
|
||||
$this->messageToDeprecationTransformer = $this->container->get(MessageToDeprecationTransformer::class);
|
||||
}
|
||||
|
||||
public function test(): void
|
||||
{
|
||||
$this->deprecationExtractor->scanDirectories([
|
||||
__DIR__ . '/../../../../vendor/symfony/dependency-injection'
|
||||
]);
|
||||
|
||||
$deprecationMessages = $this->deprecationCollector->getDeprecationMessages();
|
||||
dump($deprecationMessages);
|
||||
die;
|
||||
|
||||
// $this->messageToDeprecationTransformer->transform();
|
||||
|
||||
// @todo
|
||||
$this->assertSame(1, 1);
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@ Anonymous classes are skipped.
|
|||
|
||||
## How it helps you?
|
||||
|
||||
You can get `class`
|
||||
### 1. You can get `class`
|
||||
|
||||
```php
|
||||
$class = (string) $node->getAttribute(Attribute::CLASS_NAME);
|
||||
|
@ -38,7 +38,7 @@ if ($fqnName->toString() === 'Symfony\Component\Console\Command') {
|
|||
}
|
||||
```
|
||||
|
||||
or `type` attribute:
|
||||
### 2. Or `type` attribute:
|
||||
|
||||
```php
|
||||
/** @var string $type */
|
||||
|
@ -49,4 +49,4 @@ if ($type === 'Nette\Application\UI\Form') {
|
|||
}
|
||||
```
|
||||
|
||||
...in any Rector you create.
|
||||
...in any Rector you create.
|
||||
|
|
|
@ -4,7 +4,9 @@ namespace Rector\NodeTypeResolver\NodeVisitor;
|
|||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassLike;
|
||||
use PhpParser\NodeVisitorAbstract;
|
||||
use Rector\Node\Attribute;
|
||||
|
||||
/**
|
||||
* Add attribute 'class' with current class name.
|
||||
|
@ -12,17 +14,7 @@ use PhpParser\NodeVisitorAbstract;
|
|||
final class ClassResolver extends NodeVisitorAbstract
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const CLASS_ATTRIBUTE = 'class';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const CLASS_NODE_ATTRIBUTE = 'class_node';
|
||||
|
||||
/**
|
||||
* @var Class_|null
|
||||
* @var ClassLike|null
|
||||
*/
|
||||
private $classNode;
|
||||
|
||||
|
@ -36,14 +28,19 @@ final class ClassResolver extends NodeVisitorAbstract
|
|||
|
||||
public function enterNode(Node $node): void
|
||||
{
|
||||
// detect only first "class" to prevent anonymous classes interference
|
||||
if ($this->classNode === null && $node instanceof Class_) {
|
||||
// detect only first ClassLike elemetn
|
||||
if ($this->classNode === null && $node instanceof ClassLike) {
|
||||
// skip possible anonymous classes
|
||||
if ($node instanceof Class_ && $node->isAnonymous()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->classNode = $node;
|
||||
}
|
||||
|
||||
if ($this->classNode) {
|
||||
$node->setAttribute(self::CLASS_NODE_ATTRIBUTE, $this->classNode);
|
||||
$node->setAttribute(self::CLASS_ATTRIBUTE, $this->classNode->namespacedName->toString());
|
||||
$node->setAttribute(Attribute::CLASS_NODE, $this->classNode);
|
||||
$node->setAttribute(Attribute::CLASS_NAME, $this->classNode->namespacedName->toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
99
packages/NodeTypeResolver/src/NodeVisitor/ScopeResolver.php
Normal file
99
packages/NodeTypeResolver/src/NodeVisitor/ScopeResolver.php
Normal file
|
@ -0,0 +1,99 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeTypeResolver\NodeVisitor;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassLike;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Function_;
|
||||
use PhpParser\Node\Stmt\Interface_;
|
||||
use PhpParser\Node\Stmt\Namespace_;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use PhpParser\Node\Stmt\Trait_;
|
||||
use PhpParser\NodeVisitorAbstract;
|
||||
use Rector\Node\Attribute;
|
||||
|
||||
/**
|
||||
* In class, in interface, in trait, in method or in function.
|
||||
*/
|
||||
final class ScopeResolver extends NodeVisitorAbstract
|
||||
{
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $currentScope;
|
||||
|
||||
/**
|
||||
* @var Node|null
|
||||
*/
|
||||
private $currentScopeNode;
|
||||
|
||||
/**
|
||||
* @param Node[] $nodes
|
||||
*/
|
||||
public function beforeTraverse(array $nodes): void
|
||||
{
|
||||
$this->currentScope = null;
|
||||
}
|
||||
|
||||
public function enterNode(Node $node): void
|
||||
{
|
||||
$this->resolveClassLikeScope($node);
|
||||
|
||||
if ($node instanceof Namespace_) {
|
||||
$this->currentScope = 'scope_namespace';
|
||||
$this->currentScopeNode = $node;
|
||||
}
|
||||
|
||||
if ($node instanceof Function_) {
|
||||
$this->currentScope = 'scope_function';
|
||||
$this->currentScopeNode = $node;
|
||||
}
|
||||
|
||||
if ($node instanceof ClassMethod) {
|
||||
$this->currentScope = 'scope_class_method';
|
||||
$this->currentScopeNode = $node;
|
||||
}
|
||||
|
||||
if ($this->currentScope) {
|
||||
$node->setAttribute(Attribute::SCOPE, $this->currentScope);
|
||||
$node->setAttribute(Attribute::SCOPE_NODE, $this->currentScopeNode);
|
||||
}
|
||||
}
|
||||
|
||||
public function leaveNode(Node $node): void
|
||||
{
|
||||
if ($node instanceof ClassLike) {
|
||||
if ($node instanceof Class_ && $node->isAnonymous()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->currentScope = null;
|
||||
$this->currentScopeNode = null;
|
||||
}
|
||||
|
||||
if ($node instanceof ClassMethod || $node instanceof Function_) {
|
||||
$this->currentScope = null;
|
||||
$this->currentScopeNode = null;
|
||||
}
|
||||
}
|
||||
|
||||
private function resolveClassLikeScope(Node $node): void
|
||||
{
|
||||
if (($node instanceof Class_ && $node->isAnonymous()) || $node instanceof Property) {
|
||||
$this->currentScope = 'scope_class';
|
||||
$this->currentScopeNode = $node;
|
||||
}
|
||||
|
||||
if ($node instanceof Interface_) {
|
||||
$this->currentScope = 'scope_interface';
|
||||
$this->currentScopeNode = $node;
|
||||
}
|
||||
|
||||
if ($node instanceof Trait_) {
|
||||
$this->currentScope = 'scope_trait';
|
||||
$this->currentScopeNode = $node;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,11 +20,6 @@ use Rector\NodeTypeResolver\TypeContext;
|
|||
*/
|
||||
final class TypeResolver extends NodeVisitorAbstract
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const TYPE_ATTRIBUTE = 'type';
|
||||
|
||||
/**
|
||||
* @var TypeContext
|
||||
*/
|
||||
|
@ -108,7 +103,7 @@ final class TypeResolver extends NodeVisitorAbstract
|
|||
}
|
||||
|
||||
if ($variableType) {
|
||||
$variableNode->setAttribute(self::TYPE_ATTRIBUTE, $variableType);
|
||||
$variableNode->setAttribute(Attribute::TYPE, $variableType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,7 +114,7 @@ final class TypeResolver extends NodeVisitorAbstract
|
|||
|
||||
$variableType = $this->typeContext->getTypeForVariable($assignNode->var->name);
|
||||
if ($variableType) {
|
||||
$assignNode->var->setAttribute(self::TYPE_ATTRIBUTE, $variableType);
|
||||
$assignNode->var->setAttribute(Attribute::TYPE, $variableType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +129,7 @@ final class TypeResolver extends NodeVisitorAbstract
|
|||
$propertyType = $this->typeContext->getTypeForProperty($propertyName);
|
||||
|
||||
if ($propertyType) {
|
||||
$propertyFetchNode->setAttribute(self::TYPE_ATTRIBUTE, $propertyType);
|
||||
$propertyFetchNode->setAttribute(Attribute::TYPE, $propertyType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,7 +139,7 @@ final class TypeResolver extends NodeVisitorAbstract
|
|||
$propertyType = $this->typeContext->getTypeForProperty($propertyName);
|
||||
|
||||
if ($propertyType) {
|
||||
$propertyNode->setAttribute(self::TYPE_ATTRIBUTE, $propertyType);
|
||||
$propertyNode->setAttribute(Attribute::TYPE, $propertyType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ final class TypeContext
|
|||
$this->classProperties = [];
|
||||
$this->classLikeNode = $classLikeNode;
|
||||
|
||||
if ($classLikeNode instanceof Class_) {
|
||||
if ($classLikeNode instanceof Class_ && ! $classLikeNode->isAnonymous()) {
|
||||
$this->classProperties = $this->constructorPropertyTypesExtractor->extractFromClassNode($classLikeNode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\TriggerExtractor\Deprecation;
|
||||
|
||||
final class DeprecationCollector
|
||||
{
|
||||
/**
|
||||
* @var mixed[]
|
||||
*/
|
||||
private $deprecations = [];
|
||||
|
||||
public function addDeprecation(string $deprecation): void
|
||||
{
|
||||
$this->deprecations[] = $deprecation;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public function getDeprecations(): array
|
||||
{
|
||||
return $this->deprecations;
|
||||
}
|
||||
}
|
|
@ -1,84 +0,0 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\TriggerExtractor\NodeVisitor;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr\ConstFetch;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\NodeVisitorAbstract;
|
||||
use Rector\TriggerExtractor\Deprecation\DeprecationCollector;
|
||||
use Rector\TriggerExtractor\TriggerMessageResolver;
|
||||
|
||||
final class DeprecationDetector extends NodeVisitorAbstract
|
||||
{
|
||||
/**
|
||||
* @var DeprecationCollector
|
||||
*/
|
||||
private $deprecationCollector;
|
||||
|
||||
/**
|
||||
* @var TriggerMessageResolver
|
||||
*/
|
||||
private $triggerMessageResolver;
|
||||
|
||||
public function __construct(
|
||||
DeprecationCollector $deprecationCollector,
|
||||
TriggerMessageResolver $triggerMessageResolver
|
||||
) {
|
||||
$this->deprecationCollector = $deprecationCollector;
|
||||
$this->triggerMessageResolver = $triggerMessageResolver;
|
||||
}
|
||||
|
||||
public function enterNode(Node $node): void
|
||||
{
|
||||
if (! $this->isTriggerErrorUserDeprecated($node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var FuncCall $node */
|
||||
$deprecation = $this->triggerMessageResolver->resolve($node->args[0]->value);
|
||||
|
||||
$this->deprecationCollector->addDeprecation($deprecation);
|
||||
}
|
||||
|
||||
/**
|
||||
* This detects: "trigger_error(<some-content>, E_USER_DEPREDCATED)";
|
||||
*/
|
||||
private function isTriggerErrorUserDeprecated(Node $node): bool
|
||||
{
|
||||
if (! $this->isFunctionWithName($node, 'trigger_error')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @var FuncCall $node */
|
||||
if (count($node->args) !== 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @var Arg $secondArgumentNode */
|
||||
$secondArgumentNode = $node->args[1];
|
||||
if (! $secondArgumentNode->value instanceof ConstFetch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @var ConstFetch $constFetchNode */
|
||||
$constFetchNode = $secondArgumentNode->value;
|
||||
|
||||
return $constFetchNode->name->toString() === 'E_USER_DEPRECATED';
|
||||
}
|
||||
|
||||
private function isFunctionWithName(Node $node, string $name): bool
|
||||
{
|
||||
if (! $node instanceof FuncCall) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! $node->name instanceof Name) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $node->name->toString() === $name;
|
||||
}
|
||||
}
|
|
@ -5,4 +5,4 @@ parameters:
|
|||
- '#Undefined variable: \$container#'
|
||||
- '#Undefined variable: \$application#'
|
||||
excludes_analyse:
|
||||
- *packages/TriggerExtractor/tests/TriggerExtractorSource/Definition.php
|
||||
- *packages/DeprecationExtractor/tests/DeprecationExtractorSource/Definition.php
|
||||
|
|
|
@ -5,18 +5,12 @@ namespace Rector\Builder;
|
|||
use PhpParser\Builder\Method;
|
||||
use PhpParser\Builder\Param;
|
||||
use PhpParser\BuilderFactory;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Parser;
|
||||
use Rector\NodeFactory\NodeFactory;
|
||||
|
||||
final class ConstructorMethodBuilder
|
||||
{
|
||||
/**
|
||||
* @var Parser
|
||||
*/
|
||||
private $parser;
|
||||
|
||||
/**
|
||||
* @var BuilderFactory
|
||||
*/
|
||||
|
@ -27,25 +21,33 @@ final class ConstructorMethodBuilder
|
|||
*/
|
||||
private $statementGlue;
|
||||
|
||||
public function __construct(Parser $parser, BuilderFactory $builderFactory, StatementGlue $statementGlue)
|
||||
{
|
||||
$this->parser = $parser;
|
||||
/**
|
||||
* @var NodeFactory
|
||||
*/
|
||||
private $nodeFactory;
|
||||
|
||||
public function __construct(
|
||||
BuilderFactory $builderFactory,
|
||||
StatementGlue $statementGlue,
|
||||
NodeFactory $nodeFactory
|
||||
) {
|
||||
$this->builderFactory = $builderFactory;
|
||||
$this->statementGlue = $statementGlue;
|
||||
$this->nodeFactory = $nodeFactory;
|
||||
}
|
||||
|
||||
public function addPropertyAssignToClass(Class_ $classNode, string $propertyType, string $propertyName): void
|
||||
{
|
||||
$assign = $this->createPropertyAssignment($propertyName);
|
||||
|
||||
$constructorMethod = $classNode->getMethod('__construct') ?: null;
|
||||
|
||||
$propertyAssignNode = $this->nodeFactory->createPropertyAssignment($propertyName);
|
||||
|
||||
/** @var ClassMethod $constructorMethod */
|
||||
if ($constructorMethod) {
|
||||
$constructorMethod->params[] = $this->createParameter($propertyType, $propertyName)
|
||||
->getNode();
|
||||
|
||||
$constructorMethod->stmts[] = $assign[0];
|
||||
$constructorMethod->stmts[] = $propertyAssignNode;
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -54,7 +56,7 @@ final class ConstructorMethodBuilder
|
|||
$constructorMethod = $this->builderFactory->method('__construct')
|
||||
->makePublic()
|
||||
->addParam($this->createParameter($propertyType, $propertyName))
|
||||
->addStmts($assign);
|
||||
->addStmts([$propertyAssignNode]);
|
||||
|
||||
$this->statementGlue->addAsFirstMethod($classNode, $constructorMethod->getNode());
|
||||
}
|
||||
|
@ -64,16 +66,4 @@ final class ConstructorMethodBuilder
|
|||
return $this->builderFactory->param($propertyName)
|
||||
->setTypeHint($propertyType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Node[]
|
||||
*/
|
||||
private function createPropertyAssignment(string $propertyName): array
|
||||
{
|
||||
return $this->parser->parse(sprintf(
|
||||
'<?php $this->%s = $%s;',
|
||||
$propertyName,
|
||||
$propertyName
|
||||
));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,9 @@ use PhpParser\Node\Arg;
|
|||
use Psr\Container\ContainerInterface;
|
||||
use Symfony\Component\HttpKernel\Kernel;
|
||||
|
||||
/**
|
||||
* @see for inspiration https://github.com/sensiolabs-de/deprecation-detector/blob/master/src/TypeGuessing/Symfony/ContainerReader.phpě
|
||||
*/
|
||||
final class ServiceFromKernelResolver
|
||||
{
|
||||
public function resolveServiceClassFromArgument(Arg $argNode, string $kernelClass): ?string
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace Rector\Contract\Deprecation;
|
||||
|
||||
use Rector\Deprecation\SetNames;
|
||||
use Rector\Rector\Set\SetNames;
|
||||
|
||||
interface DeprecationInterface
|
||||
{
|
||||
|
|
|
@ -8,8 +8,6 @@ use Symfony\Component\Console\Application;
|
|||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symplify\PackageBuilder\Adapter\Symfony\DependencyInjection\DefinitionCollector;
|
||||
|
||||
final class CollectorCompilerPass implements CompilerPassInterface
|
||||
|
@ -18,7 +16,6 @@ final class CollectorCompilerPass implements CompilerPassInterface
|
|||
{
|
||||
$this->collectCommandsToConsoleApplication($containerBuilder);
|
||||
$this->collectRectorsToRectorCollector($containerBuilder);
|
||||
$this->collectEventSubscribersToEventDisptacher($containerBuilder);
|
||||
}
|
||||
|
||||
private function collectCommandsToConsoleApplication(ContainerBuilder $containerBuilder): void
|
||||
|
@ -40,14 +37,4 @@ final class CollectorCompilerPass implements CompilerPassInterface
|
|||
'addRector'
|
||||
);
|
||||
}
|
||||
|
||||
private function collectEventSubscribersToEventDisptacher(ContainerBuilder $containerBuilder): void
|
||||
{
|
||||
DefinitionCollector::loadCollectorWithType(
|
||||
$containerBuilder,
|
||||
EventDispatcherInterface::class,
|
||||
EventSubscriberInterface::class,
|
||||
'addSubscriber'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,10 +10,24 @@ namespace Rector\Node;
|
|||
final class Attribute
|
||||
{
|
||||
/**
|
||||
* Class, interface or trait FQN type.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const TYPE = 'type';
|
||||
|
||||
/**
|
||||
* In class, in interface, in trait, in method or in function
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public const SCOPE = 'scope';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public const SCOPE_NODE = 'scope_node';
|
||||
|
||||
/**
|
||||
* System name to be found in @see \PhpParser\NodeVisitor\NameResolver
|
||||
* Do not change this even if you want!
|
||||
|
|
78
src/NodeAnalyzer/DocBlockAnalyzer.php
Normal file
78
src/NodeAnalyzer/DocBlockAnalyzer.php
Normal file
|
@ -0,0 +1,78 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\NodeAnalyzer;
|
||||
|
||||
use PhpCsFixer\DocBlock\DocBlock;
|
||||
use PhpParser\Comment\Doc;
|
||||
use PhpParser\Node;
|
||||
use Rector\Exception\NotImplementedException;
|
||||
|
||||
final class DocBlockAnalyzer
|
||||
{
|
||||
public function hasAnnotation(Node $node, string $annotation): bool
|
||||
{
|
||||
$docBlock = $this->createDocBlockFromNode($node);
|
||||
|
||||
return (bool) $docBlock->getAnnotationsOfType($annotation);
|
||||
}
|
||||
|
||||
public function removeAnnotationFromNode(Node $node, string $annotation): void
|
||||
{
|
||||
$docBlock = $this->createDocBlockFromNode($node);
|
||||
|
||||
$annotations = $docBlock->getAnnotationsOfType($annotation);
|
||||
foreach ($annotations as $injectAnnotation) {
|
||||
$injectAnnotation->remove();
|
||||
}
|
||||
|
||||
$node->setDocComment(new Doc($docBlock->getContent()));
|
||||
}
|
||||
|
||||
public function getAnnotationFromNode(Node $node, string $annotation): string
|
||||
{
|
||||
$docBlock = new DocBlock($node->getDocComment());
|
||||
|
||||
$annotationTags = $docBlock->getAnnotationsOfType($annotation);
|
||||
if (count($annotationTags) === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (count($annotationTags) === 1) {
|
||||
$type = $annotationTags[0]->getTag()->getName();
|
||||
if ($type === 'var') {
|
||||
return implode('|', $annotationTags[0]->getTypes());
|
||||
}
|
||||
|
||||
if ($type === 'deprecated') {
|
||||
$content = $annotationTags[0]->getContent();
|
||||
|
||||
return ltrim($content, '* @deprecated ');
|
||||
}
|
||||
}
|
||||
|
||||
throw new NotImplementedException(sprintf(
|
||||
'Not implemented yet. Go to "%s::%s()" and add check for "%s" annotation.',
|
||||
__CLASS__,
|
||||
__METHOD__,
|
||||
$annotation
|
||||
));
|
||||
}
|
||||
|
||||
public function getDeprecatedDocComment(Node $node): ?string
|
||||
{
|
||||
$docBlock = new DocBlock($node->getDocComment());
|
||||
$deprecatedTag = $docBlock->getAnnotationsOfType('deprecated');
|
||||
if (count($deprecatedTag) === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$comment = $deprecatedTag[0]->getContent();
|
||||
|
||||
return preg_replace('/[[:blank:]]+/', ' ', $comment);
|
||||
}
|
||||
|
||||
private function createDocBlockFromNode(Node $node): DocBlock
|
||||
{
|
||||
return new DocBlock($node->getDocComment());
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ use PhpParser\Node;
|
|||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr\Array_;
|
||||
use PhpParser\Node\Expr\ArrayItem;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\ClassConstFetch;
|
||||
use PhpParser\Node\Expr\ConstFetch;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
|
@ -16,6 +17,7 @@ use PhpParser\Node\Identifier;
|
|||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\Node\Stmt\TraitUse;
|
||||
|
||||
final class NodeFactory
|
||||
|
@ -133,4 +135,21 @@ final class NodeFactory
|
|||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates $this->property = $property;
|
||||
*/
|
||||
public function createPropertyAssignment(string $propertyName): Expression
|
||||
{
|
||||
$variable = new Variable($propertyName, [
|
||||
'name' => $propertyName,
|
||||
]);
|
||||
|
||||
$assign = new Assign(
|
||||
$this->createLocalPropertyFetch($propertyName),
|
||||
$variable
|
||||
);
|
||||
|
||||
return new Expression($assign);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,8 +46,9 @@ final class PropertyToClassAdder extends NodeVisitorAbstract
|
|||
public function afterTraverse(array $nodes): array
|
||||
{
|
||||
foreach ($nodes as $key => $node) {
|
||||
if ($node instanceof Class_) {
|
||||
if ($node instanceof Class_ && ! $node->isAnonymous()) {
|
||||
$nodes[$key] = $this->processClass($node, (string) $node->name);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ abstract class AbstractChangeParentClassRector extends AbstractRector
|
|||
{
|
||||
public function isCandidate(Node $node): bool
|
||||
{
|
||||
if (! $node instanceof Class_ || $node->extends === null) {
|
||||
if (! $node instanceof Class_ || $node->extends === null || $node->isAnonymous()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,10 +6,10 @@ use PhpParser\Node;
|
|||
use PhpParser\Node\Expr\ArrayDimFetch;
|
||||
use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use Rector\Deprecation\SetNames;
|
||||
use Rector\Node\Attribute;
|
||||
use Rector\NodeFactory\NodeFactory;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\Rector\Set\SetNames;
|
||||
|
||||
/**
|
||||
* Covers https://doc.nette.org/en/2.4/migration-2-4#toc-nette-smartobject.
|
||||
|
|
|
@ -5,11 +5,11 @@ namespace Rector\Rector\Contrib\Nette;
|
|||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\ClassConstFetch;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use Rector\Deprecation\SetNames;
|
||||
use Rector\Node\Attribute;
|
||||
use Rector\NodeAnalyzer\MethodCallAnalyzer;
|
||||
use Rector\NodeFactory\NodeFactory;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\Rector\Set\SetNames;
|
||||
|
||||
/**
|
||||
* Covers https://forum.nette.org/cs/26672-missing-setrequired-true-false-on-field-abc-in-form
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace Rector\Rector\Contrib\Nette;
|
||||
|
||||
use Rector\Deprecation\SetNames;
|
||||
use Rector\Rector\AbstractChangeMethodNameRector;
|
||||
use Rector\Rector\Set\SetNames;
|
||||
|
||||
final class HtmlAddMethodRector extends AbstractChangeMethodNameRector
|
||||
{
|
||||
|
|
|
@ -2,52 +2,31 @@
|
|||
|
||||
namespace Rector\Rector\Contrib\Nette;
|
||||
|
||||
use PhpCsFixer\DocBlock\DocBlock;
|
||||
use PhpParser\Comment\Doc;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use Rector\Builder\Class_\ClassPropertyCollector;
|
||||
use Rector\Deprecation\SetNames;
|
||||
use Rector\Node\Attribute;
|
||||
use Rector\NodeAnalyzer\DocBlockAnalyzer;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\Rector\Set\SetNames;
|
||||
|
||||
final class InjectPropertyRector extends AbstractRector
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const ANNOTATION_INJECT = 'inject';
|
||||
|
||||
/**
|
||||
* @var ClassPropertyCollector
|
||||
*/
|
||||
private $classPropertyCollector;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @var DocBlockAnalyzer
|
||||
*/
|
||||
private $className;
|
||||
private $docBlockAnalyzer;
|
||||
|
||||
public function __construct(ClassPropertyCollector $classPropertyCollector)
|
||||
public function __construct(ClassPropertyCollector $classPropertyCollector, DocBlockAnalyzer $docBlockAnalyzer)
|
||||
{
|
||||
$this->classPropertyCollector = $classPropertyCollector;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Node[] $nodes
|
||||
* @return null|Node[]
|
||||
*/
|
||||
public function beforeTraverse(array $nodes): ?array
|
||||
{
|
||||
$this->className = null;
|
||||
|
||||
foreach ($nodes as $node) {
|
||||
if ($node instanceof Class_) {
|
||||
$this->className = (string) $node->name;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
$this->docBlockAnalyzer = $docBlockAnalyzer;
|
||||
}
|
||||
|
||||
public function isCandidate(Node $node): bool
|
||||
|
@ -56,7 +35,7 @@ final class InjectPropertyRector extends AbstractRector
|
|||
return false;
|
||||
}
|
||||
|
||||
if (! $this->hasInjectAnnotation($node)) {
|
||||
if (! $this->docBlockAnalyzer->hasAnnotation($node, 'inject')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -68,12 +47,11 @@ final class InjectPropertyRector extends AbstractRector
|
|||
*/
|
||||
public function refactor(Node $propertyNode): Node
|
||||
{
|
||||
$propertyDocBlock = $this->createDocBlockFromNode($propertyNode);
|
||||
$propertyNode = $this->removeInjectAnnotationFromProperty($propertyNode, $propertyDocBlock);
|
||||
$this->docBlockAnalyzer->removeAnnotationFromNode($propertyNode, 'inject');
|
||||
|
||||
$propertyNode->flags = Class_::MODIFIER_PRIVATE;
|
||||
|
||||
$this->addPropertyToCollector($propertyNode, $propertyDocBlock);
|
||||
$this->addPropertyToCollector($propertyNode);
|
||||
|
||||
return $propertyNode;
|
||||
}
|
||||
|
@ -88,37 +66,16 @@ final class InjectPropertyRector extends AbstractRector
|
|||
return 2.1;
|
||||
}
|
||||
|
||||
private function hasInjectAnnotation(Property $propertyNode): bool
|
||||
private function addPropertyToCollector(Property $propertyNode): void
|
||||
{
|
||||
$propertyDocBlock = $this->createDocBlockFromNode($propertyNode);
|
||||
|
||||
return (bool) $propertyDocBlock->getAnnotationsOfType(self::ANNOTATION_INJECT);
|
||||
}
|
||||
|
||||
private function createDocBlockFromNode(Node $node): DocBlock
|
||||
{
|
||||
return new DocBlock($node->getDocComment());
|
||||
}
|
||||
|
||||
private function removeInjectAnnotationFromProperty(Property $propertyNode, DocBlock $propertyDocBlock): Property
|
||||
{
|
||||
$injectAnnotations = $propertyDocBlock->getAnnotationsOfType(self::ANNOTATION_INJECT);
|
||||
foreach ($injectAnnotations as $injectAnnotation) {
|
||||
$injectAnnotation->remove();
|
||||
}
|
||||
|
||||
$propertyNode->setDocComment(new Doc($propertyDocBlock->getContent()));
|
||||
|
||||
return $propertyNode;
|
||||
}
|
||||
|
||||
private function addPropertyToCollector(Property $propertyNode, DocBlock $propertyDocBlock): void
|
||||
{
|
||||
$propertyType = $propertyDocBlock->getAnnotationsOfType('var')[0]
|
||||
->getTypes()[0];
|
||||
$propertyType = $this->docBlockAnalyzer->getAnnotationFromNode($propertyNode, 'var');
|
||||
|
||||
$propertyName = (string) $propertyNode->props[0]->name;
|
||||
|
||||
$this->classPropertyCollector->addPropertyForClass($this->className, $propertyType, $propertyName);
|
||||
$this->classPropertyCollector->addPropertyForClass(
|
||||
(string) $propertyNode->getAttribute(Attribute::CLASS_NAME),
|
||||
$propertyType,
|
||||
$propertyName
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace Rector\Rector\Contrib\Nette;
|
||||
|
||||
use Rector\Deprecation\SetNames;
|
||||
use Rector\Rector\AbstractClassReplacerRector;
|
||||
use Rector\Rector\Set\SetNames;
|
||||
|
||||
final class NetteConfiguratorRector extends AbstractClassReplacerRector
|
||||
{
|
||||
|
|
|
@ -6,10 +6,10 @@ use PhpParser\Node;
|
|||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use Rector\Builder\StatementGlue;
|
||||
use Rector\Deprecation\SetNames;
|
||||
use Rector\Node\Attribute;
|
||||
use Rector\NodeFactory\NodeFactory;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\Rector\Set\SetNames;
|
||||
|
||||
/**
|
||||
* Covers https://doc.nette.org/en/2.4/migration-2-4#toc-nette-smartobject.
|
||||
|
@ -54,7 +54,7 @@ final class NetteObjectToSmartTraitRector extends AbstractRector
|
|||
|
||||
public function isCandidate(Node $node): bool
|
||||
{
|
||||
if (! $node instanceof Class_ || $node->extends === null) {
|
||||
if (! $node instanceof Class_ || $node->extends === null || $node->isAnonymous()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace Rector\Rector\Contrib\Nette;
|
||||
|
||||
use Rector\Deprecation\SetNames;
|
||||
use Rector\Rector\AbstractChangeMethodNameRector;
|
||||
use Rector\Rector\Set\SetNames;
|
||||
|
||||
final class PhpGeneratorDocumentMethodRector extends AbstractChangeMethodNameRector
|
||||
{
|
||||
|
|
|
@ -5,9 +5,9 @@ namespace Rector\Rector\Contrib\Nette;
|
|||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\ClassConstFetch;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use Rector\Deprecation\SetNames;
|
||||
use Rector\Node\Attribute;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\Rector\Set\SetNames;
|
||||
|
||||
final class RemoveConfiguratorConstantsRector extends AbstractRector
|
||||
{
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace Rector\Rector\Contrib\PHPUnit;
|
||||
|
||||
use Rector\Deprecation\SetNames;
|
||||
use Rector\Rector\AbstractClassReplacerRector;
|
||||
use Rector\Rector\Set\SetNames;
|
||||
|
||||
final class NamespaceClassRector extends AbstractClassReplacerRector
|
||||
{
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace Rector\Rector\Contrib\PHP_CodeSniffer;
|
||||
|
||||
use Rector\Deprecation\SetNames;
|
||||
use Rector\Rector\AbstractClassReplacerRector;
|
||||
use Rector\Rector\Set\SetNames;
|
||||
|
||||
final class NamespaceClassRector extends AbstractClassReplacerRector
|
||||
{
|
||||
|
|
|
@ -5,10 +5,10 @@ namespace Rector\Rector\Contrib\Symfony;
|
|||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\ConstFetch;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use Rector\Deprecation\SetNames;
|
||||
use Rector\Node\Attribute;
|
||||
use Rector\NodeFactory\NodeFactory;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\Rector\Set\SetNames;
|
||||
|
||||
/**
|
||||
* Ref: https://github.com/symfony/symfony/blob/master/UPGRADE-4.0.md#validator
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace Rector\Rector\Contrib\Symfony;
|
||||
|
||||
use Rector\Deprecation\SetNames;
|
||||
use Rector\Rector\AbstractChangeParentClassRector;
|
||||
use Rector\Rector\Set\SetNames;
|
||||
|
||||
/**
|
||||
* Ref: https://github.com/symfony/symfony/blob/master/UPGRADE-4.0.md#validator
|
||||
|
|
|
@ -5,10 +5,10 @@ namespace Rector\Rector\Contrib\Symfony;
|
|||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\BinaryOp\BooleanAnd;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use Rector\Deprecation\SetNames;
|
||||
use Rector\Node\Attribute;
|
||||
use Rector\NodeFactory\NodeFactory;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\Rector\Set\SetNames;
|
||||
|
||||
/**
|
||||
* Converts all:
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
namespace Rector\Rector\Contrib\Symfony;
|
||||
|
||||
use Rector\Deprecation\SetNames;
|
||||
use Rector\Rector\AbstractClassReplacerRector;
|
||||
use Rector\Rector\Set\SetNames;
|
||||
|
||||
/**
|
||||
* Ref.: https://github.com/symfony/symfony/blob/master/UPGRADE-4.0.md#frameworkbundle
|
||||
|
|
|
@ -5,9 +5,9 @@ namespace Rector\Rector\Contrib\Symfony;
|
|||
use PhpParser\Node;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use Rector\Deprecation\SetNames;
|
||||
use Rector\NodeFactory\NodeFactory;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\Rector\Set\SetNames;
|
||||
|
||||
/**
|
||||
* Converts all:
|
||||
|
|
|
@ -5,10 +5,10 @@ namespace Rector\Rector\Contrib\Symfony;
|
|||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\StaticCall;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use Rector\Deprecation\SetNames;
|
||||
use Rector\NodeAnalyzer\MethodCallAnalyzer;
|
||||
use Rector\NodeFactory\NodeFactory;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\Rector\Set\SetNames;
|
||||
|
||||
/**
|
||||
* Converts all:
|
||||
|
|
|
@ -9,11 +9,11 @@ use PhpParser\Node\Name\FullyQualified;
|
|||
use Rector\Builder\Class_\ClassPropertyCollector;
|
||||
use Rector\Builder\Kernel\ServiceFromKernelResolver;
|
||||
use Rector\Builder\Naming\NameResolver;
|
||||
use Rector\Deprecation\SetNames;
|
||||
use Rector\Node\Attribute;
|
||||
use Rector\NodeAnalyzer\SymfonyContainerCallsAnalyzer;
|
||||
use Rector\NodeFactory\NodeFactory;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\Rector\Set\SetNames;
|
||||
use Rector\Tests\Rector\Contrib\SymfonyExtra\GetterToPropertyRector\Source\LocalKernel;
|
||||
|
||||
/**
|
||||
|
|
|
@ -7,11 +7,11 @@ use PhpParser\Node\Expr\MethodCall;
|
|||
use Rector\Builder\Class_\ClassPropertyCollector;
|
||||
use Rector\Builder\Kernel\ServiceFromKernelResolver;
|
||||
use Rector\Builder\Naming\NameResolver;
|
||||
use Rector\Deprecation\SetNames;
|
||||
use Rector\Node\Attribute;
|
||||
use Rector\NodeAnalyzer\SymfonyContainerCallsAnalyzer;
|
||||
use Rector\NodeFactory\NodeFactory;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\Rector\Set\SetNames;
|
||||
use Rector\Tests\Rector\Contrib\SymfonyExtra\GetterToPropertyRector\Source\LocalKernel;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
<?php declare(strict_types=1);
|
||||
|
||||
namespace Rector\Deprecation;
|
||||
namespace Rector\Rector\Set;
|
||||
|
||||
/**
|
||||
* @todo split to make SOLID
|
||||
*/
|
||||
final class SetNames
|
||||
{
|
||||
/**
|
|
@ -1,12 +1,12 @@
|
|||
imports:
|
||||
- { resource: '../../packages/TriggerExtractor/src/config/services.yml' }
|
||||
- { resource: '../../packages/DeprecationExtractor/src/config/services.yml' }
|
||||
|
||||
parameters:
|
||||
name: "Rector"
|
||||
|
||||
# todo
|
||||
kernel_class: # for name based service refactoring
|
||||
|
||||
name: "Rector"
|
||||
|
||||
services:
|
||||
_defaults:
|
||||
autowire: true
|
||||
|
@ -22,9 +22,15 @@ services:
|
|||
|
||||
Rector\NodeTraverser\StandaloneTraverseNodeTraverser:
|
||||
calls:
|
||||
# adds FQN names for elements
|
||||
- ['addNodeVisitor', ['@PhpParser\NodeVisitor\NameResolver']]
|
||||
# adds previous, next and parent node via attribute
|
||||
- ['addNodeVisitor', ['@Rector\NodeVisitor\NodeConnector']]
|
||||
# adds type to variable and property nodes via attribute
|
||||
- ['addNodeVisitor', ['@Rector\NodeTypeResolver\NodeVisitor\TypeResolver']]
|
||||
# adds class/interface/function/method scope to all nodes attribute
|
||||
- ['addNodeVisitor', ['@Rector\NodeTypeResolver\NodeVisitor\ScopeResolver']]
|
||||
# adds current class to all nodes via attribute
|
||||
- ['addNodeVisitor', ['@Rector\NodeTypeResolver\NodeVisitor\ClassResolver']]
|
||||
|
||||
# 3rd party services
|
||||
|
@ -44,6 +50,7 @@ services:
|
|||
PhpParser\NodeVisitor\NameResolver:
|
||||
arguments:
|
||||
$options:
|
||||
# keep nodes the same, so the code can be saved without name changes
|
||||
'replaceNodes': false
|
||||
|
||||
PhpParser\NodeTraverser: ~
|
||||
|
|
Loading…
Reference in New Issue
Block a user