Merge pull request #37 from TomasVotruba/flow

[Flow] init
This commit is contained in:
Tomáš Votruba 2017-09-09 20:11:47 +02:00 committed by GitHub
commit 3053b30783
58 changed files with 890 additions and 296 deletions

View File

@ -9,6 +9,7 @@ $possibleAutoloadPaths = [__DIR__ . '/../vendor/autoload.php', __DIR__ . '/../..
foreach ($possibleAutoloadPaths as $possibleAutoloadPath) {
if (is_file($possibleAutoloadPath)) {
require_once $possibleAutoloadPath;
break;
}
}

View File

@ -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": {

View File

@ -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

View File

@ -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.

View File

@ -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...

View File

@ -0,0 +1,7 @@
<?php declare(strict_types=1);
namespace Rector\DeprecationExtractor\Contract\Deprecation;
interface DeprecationInterface
{
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View 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)
));
}
}

View File

@ -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
));
}
}

View File

@ -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;
}
}

View File

@ -3,5 +3,6 @@ services:
autowire: true
# PSR-4 autodiscovery
Rector\TriggerExtractor\:
Rector\DeprecationExtractor\:
resource: '../../src'
exclude: '../../src/{Deprecation/ClassMethodDeprecation.php}'

View File

@ -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

View File

@ -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'));
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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.

View File

@ -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());
}
}
}

View 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;
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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
));
}
}

View File

@ -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

View File

@ -2,7 +2,7 @@
namespace Rector\Contract\Deprecation;
use Rector\Deprecation\SetNames;
use Rector\Rector\Set\SetNames;
interface DeprecationInterface
{

View File

@ -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'
);
}
}

View File

@ -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!

View 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());
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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.

View File

@ -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

View File

@ -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
{

View File

@ -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
);
}
}

View File

@ -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
{

View File

@ -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;
}

View File

@ -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
{

View File

@ -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
{

View File

@ -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
{

View File

@ -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
{

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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:

View File

@ -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:

View File

@ -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;
/**

View File

@ -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;
/**

View File

@ -1,10 +1,7 @@
<?php declare(strict_types=1);
namespace Rector\Deprecation;
namespace Rector\Rector\Set;
/**
* @todo split to make SOLID
*/
final class SetNames
{
/**

View File

@ -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: ~