mirror of
https://github.com/rectorphp/rector.git
synced 2024-06-05 10:50:48 +00:00
Merge pull request #5 from TomasVotruba/upgrade-deprection-constant
[UpgradeDeprecation] add ReplaceDeprecatedConstantNodeVisitor
This commit is contained in:
commit
244b561657
|
@ -16,9 +16,9 @@ script:
|
||||||
- vendor/bin/phpunit $PHPUNIT_FLAGS
|
- vendor/bin/phpunit $PHPUNIT_FLAGS
|
||||||
# check coding standard (defined in composer.json "scripts" section)
|
# check coding standard (defined in composer.json "scripts" section)
|
||||||
# if this fails, run "composer fs" to fix all fixable issues
|
# if this fails, run "composer fs" to fix all fixable issues
|
||||||
- composer cs
|
- composer check-cs
|
||||||
# check with phpstan (defined in composer.json "scripts" section)
|
# check with phpstan (defined in composer.json "scripts" section)
|
||||||
- composer ps
|
# - composer phpstan
|
||||||
|
|
||||||
after_script:
|
after_script:
|
||||||
# upload coverage.xml file to Coveralls to analyze it
|
# upload coverage.xml file to Coveralls to analyze it
|
||||||
|
@ -29,7 +29,5 @@ after_script:
|
||||||
php coveralls.phar --verbose
|
php coveralls.phar --verbose
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# do not send success notifications, they have no value
|
|
||||||
notifications:
|
notifications:
|
||||||
email:
|
email: never
|
||||||
on_success: never
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "rector/rector",
|
"name": "rector/rector",
|
||||||
"description": "Tool that reconstructs your legacy code to modern codebase.",
|
"description": "Refactor legacy code to modern frameworks.",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"authors": [
|
"authors": [
|
||||||
{ "name": "Tomas Votruba", "email": "tomas.vot@gmail.com", "homepage": "https://tomasvotruba.com" },
|
{ "name": "Tomas Votruba", "email": "tomas.vot@gmail.com", "homepage": "https://tomasvotruba.com" },
|
||||||
|
@ -11,7 +11,6 @@
|
||||||
"symfony/console": "^3.3",
|
"symfony/console": "^3.3",
|
||||||
"symfony/dependency-injection": "^3.3",
|
"symfony/dependency-injection": "^3.3",
|
||||||
"nikic/php-parser": "4.0.x-dev as 3.0.2",
|
"nikic/php-parser": "4.0.x-dev as 3.0.2",
|
||||||
"ocramius/code-generator-utils": "^0.4",
|
|
||||||
"nette/utils": "^2.4"
|
"nette/utils": "^2.4"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
@ -31,7 +30,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"all": ["phpunit", "@cs", "@ps"],
|
"all": ["phpunit", "@check-cs", "@phpstan"],
|
||||||
"check-cs": "ecs check bin src tests",
|
"check-cs": "ecs check bin src tests",
|
||||||
"fix-cs": "ecs check bin src tests --fix",
|
"fix-cs": "ecs check bin src tests --fix",
|
||||||
"phpstan": "phpstan analyse bin src tests --level 7 --configuration phpstan.neon"
|
"phpstan": "phpstan analyse bin src tests --level 7 --configuration phpstan.neon"
|
||||||
|
|
|
@ -1,5 +1,69 @@
|
||||||
includes:
|
includes:
|
||||||
- vendor/symplify/easy-coding-standard/config/psr2-checkers.neon
|
- vendor/symplify/easy-coding-standard/config/psr2-checkers.neon
|
||||||
|
- vendor/symplify/easy-coding-standard/config/php70-checkers.neon
|
||||||
- vendor/symplify/easy-coding-standard/config/php71-checkers.neon
|
- vendor/symplify/easy-coding-standard/config/php71-checkers.neon
|
||||||
|
|
||||||
checkers:
|
checkers:
|
||||||
|
# Slevomat
|
||||||
|
- SlevomatCodingStandard\Sniffs\ControlStructures\YodaComparisonSniff
|
||||||
|
- SlevomatCodingStandard\Sniffs\Exceptions\DeadCatchSniff
|
||||||
|
- SlevomatCodingStandard\Sniffs\Exceptions\ReferenceThrowableOnlySniff
|
||||||
|
SlevomatCodingStandard\Sniffs\Namespaces\ReferenceUsedNamesOnlySniff:
|
||||||
|
allowPartialUses: false
|
||||||
|
allowFullyQualifiedNameForCollidingClasses: false
|
||||||
|
allowFullyQualifiedGlobalClasses: true
|
||||||
|
- SlevomatCodingStandard\Sniffs\Classes\UnusedPrivateElementsSniff
|
||||||
|
|
||||||
|
# Files
|
||||||
|
PHP_CodeSniffer\Standards\Generic\Sniffs\Files\LineLengthSniff:
|
||||||
|
absoluteLineLimit: 120
|
||||||
|
|
||||||
|
# PSR-4
|
||||||
|
- PhpCsFixer\Fixer\Basic\Psr4Fixer
|
||||||
|
|
||||||
|
# Code Analysis
|
||||||
|
- PHP_CodeSniffer\Standards\Generic\Sniffs\CodeAnalysis\EmptyStatementSniff
|
||||||
|
PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics\CyclomaticComplexitySniff:
|
||||||
|
absoluteComplexity: 5
|
||||||
|
PHP_CodeSniffer\Standards\Generic\Sniffs\Metrics\NestingLevelSniff:
|
||||||
|
absoluteNestingLevel: 3
|
||||||
|
|
||||||
|
# Naming Conventions
|
||||||
|
- PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\CamelCapsFunctionNameSniff
|
||||||
|
|
||||||
|
# PHP
|
||||||
|
- PHP_CodeSniffer\Standards\Squiz\Sniffs\PHP\NonExecutableCodeSniff
|
||||||
|
|
||||||
|
# WhiteSpace
|
||||||
|
- PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\LanguageConstructSpacingSniff
|
||||||
|
PHP_CodeSniffer\Standards\Squiz\Sniffs\WhiteSpace\SuperfluousWhitespaceSniff:
|
||||||
|
ignoreBlankLines: false
|
||||||
|
|
||||||
|
# Namespaces
|
||||||
|
- PhpCsFixer\Fixer\Import\OrderedImportsFixer
|
||||||
|
- PhpCsFixer\Fixer\Import\NoUnusedImportsFixer
|
||||||
|
|
||||||
|
PhpCsFixer\Fixer\Operator\ConcatSpaceFixer:
|
||||||
|
spacing: one
|
||||||
|
- PhpCsFixer\Fixer\ClassNotation\OrderedClassElementsFixer
|
||||||
|
- PhpCsFixer\Fixer\Semicolon\SemicolonAfterInstructionFixer
|
||||||
|
- PhpCsFixer\Fixer\Operator\NotOperatorWithSuccessorSpaceFixer
|
||||||
|
- PhpCsFixer\Fixer\ControlStructure\NoUselessElseFixer
|
||||||
|
- PhpCsFixer\Fixer\ReturnNotation\NoUselessReturnFixer
|
||||||
|
- PhpCsFixer\Fixer\Strict\StrictComparisonFixer
|
||||||
|
PhpCsFixer\Fixer\Phpdoc\GeneralPhpdocAnnotationRemoveFixer:
|
||||||
|
annotations:
|
||||||
|
- author
|
||||||
|
- throws
|
||||||
|
- expectedException
|
||||||
|
|
||||||
|
# PHPUnit
|
||||||
|
- PhpCsFixer\Fixer\PhpUnit\PhpUnitStrictFixer
|
||||||
|
|
||||||
|
# new since PhpCsFixer 2.2-2.4
|
||||||
|
- PhpCsFixer\Fixer\Phpdoc\PhpdocReturnSelfReferenceFixer
|
||||||
|
PhpCsFixer\Fixer\LanguageConstruct\IsNullFixer:
|
||||||
|
use_yoda_style: false
|
||||||
|
- PhpCsFixer\Fixer\Basic\NonPrintableCharacterFixer
|
||||||
|
- PhpCsFixer\Fixer\Phpdoc\PhpdocTypesOrderFixer
|
||||||
|
- PhpCsFixer\Fixer\Comment\SingleLineCommentStyleFixer
|
|
@ -5,7 +5,7 @@ namespace Rector\Application;
|
||||||
use PhpParser\Lexer;
|
use PhpParser\Lexer;
|
||||||
use PhpParser\NodeTraverser;
|
use PhpParser\NodeTraverser;
|
||||||
use PhpParser\Parser;
|
use PhpParser\Parser;
|
||||||
use Rector\Printer\CodeStyledPrinter;
|
use Rector\Printer\FormatPerservingPrinter;
|
||||||
use SplFileInfo;
|
use SplFileInfo;
|
||||||
|
|
||||||
final class FileProcessor
|
final class FileProcessor
|
||||||
|
@ -16,9 +16,9 @@ final class FileProcessor
|
||||||
private $parser;
|
private $parser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var CodeStyledPrinter
|
* @var FormatPerservingPrinter
|
||||||
*/
|
*/
|
||||||
private $codeStyledPrinter;
|
private $formatPerservingPrinter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var NodeTraverser
|
* @var NodeTraverser
|
||||||
|
@ -30,10 +30,14 @@ final class FileProcessor
|
||||||
*/
|
*/
|
||||||
private $lexer;
|
private $lexer;
|
||||||
|
|
||||||
public function __construct(Parser $parser, CodeStyledPrinter $codeStyledPrinter, Lexer $lexer, NodeTraverser $nodeTraverser)
|
public function __construct(
|
||||||
{
|
Parser $parser,
|
||||||
|
FormatPerservingPrinter $codeStyledPrinter,
|
||||||
|
Lexer $lexer,
|
||||||
|
NodeTraverser $nodeTraverser
|
||||||
|
) {
|
||||||
$this->parser = $parser;
|
$this->parser = $parser;
|
||||||
$this->codeStyledPrinter = $codeStyledPrinter;
|
$this->formatPerservingPrinter = $codeStyledPrinter;
|
||||||
$this->nodeTraverser = $nodeTraverser;
|
$this->nodeTraverser = $nodeTraverser;
|
||||||
$this->lexer = $lexer;
|
$this->lexer = $lexer;
|
||||||
}
|
}
|
||||||
|
@ -57,12 +61,10 @@ final class FileProcessor
|
||||||
}
|
}
|
||||||
|
|
||||||
$oldStmts = $this->cloneArrayOfObjects($oldStmts);
|
$oldStmts = $this->cloneArrayOfObjects($oldStmts);
|
||||||
|
|
||||||
$oldTokens = $this->lexer->getTokens();
|
$oldTokens = $this->lexer->getTokens();
|
||||||
|
|
||||||
$newStmts = $this->nodeTraverser->traverse($oldStmts);
|
$newStmts = $this->nodeTraverser->traverse($oldStmts);
|
||||||
|
|
||||||
$this->codeStyledPrinter->printToFile($file, $newStmts, $oldStmts, $oldTokens);
|
$this->formatPerservingPrinter->printToFile($file, $newStmts, $oldStmts, $oldTokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -11,9 +11,7 @@ final class ClassPropertyCollector
|
||||||
|
|
||||||
public function addPropertyForClass(string $class, string $propertyType, string $propertyName): void
|
public function addPropertyForClass(string $class, string $propertyType, string $propertyName): void
|
||||||
{
|
{
|
||||||
$this->classProperties[$class] = [
|
$this->classProperties[$class][$propertyType] = $propertyName;
|
||||||
$propertyType => $propertyName,
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
namespace Rector\Builder;
|
namespace Rector\Builder;
|
||||||
|
|
||||||
use Nette\Utils\Arrays;
|
|
||||||
use PhpParser\Builder\Method;
|
use PhpParser\Builder\Method;
|
||||||
use PhpParser\Builder\Param;
|
use PhpParser\Builder\Param;
|
||||||
use PhpParser\BuilderFactory;
|
use PhpParser\BuilderFactory;
|
||||||
|
@ -23,10 +22,16 @@ final class ConstructorMethodBuilder
|
||||||
*/
|
*/
|
||||||
private $builderFactory;
|
private $builderFactory;
|
||||||
|
|
||||||
public function __construct(Parser $parser, BuilderFactory $builderFactory)
|
/**
|
||||||
|
* @var StatementGlue
|
||||||
|
*/
|
||||||
|
private $statementGlue;
|
||||||
|
|
||||||
|
public function __construct(Parser $parser, BuilderFactory $builderFactory, StatementGlue $statementGlue)
|
||||||
{
|
{
|
||||||
$this->parser = $parser;
|
$this->parser = $parser;
|
||||||
$this->builderFactory = $builderFactory;
|
$this->builderFactory = $builderFactory;
|
||||||
|
$this->statementGlue = $statementGlue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addPropertyAssignToClass(Class_ $classNode, string $propertyType, string $propertyName): void
|
public function addPropertyAssignToClass(Class_ $classNode, string $propertyType, string $propertyName): void
|
||||||
|
@ -50,7 +55,7 @@ final class ConstructorMethodBuilder
|
||||||
->addParam($this->createParameter($propertyType, $propertyName))
|
->addParam($this->createParameter($propertyType, $propertyName))
|
||||||
->addStmts($assign);
|
->addStmts($assign);
|
||||||
|
|
||||||
$this->addAsFirstMethod($classNode, $constructorMethod->getNode());
|
$this->statementGlue->addAsFirstMethod($classNode, $constructorMethod->getNode());
|
||||||
}
|
}
|
||||||
|
|
||||||
private function createParameter(string $propertyType, string $propertyName): Param
|
private function createParameter(string $propertyType, string $propertyName): Param
|
||||||
|
@ -70,21 +75,4 @@ final class ConstructorMethodBuilder
|
||||||
$propertyName
|
$propertyName
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function addAsFirstMethod(Class_ $classNode, ClassMethod $constructorMethod): void
|
|
||||||
{
|
|
||||||
foreach ($classNode->stmts as $key => $classElementNode) {
|
|
||||||
if ($classElementNode instanceof ClassMethod) {
|
|
||||||
Arrays::insertBefore(
|
|
||||||
$classNode->stmts,
|
|
||||||
$key,
|
|
||||||
['before_' . $key => $constructorMethod]
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$classNode->stmts[] = $constructorMethod;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,9 @@
|
||||||
|
|
||||||
namespace Rector\Builder;
|
namespace Rector\Builder;
|
||||||
|
|
||||||
use Nette\Utils\Arrays;
|
|
||||||
use PhpParser\BuilderFactory;
|
use PhpParser\BuilderFactory;
|
||||||
use PhpParser\Comment\Doc;
|
use PhpParser\Comment\Doc;
|
||||||
use PhpParser\Node\Stmt\Class_;
|
use PhpParser\Node\Stmt\Class_;
|
||||||
use PhpParser\Node\Stmt\ClassMethod;
|
|
||||||
use PhpParser\Node\Stmt\Property;
|
use PhpParser\Node\Stmt\Property;
|
||||||
|
|
||||||
final class PropertyBuilder
|
final class PropertyBuilder
|
||||||
|
@ -16,45 +14,26 @@ final class PropertyBuilder
|
||||||
*/
|
*/
|
||||||
private $builderFactory;
|
private $builderFactory;
|
||||||
|
|
||||||
public function __construct(BuilderFactory $builderFactory)
|
/**
|
||||||
|
* @var StatementGlue
|
||||||
|
*/
|
||||||
|
private $statementGlue;
|
||||||
|
|
||||||
|
public function __construct(BuilderFactory $builderFactory, StatementGlue $statementGlue)
|
||||||
{
|
{
|
||||||
$this->builderFactory = $builderFactory;
|
$this->builderFactory = $builderFactory;
|
||||||
|
$this->statementGlue = $statementGlue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addPropertyToClass(Class_ $classNode, string $propertyType, string $propertyName): void
|
public function addPropertyToClass(Class_ $classNode, string $propertyType, string $propertyName): void
|
||||||
{
|
{
|
||||||
|
if ($this->doesPropertyAlreadyExist($classNode, $propertyName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$propertyNode = $this->buildPrivatePropertyNode($propertyType, $propertyName);
|
$propertyNode = $this->buildPrivatePropertyNode($propertyType, $propertyName);
|
||||||
|
|
||||||
// add before first method
|
$this->statementGlue->addAsFirstMethod($classNode, $propertyNode);
|
||||||
foreach ($classNode->stmts as $key => $classElementNode) {
|
|
||||||
if ($classElementNode instanceof ClassMethod) {
|
|
||||||
Arrays::insertBefore(
|
|
||||||
$classNode->stmts,
|
|
||||||
$key,
|
|
||||||
['before_' . $key => $propertyNode]
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// or after last property
|
|
||||||
$previousElement = null;
|
|
||||||
foreach ($classNode->stmts as $key => $classElementNode) {
|
|
||||||
if ($previousElement instanceof Property && ! $classElementNode instanceof Property) {
|
|
||||||
Arrays::insertBefore(
|
|
||||||
$classNode->stmts,
|
|
||||||
$key,
|
|
||||||
['before_' . $key => $propertyNode]
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$previousElement = $classElementNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
$classNode->stmts[] = $propertyNode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function buildPrivatePropertyNode(string $propertyType, string $propertyName): Property
|
private function buildPrivatePropertyNode(string $propertyType, string $propertyName): Property
|
||||||
|
@ -74,4 +53,20 @@ final class PropertyBuilder
|
||||||
. PHP_EOL . ' * @var ' . $propertyType
|
. PHP_EOL . ' * @var ' . $propertyType
|
||||||
. PHP_EOL . ' */');
|
. PHP_EOL . ' */');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function doesPropertyAlreadyExist(Class_ $classNode, string $propertyName): bool
|
||||||
|
{
|
||||||
|
foreach ($classNode->stmts as $inClassNode) {
|
||||||
|
if (! $inClassNode instanceof Property) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$classPropertyName = (string) $inClassNode->props[0]->name;
|
||||||
|
if ($classPropertyName === $propertyName) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
70
src/Builder/StatementGlue.php
Normal file
70
src/Builder/StatementGlue.php
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\Builder;
|
||||||
|
|
||||||
|
use Nette\Utils\Arrays;
|
||||||
|
use PhpParser\Node;
|
||||||
|
use PhpParser\Node\Stmt\Class_;
|
||||||
|
use PhpParser\Node\Stmt\ClassMethod;
|
||||||
|
use PhpParser\Node\Stmt\Property;
|
||||||
|
use PhpParser\Node\Stmt\TraitUse;
|
||||||
|
|
||||||
|
final class StatementGlue
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param ClassMethod|Property $node
|
||||||
|
*/
|
||||||
|
public function addAsFirstMethod(Class_ $classNode, Node $node): void
|
||||||
|
{
|
||||||
|
foreach ($classNode->stmts as $key => $classElementNode) {
|
||||||
|
if ($classElementNode instanceof ClassMethod) {
|
||||||
|
$this->insertBefore($classNode, $node, $key);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$previousElement = null;
|
||||||
|
foreach ($classNode->stmts as $key => $classElementNode) {
|
||||||
|
if ($previousElement instanceof Property && ! $classElementNode instanceof Property) {
|
||||||
|
$this->insertBefore($classNode, $node, $key);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$previousElement = $classElementNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
$classNode->stmts[] = $node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addAsFirstTrait(Class_ $classNode, Node $node): void
|
||||||
|
{
|
||||||
|
$this->addStatementToClassBeforeTypes($classNode, $node, TraitUse::class, Property::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addStatementToClassBeforeTypes(Class_ $classNode, Node $node, string ...$types): void
|
||||||
|
{
|
||||||
|
foreach ($types as $type) {
|
||||||
|
foreach ($classNode->stmts as $key => $classElementNode) {
|
||||||
|
if (is_a($classElementNode, $type, true)) {
|
||||||
|
$this->insertBefore($classNode, $node, $key);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$classNode->stmts[] = $node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int|string $key
|
||||||
|
*/
|
||||||
|
private function insertBefore(Class_ $classNode, Node $node, $key): void
|
||||||
|
{
|
||||||
|
Arrays::insertBefore($classNode->stmts, $key, [
|
||||||
|
'before_' . $key => $node
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,6 +17,11 @@ final class ReconstructCommand extends Command
|
||||||
*/
|
*/
|
||||||
private const NAME = 'reconstruct';
|
private const NAME = 'reconstruct';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private const ARGUMENT_SOURCE_NAME = 'source';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var FileProcessor
|
* @var FileProcessor
|
||||||
*/
|
*/
|
||||||
|
@ -29,11 +34,6 @@ final class ReconstructCommand extends Command
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private const ARGUMENT_SOURCE_NAME = 'source';
|
|
||||||
|
|
||||||
protected function configure(): void
|
protected function configure(): void
|
||||||
{
|
{
|
||||||
$this->setName(self::NAME);
|
$this->setName(self::NAME);
|
||||||
|
|
21
src/Contract/Deprecation/DeprecationInterface.php
Normal file
21
src/Contract/Deprecation/DeprecationInterface.php
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\Contract\Deprecation;
|
||||||
|
|
||||||
|
use Rector\Deprecation\SetNames;
|
||||||
|
|
||||||
|
interface DeprecationInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* A project that is related to this.
|
||||||
|
* E.g "Nette", "Symfony"
|
||||||
|
* Use constants from @see SetNames, if possible.
|
||||||
|
*/
|
||||||
|
public function getSetName(): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Version this deprecations is active since.
|
||||||
|
* E.g. 2.3
|
||||||
|
*/
|
||||||
|
public function sinceVersion(): float;
|
||||||
|
}
|
15
src/Contract/Rector/RectorInterface.php
Normal file
15
src/Contract/Rector/RectorInterface.php
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\Contract\Rector;
|
||||||
|
|
||||||
|
use PhpParser\Node;
|
||||||
|
|
||||||
|
interface RectorInterface
|
||||||
|
{
|
||||||
|
public function isCandidate(Node $node): bool;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Node $node
|
||||||
|
*/
|
||||||
|
public function refactor($node): ?Node;
|
||||||
|
}
|
|
@ -10,14 +10,24 @@ use Symfony\Component\HttpKernel\Kernel;
|
||||||
|
|
||||||
final class AppKernel extends Kernel
|
final class AppKernel extends Kernel
|
||||||
{
|
{
|
||||||
public function __construct()
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $config;
|
||||||
|
|
||||||
|
public function __construct(?string $config = '')
|
||||||
{
|
{
|
||||||
|
$this->config = $config;
|
||||||
parent::__construct('dev', true);
|
parent::__construct('dev', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function registerContainerConfiguration(LoaderInterface $loader): void
|
public function registerContainerConfiguration(LoaderInterface $loader): void
|
||||||
{
|
{
|
||||||
$loader->load(__DIR__ . '/../config/services.yml');
|
$loader->load(__DIR__ . '/../config/services.yml');
|
||||||
|
|
||||||
|
if ($this->config) {
|
||||||
|
$loader->load($this->config);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCacheDir(): string
|
public function getCacheDir(): string
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
namespace Rector\DependencyInjection\CompilerPass;
|
namespace Rector\DependencyInjection\CompilerPass;
|
||||||
|
|
||||||
use PhpParser\NodeTraverser;
|
|
||||||
use PhpParser\NodeVisitor;
|
use PhpParser\NodeVisitor;
|
||||||
|
use Rector\NodeTraverser\NodeTraverserFactory;
|
||||||
use Symfony\Component\Console\Application;
|
use Symfony\Component\Console\Application;
|
||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
|
||||||
|
@ -32,9 +32,9 @@ final class CollectorCompilerPass implements CompilerPassInterface
|
||||||
{
|
{
|
||||||
DefinitionCollector::loadCollectorWithType(
|
DefinitionCollector::loadCollectorWithType(
|
||||||
$containerBuilder,
|
$containerBuilder,
|
||||||
NodeTraverser::class,
|
NodeTraverserFactory::class,
|
||||||
NodeVisitor::class,
|
NodeVisitor::class,
|
||||||
'addVisitor'
|
'addNodeVisitor'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,4 +13,12 @@ final class ContainerFactory
|
||||||
|
|
||||||
return $appKernel->getContainer();
|
return $appKernel->getContainer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function createWithConfig(string $config): ContainerInterface
|
||||||
|
{
|
||||||
|
$appKernel = new AppKernel($config);
|
||||||
|
$appKernel->boot();
|
||||||
|
|
||||||
|
return $appKernel->getContainer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
16
src/Deprecation/SetNames.php
Normal file
16
src/Deprecation/SetNames.php
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\Deprecation;
|
||||||
|
|
||||||
|
final class SetNames
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public const NETTE = 'Nette';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public const SYMFONY = 'Symfony';
|
||||||
|
}
|
50
src/NodeTraverser/NodeTraverserFactory.php
Normal file
50
src/NodeTraverser/NodeTraverserFactory.php
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\NodeTraverser;
|
||||||
|
|
||||||
|
use PhpParser\NodeTraverser;
|
||||||
|
use PhpParser\NodeVisitor;
|
||||||
|
use PhpParser\NodeVisitor\CloningVisitor;
|
||||||
|
use Rector\NodeVisitor\Traverse\NodeConnectorNodeVisitor;
|
||||||
|
use Rector\NodeVisitor\Traverse\ParentConnectorNodeVisitor;
|
||||||
|
|
||||||
|
final class NodeTraverserFactory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var NodeVisitor[]
|
||||||
|
*/
|
||||||
|
private $nodeVisitors = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string[]
|
||||||
|
*/
|
||||||
|
private $priorityNodeVisitorClasses = [
|
||||||
|
CloningVisitor::class,
|
||||||
|
ParentConnectorNodeVisitor::class,
|
||||||
|
NodeConnectorNodeVisitor::class
|
||||||
|
];
|
||||||
|
|
||||||
|
public function addNodeVisitor(NodeVisitor $nodeVisitor): void
|
||||||
|
{
|
||||||
|
$this->nodeVisitors[] = $nodeVisitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(): NodeTraverser
|
||||||
|
{
|
||||||
|
$nodeTraverser = new NodeTraverser;
|
||||||
|
|
||||||
|
foreach ($this->priorityNodeVisitorClasses as $priorityNodeVisitor) {
|
||||||
|
$nodeTraverser->addVisitor(new $priorityNodeVisitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($this->nodeVisitors as $nodeVisitor) {
|
||||||
|
if (in_array(get_class($nodeVisitor), $this->priorityNodeVisitorClasses, true)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$nodeTraverser->addVisitor($nodeVisitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $nodeTraverser;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,21 +0,0 @@
|
||||||
<?php declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Rector\NodeTraverser;
|
|
||||||
|
|
||||||
final class StateHolder
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
private $isAfterTraverseCalled = false;
|
|
||||||
|
|
||||||
public function setAfterTraverserIsCalled(): void
|
|
||||||
{
|
|
||||||
$this->isAfterTraverseCalled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isAfterTraverseCalled(): bool
|
|
||||||
{
|
|
||||||
return $this->isAfterTraverseCalled;
|
|
||||||
}
|
|
||||||
}
|
|
26
src/NodeTraverser/TokenSwitcher.php
Normal file
26
src/NodeTraverser/TokenSwitcher.php
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\NodeTraverser;
|
||||||
|
|
||||||
|
final class TokenSwitcher
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $isEnabled = false;
|
||||||
|
|
||||||
|
public function enable(): void
|
||||||
|
{
|
||||||
|
$this->isEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function disable(): void
|
||||||
|
{
|
||||||
|
$this->isEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isEnabled(): bool
|
||||||
|
{
|
||||||
|
return $this->isEnabled;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
namespace Rector\NodeVisitor\DependencyInjection\NamedServicesToConstructor;
|
namespace Rector\NodeVisitor\DependencyInjection;
|
||||||
|
|
||||||
use PhpParser\Node;
|
use PhpParser\Node;
|
||||||
use PhpParser\Node\Stmt\Class_;
|
use PhpParser\Node\Stmt\Class_;
|
||||||
|
@ -8,7 +8,7 @@ use PhpParser\NodeVisitorAbstract;
|
||||||
use Rector\Builder\Class_\ClassPropertyCollector;
|
use Rector\Builder\Class_\ClassPropertyCollector;
|
||||||
use Rector\Builder\ConstructorMethodBuilder;
|
use Rector\Builder\ConstructorMethodBuilder;
|
||||||
use Rector\Builder\PropertyBuilder;
|
use Rector\Builder\PropertyBuilder;
|
||||||
use Rector\NodeTraverser\StateHolder;
|
use Rector\NodeTraverser\TokenSwitcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add new propertis to class and to contructor.
|
* Add new propertis to class and to contructor.
|
||||||
|
@ -31,20 +31,20 @@ final class AddPropertiesToClassNodeVisitor extends NodeVisitorAbstract
|
||||||
private $newClassPropertyCollector;
|
private $newClassPropertyCollector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var StateHolder
|
* @var TokenSwitcher
|
||||||
*/
|
*/
|
||||||
private $stateHolder;
|
private $tokenSwitcher;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
ConstructorMethodBuilder $constructorMethodBuilder,
|
ConstructorMethodBuilder $constructorMethodBuilder,
|
||||||
PropertyBuilder $propertyBuilder,
|
PropertyBuilder $propertyBuilder,
|
||||||
ClassPropertyCollector $newClassPropertyCollector,
|
ClassPropertyCollector $newClassPropertyCollector,
|
||||||
StateHolder $stateHolder
|
TokenSwitcher $tokenSwitcher
|
||||||
) {
|
) {
|
||||||
$this->constructorMethodBuilder = $constructorMethodBuilder;
|
$this->constructorMethodBuilder = $constructorMethodBuilder;
|
||||||
$this->propertyBuilder = $propertyBuilder;
|
$this->propertyBuilder = $propertyBuilder;
|
||||||
$this->newClassPropertyCollector = $newClassPropertyCollector;
|
$this->newClassPropertyCollector = $newClassPropertyCollector;
|
||||||
$this->stateHolder = $stateHolder;
|
$this->tokenSwitcher = $tokenSwitcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,24 +53,28 @@ final class AddPropertiesToClassNodeVisitor extends NodeVisitorAbstract
|
||||||
*/
|
*/
|
||||||
public function afterTraverse(array $nodes): array
|
public function afterTraverse(array $nodes): array
|
||||||
{
|
{
|
||||||
foreach ($nodes as $node) {
|
foreach ($nodes as $key => $node) {
|
||||||
if ($node instanceof Class_) {
|
if ($node instanceof Class_) {
|
||||||
$this->reconstruct($node, (string) $node->name);
|
$nodes[$key] = $this->reconstruct($node, (string) $node->name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this does!
|
||||||
|
$this->tokenSwitcher->disable();
|
||||||
|
|
||||||
return $nodes;
|
return $nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function reconstruct(Class_ $classNode, string $className): void
|
private function reconstruct(Class_ $classNode, string $className): Class_
|
||||||
{
|
{
|
||||||
$propertiesForClass = $this->newClassPropertyCollector->getPropertiesforClass($className);
|
$propertiesForClass = $this->newClassPropertyCollector->getPropertiesforClass($className);
|
||||||
|
|
||||||
foreach ($propertiesForClass as $propertyType => $propertyName) {
|
foreach ($propertiesForClass as $propertyType => $propertyName) {
|
||||||
$this->stateHolder->setAfterTraverserIsCalled();
|
|
||||||
$this->constructorMethodBuilder->addPropertyAssignToClass($classNode, $propertyType, $propertyName);
|
$this->constructorMethodBuilder->addPropertyAssignToClass($classNode, $propertyType, $propertyName);
|
||||||
$this->propertyBuilder->addPropertyToClass($classNode, $propertyType, $propertyName);
|
$this->propertyBuilder->addPropertyToClass($classNode, $propertyType, $propertyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return $classNode;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,127 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\NodeVisitor\DependencyInjection\InjectAnnotationToConstructor;
|
||||||
|
|
||||||
|
use PhpCsFixer\DocBlock\DocBlock;
|
||||||
|
use PhpParser\Comment\Doc;
|
||||||
|
use PhpParser\Node;
|
||||||
|
use PhpParser\Node\Stmt\Class_;
|
||||||
|
use PhpParser\Node\Stmt\Property;
|
||||||
|
use PhpParser\NodeVisitorAbstract;
|
||||||
|
use Rector\Builder\Class_\ClassPropertyCollector;
|
||||||
|
use Rector\NodeTraverser\TokenSwitcher;
|
||||||
|
|
||||||
|
final class PropertyRector extends NodeVisitorAbstract
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private const ANNOTATION_INJECT = 'inject';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var TokenSwitcher
|
||||||
|
*/
|
||||||
|
private $tokenSwitcher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ClassPropertyCollector
|
||||||
|
*/
|
||||||
|
private $classPropertyCollector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $className;
|
||||||
|
|
||||||
|
public function __construct(TokenSwitcher $tokenSwitcher, ClassPropertyCollector $classPropertyCollector)
|
||||||
|
{
|
||||||
|
$this->tokenSwitcher = $tokenSwitcher;
|
||||||
|
$this->classPropertyCollector = $classPropertyCollector;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Node[] $nodes
|
||||||
|
* @return null|array
|
||||||
|
*/
|
||||||
|
public function beforeTraverse(array $nodes): ?array
|
||||||
|
{
|
||||||
|
$this->className = null;
|
||||||
|
|
||||||
|
foreach ($nodes as $node) {
|
||||||
|
if ($node instanceof Class_) {
|
||||||
|
$this->className = (string) $node->name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function enterNode(Node $node): ?Node
|
||||||
|
{
|
||||||
|
if (! $this->isCandidate($node)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->reconstructProperty($node);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isCandidate(Node $node): bool
|
||||||
|
{
|
||||||
|
if (! $node instanceof Property) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $this->hasInjectAnnotation($node)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->tokenSwitcher->enable();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function reconstructProperty($propertyNode): Property
|
||||||
|
{
|
||||||
|
$propertyDocBlock = $this->createDocBlockFromNode($propertyNode);
|
||||||
|
$propertyNode = $this->removeInjectAnnotationFromProperty($propertyNode, $propertyDocBlock);
|
||||||
|
|
||||||
|
$propertyNode->flags = Class_::MODIFIER_PRIVATE;
|
||||||
|
|
||||||
|
$this->addPropertyToCollector($propertyNode, $propertyDocBlock);
|
||||||
|
|
||||||
|
return $propertyNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function hasInjectAnnotation(Property $propertyNode): bool
|
||||||
|
{
|
||||||
|
$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];
|
||||||
|
|
||||||
|
$propertyName = (string)$propertyNode->props[0]->name;
|
||||||
|
|
||||||
|
$this->classPropertyCollector->addPropertyForClass($this->className, $propertyType, $propertyName);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,106 +0,0 @@
|
||||||
<?php declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace Rector\NodeVisitor\DependencyInjection;
|
|
||||||
|
|
||||||
use PhpCsFixer\DocBlock\DocBlock;
|
|
||||||
use PhpParser\Comment\Doc;
|
|
||||||
use PhpParser\Node;
|
|
||||||
use PhpParser\Node\Stmt\Class_;
|
|
||||||
use PhpParser\Node\Stmt\Property;
|
|
||||||
use PhpParser\NodeVisitorAbstract;
|
|
||||||
use Rector\Builder\ConstructorMethodBuilder;
|
|
||||||
|
|
||||||
final class InjectAnnotationToConstructorNodeVisitor extends NodeVisitorAbstract
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private const ANNOTATION_INJECT = 'inject';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var ConstructorMethodBuilder
|
|
||||||
*/
|
|
||||||
private $constructorMethodBuilder;
|
|
||||||
|
|
||||||
public function __construct(ConstructorMethodBuilder $constructorMethodBuilder)
|
|
||||||
{
|
|
||||||
$this->constructorMethodBuilder = $constructorMethodBuilder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isCandidate(Node $node): bool
|
|
||||||
{
|
|
||||||
return $node instanceof Class_;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when entering a node.
|
|
||||||
*
|
|
||||||
* Return value semantics:
|
|
||||||
* * null
|
|
||||||
* => $node stays as-is
|
|
||||||
* * NodeTraverser::DONT_TRAVERSE_CHILDREN
|
|
||||||
* => Children of $node are not traversed. $node stays as-is
|
|
||||||
* * NodeTraverser::STOP_TRAVERSAL
|
|
||||||
* => Traversal is aborted. $node stays as-is
|
|
||||||
* * otherwise
|
|
||||||
* => $node is set to the return value
|
|
||||||
*
|
|
||||||
* @return null|int|Node Replacement node (or special return value)
|
|
||||||
*/
|
|
||||||
public function enterNode(Node $node)
|
|
||||||
{
|
|
||||||
if ($node instanceof Class_) {
|
|
||||||
$this->reconstruct($node);
|
|
||||||
return $node;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function reconstruct(Class_ $classNode): void
|
|
||||||
{
|
|
||||||
foreach ($classNode->stmts as $classElementStatement) {
|
|
||||||
if (! $classElementStatement instanceof Property) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$propertyNode = $classElementStatement;
|
|
||||||
|
|
||||||
$propertyDocBlock = $this->createDocBlockFromProperty($propertyNode);
|
|
||||||
$injectAnnotations = $propertyDocBlock->getAnnotationsOfType(self::ANNOTATION_INJECT);
|
|
||||||
if (! $injectAnnotations) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->removeInjectAnnotationFromProperty($propertyNode, $propertyDocBlock);
|
|
||||||
$this->makePropertyPrivate($propertyNode);
|
|
||||||
|
|
||||||
$propertyType = $propertyDocBlock->getAnnotationsOfType('var')[0]
|
|
||||||
->getTypes()[0];
|
|
||||||
$propertyName = (string) $propertyNode->props[0]->name;
|
|
||||||
|
|
||||||
$this->constructorMethodBuilder->addPropertyAssignToClass($classNode, $propertyType, $propertyName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createDocBlockFromProperty(Property $propertyNode): DocBlock
|
|
||||||
{
|
|
||||||
return new DocBlock($propertyNode->getDocComment());
|
|
||||||
}
|
|
||||||
|
|
||||||
private function makePropertyPrivate(Property $propertyNode): void
|
|
||||||
{
|
|
||||||
$propertyNode->flags = Class_::MODIFIER_PRIVATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function removeInjectAnnotationFromProperty(Property $propertyNode, DocBlock $propertyDocBlock): void
|
|
||||||
{
|
|
||||||
$injectAnnotations = $propertyDocBlock->getAnnotationsOfType(self::ANNOTATION_INJECT);
|
|
||||||
|
|
||||||
foreach ($injectAnnotations as $injectAnnotation) {
|
|
||||||
$injectAnnotation->remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
$propertyNode->setDocComment(new Doc($propertyDocBlock->getContent()));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -8,11 +8,12 @@ use PhpParser\Node\Expr\MethodCall;
|
||||||
use PhpParser\Node\Expr\PropertyFetch;
|
use PhpParser\Node\Expr\PropertyFetch;
|
||||||
use PhpParser\Node\Expr\Variable;
|
use PhpParser\Node\Expr\Variable;
|
||||||
use PhpParser\Node\Scalar\String_;
|
use PhpParser\Node\Scalar\String_;
|
||||||
|
use PhpParser\Node\Stmt\Class_;
|
||||||
use PhpParser\NodeVisitorAbstract;
|
use PhpParser\NodeVisitorAbstract;
|
||||||
|
use Rector\Builder\Class_\ClassPropertyCollector;
|
||||||
use Rector\Builder\Kernel\ServiceFromKernelResolver;
|
use Rector\Builder\Kernel\ServiceFromKernelResolver;
|
||||||
use Rector\Builder\Naming\NameResolver;
|
use Rector\Builder\Naming\NameResolver;
|
||||||
use Rector\Builder\Class_\ClassPropertyCollector;
|
use Rector\Tests\NodeVisitor\DependencyInjection\NamedServicesToConstructorRector\Source\LocalKernel;
|
||||||
use Rector\Tests\NodeVisitor\DependencyInjection\NamedServicesToConstructorReconstructor\Source\LocalKernel;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts all:
|
* Converts all:
|
||||||
|
@ -21,7 +22,7 @@ use Rector\Tests\NodeVisitor\DependencyInjection\NamedServicesToConstructorRecon
|
||||||
* into:
|
* into:
|
||||||
* $this->someService # where "someService" is type of the service
|
* $this->someService # where "someService" is type of the service
|
||||||
*/
|
*/
|
||||||
final class GetterToPropertyNodeVisitor extends NodeVisitorAbstract
|
final class GetterToPropertyRector extends NodeVisitorAbstract
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
|
@ -55,12 +56,14 @@ final class GetterToPropertyNodeVisitor extends NodeVisitorAbstract
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Node[] $nodes
|
* @param Node[] $nodes
|
||||||
* @return array|null
|
* @return null|array
|
||||||
*/
|
*/
|
||||||
public function beforeTraverse(array $nodes): ?array
|
public function beforeTraverse(array $nodes): ?array
|
||||||
{
|
{
|
||||||
|
$this->className = null;
|
||||||
|
|
||||||
foreach ($nodes as $node) {
|
foreach ($nodes as $node) {
|
||||||
if ($node instanceof Node\Stmt\Class_) {
|
if ($node instanceof Class_) {
|
||||||
$this->className = (string) $node->name;
|
$this->className = (string) $node->name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,25 +71,10 @@ final class GetterToPropertyNodeVisitor extends NodeVisitorAbstract
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function enterNode(Node $node): ?Node
|
||||||
* Return value semantics:
|
|
||||||
* * null
|
|
||||||
* => $node stays as-is
|
|
||||||
* * NodeTraverser::DONT_TRAVERSE_CHILDREN
|
|
||||||
* => Children of $node are not traversed. $node stays as-is
|
|
||||||
* * NodeTraverser::STOP_TRAVERSAL
|
|
||||||
* => Traversal is aborted. $node stays as-is
|
|
||||||
* * otherwise
|
|
||||||
* => $node is set to the return value.
|
|
||||||
*
|
|
||||||
* @return null|int|Node
|
|
||||||
*/
|
|
||||||
public function enterNode(Node $node)
|
|
||||||
{
|
{
|
||||||
if ($this->isCandidate($node)) {
|
if ($this->isCandidate($node)) {
|
||||||
$this->reconstruct($node);
|
return $this->reconstruct($node);
|
||||||
|
|
||||||
return $node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
@ -96,11 +84,9 @@ final class GetterToPropertyNodeVisitor extends NodeVisitorAbstract
|
||||||
{
|
{
|
||||||
// $var = $this->get('some_service');
|
// $var = $this->get('some_service');
|
||||||
// $var = $this->get('some_service')->getData();
|
// $var = $this->get('some_service')->getData();
|
||||||
if ($node instanceof Assign) {
|
if ($node instanceof Assign && ($node->expr instanceof MethodCall || $node->var instanceof MethodCall)) {
|
||||||
if ($node->expr instanceof MethodCall || $node->var instanceof MethodCall) {
|
if ($this->isContainerGetCall($node->expr)) {
|
||||||
if ($this->isContainerGetCall($node->expr)) {
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
45
src/NodeVisitor/Traverse/NodeConnectorNodeVisitor.php
Normal file
45
src/NodeVisitor/Traverse/NodeConnectorNodeVisitor.php
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\NodeVisitor\Traverse;
|
||||||
|
|
||||||
|
use PhpParser\Node;
|
||||||
|
use PhpParser\NodeVisitorAbstract;
|
||||||
|
|
||||||
|
final class NodeConnectorNodeVisitor extends NodeVisitorAbstract
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Node[]
|
||||||
|
*/
|
||||||
|
private $stack = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Node
|
||||||
|
*/
|
||||||
|
private $prev;
|
||||||
|
|
||||||
|
public function beforeTraverse(array $nodes): void
|
||||||
|
{
|
||||||
|
$this->stack = [];
|
||||||
|
$this->prev = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function enterNode(Node $node): void
|
||||||
|
{
|
||||||
|
if (! empty($this->stack)) {
|
||||||
|
$node->setAttribute('parent', $this->stack[count($this->stack)-1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->prev && $this->prev->getAttribute('parent') === $node->getAttribute('parent')) {
|
||||||
|
$node->setAttribute('prev', $this->prev);
|
||||||
|
$this->prev->setAttribute('next', $node);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->stack[] = $node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function leaveNode(Node $node): void
|
||||||
|
{
|
||||||
|
$this->prev = $node;
|
||||||
|
array_pop($this->stack);
|
||||||
|
}
|
||||||
|
}
|
33
src/NodeVisitor/Traverse/ParentConnectorNodeVisitor.php
Normal file
33
src/NodeVisitor/Traverse/ParentConnectorNodeVisitor.php
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\NodeVisitor\Traverse;
|
||||||
|
|
||||||
|
use PhpParser\Node;
|
||||||
|
use PhpParser\NodeVisitorAbstract;
|
||||||
|
|
||||||
|
final class ParentConnectorNodeVisitor extends NodeVisitorAbstract
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Node[]
|
||||||
|
*/
|
||||||
|
private $stack = [];
|
||||||
|
|
||||||
|
public function beforeTraverse(array $nodes): void
|
||||||
|
{
|
||||||
|
$this->stack = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function enterNode(Node $node): void
|
||||||
|
{
|
||||||
|
if (! empty($this->stack)) {
|
||||||
|
$node->setAttribute('parent', $this->stack[count($this->stack)-1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->stack[] = $node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function leaveNode(Node $node): void
|
||||||
|
{
|
||||||
|
array_pop($this->stack);
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,9 +15,7 @@ final class LexerFactory
|
||||||
{
|
{
|
||||||
return new Emulative([
|
return new Emulative([
|
||||||
'usedAttributes' => [
|
'usedAttributes' => [
|
||||||
'comments',
|
'comments', 'startLine', 'endLine', 'startTokenPos', 'endTokenPos',
|
||||||
'startLine', 'endLine',
|
|
||||||
'startTokenPos', 'endTokenPos',
|
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,14 +13,24 @@ final class ParserFactory
|
||||||
*/
|
*/
|
||||||
private $lexer;
|
private $lexer;
|
||||||
|
|
||||||
public function __construct(Lexer $lexer)
|
/**
|
||||||
|
* @var NikicParserFactory
|
||||||
|
*/
|
||||||
|
private $nikicParserFactory;
|
||||||
|
|
||||||
|
public function __construct(Lexer $lexer, NikicParserFactory $nikicParserFactory)
|
||||||
{
|
{
|
||||||
$this->lexer = $lexer;
|
$this->lexer = $lexer;
|
||||||
|
$this->nikicParserFactory = $nikicParserFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create(): Parser
|
public function create(): Parser
|
||||||
{
|
{
|
||||||
$nikicParserFactory = new NikicParserFactory;
|
return $this->nikicParserFactory->create(NikicParserFactory::PREFER_PHP7, $this->lexer, [
|
||||||
return $nikicParserFactory->create(NikicParserFactory::PREFER_PHP7, $this->lexer);
|
'useIdentifierNodes' => true,
|
||||||
|
'useConsistentVariableNodes' => true,
|
||||||
|
'useExpressionStatements' => true,
|
||||||
|
'useNopStatements' => false,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ namespace Rector\Printer;
|
||||||
use PhpParser\PrettyPrinter\Standard;
|
use PhpParser\PrettyPrinter\Standard;
|
||||||
use SplFileInfo;
|
use SplFileInfo;
|
||||||
|
|
||||||
final class CodeStyledPrinter
|
final class FormatPerservingPrinter
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var Standard
|
* @var Standard
|
28
src/Rector/AbstractRector.php
Normal file
28
src/Rector/AbstractRector.php
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\Rector;
|
||||||
|
|
||||||
|
use PhpParser\Node;
|
||||||
|
use PhpParser\NodeTraverser;
|
||||||
|
use PhpParser\NodeVisitorAbstract;
|
||||||
|
use Rector\Contract\Deprecation\DeprecationInterface;
|
||||||
|
use Rector\Contract\Rector\RectorInterface;
|
||||||
|
|
||||||
|
abstract class AbstractRector extends NodeVisitorAbstract implements DeprecationInterface, RectorInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return null|int|Node
|
||||||
|
*/
|
||||||
|
public function enterNode(Node $node)
|
||||||
|
{
|
||||||
|
if ($this->isCandidate($node)) {
|
||||||
|
if ($newNode = $this->refactor($node)) {
|
||||||
|
return $newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NodeTraverser::DONT_TRAVERSE_CHILDREN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
88
src/Rector/Contrib/Nette/FormCallbackRector.php
Normal file
88
src/Rector/Contrib/Nette/FormCallbackRector.php
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\Rector\Contrib\Nette;
|
||||||
|
|
||||||
|
use PhpParser\Node;
|
||||||
|
use PhpParser\Node\Expr\Array_;
|
||||||
|
use PhpParser\Node\Expr\ArrayItem;
|
||||||
|
use PhpParser\Node\Expr\PropertyFetch;
|
||||||
|
use PhpParser\Node\Scalar\String_;
|
||||||
|
use PhpParser\NodeTraverser;
|
||||||
|
use PhpParser\NodeVisitorAbstract;
|
||||||
|
use Rector\Contract\Deprecation\DeprecationInterface;
|
||||||
|
use Rector\Deprecation\SetNames;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Covers https://doc.nette.org/en/2.4/migration-2-4#toc-nette-smartobject
|
||||||
|
*/
|
||||||
|
final class FormCallbackRector extends NodeVisitorAbstract implements DeprecationInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Node
|
||||||
|
*/
|
||||||
|
private $previousNode;
|
||||||
|
|
||||||
|
public function getSetName(): string
|
||||||
|
{
|
||||||
|
return SetNames::NETTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sinceVersion(): float
|
||||||
|
{
|
||||||
|
return 2.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return null|int|Node
|
||||||
|
*/
|
||||||
|
public function enterNode(Node $node)
|
||||||
|
{
|
||||||
|
if ($this->previousNode && $this->isFormEventAssign($this->previousNode)) {
|
||||||
|
if (! $node instanceof PropertyFetch) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->createShortArray($node);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->previousNode = $node;
|
||||||
|
if ($this->isFormEventAssign($node)) {
|
||||||
|
// do not check children, just go to next token
|
||||||
|
return NodeTraverser::DONT_TRAVERSE_CHILDREN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function isFormEventAssign(Node $node): bool
|
||||||
|
{
|
||||||
|
if (! $node instanceof PropertyFetch) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($node->var->name !== 'form') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$propertyName = (string) $node->name;
|
||||||
|
if (! in_array($propertyName, ['onSuccess', 'onSubmit'], true)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createShortArray(Node $node): Array_
|
||||||
|
{
|
||||||
|
return new Array_([
|
||||||
|
new ArrayItem($node->var),
|
||||||
|
new ArrayItem(
|
||||||
|
new String_(
|
||||||
|
(string) $node->name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
], [
|
||||||
|
'kind' => Array_::KIND_SHORT
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
84
src/Rector/Contrib/Nette/NetteObjectToSmartTraitRector.php
Normal file
84
src/Rector/Contrib/Nette/NetteObjectToSmartTraitRector.php
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\Rector\Contrib\Nette;
|
||||||
|
|
||||||
|
use PhpParser\Node;
|
||||||
|
use PhpParser\Node\Name\FullyQualified;
|
||||||
|
use PhpParser\Node\Stmt\Class_;
|
||||||
|
use PhpParser\Node\Stmt\TraitUse;
|
||||||
|
use Rector\Builder\StatementGlue;
|
||||||
|
use Rector\Deprecation\SetNames;
|
||||||
|
use Rector\NodeTraverser\TokenSwitcher;
|
||||||
|
use Rector\Rector\AbstractRector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Covers https://doc.nette.org/en/2.4/migration-2-4#toc-nette-smartobject
|
||||||
|
*/
|
||||||
|
final class NetteObjectToSmartTraitRector extends AbstractRector
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var StatementGlue
|
||||||
|
*/
|
||||||
|
private $statementGlue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var TokenSwitcher
|
||||||
|
*/
|
||||||
|
private $tokenSwitcher;
|
||||||
|
|
||||||
|
public function __construct(StatementGlue $statementGlue, TokenSwitcher $tokenSwitcher)
|
||||||
|
{
|
||||||
|
$this->statementGlue = $statementGlue;
|
||||||
|
$this->tokenSwitcher = $tokenSwitcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSetName(): string
|
||||||
|
{
|
||||||
|
return SetNames::NETTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sinceVersion(): float
|
||||||
|
{
|
||||||
|
return 2.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isCandidate(Node $node): bool
|
||||||
|
{
|
||||||
|
if ($node instanceof Class_) {
|
||||||
|
if (! $node->extends) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$parentClassName = (string) $node->extends;
|
||||||
|
if ($parentClassName !== 'Nette\Object') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->tokenSwitcher->enable();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Class_ $classNode
|
||||||
|
*/
|
||||||
|
public function refactor($classNode): ?Node
|
||||||
|
{
|
||||||
|
$traitUseNode = $this->createTraitUse('Nette\SmartObject');
|
||||||
|
$this->statementGlue->addAsFirstTrait($classNode, $traitUseNode);
|
||||||
|
|
||||||
|
// remove parent class
|
||||||
|
$classNode->extends = null;
|
||||||
|
|
||||||
|
return $classNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createTraitUse(string $traitName): TraitUse
|
||||||
|
{
|
||||||
|
return new TraitUse([
|
||||||
|
new FullyQualified($traitName)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\Rector\Contrib\Nette;
|
||||||
|
|
||||||
|
use PhpParser\Node;
|
||||||
|
use PhpParser\Node\Expr\ClassConstFetch;
|
||||||
|
use PhpParser\Node\Scalar\String_;
|
||||||
|
use Rector\Deprecation\SetNames;
|
||||||
|
use Rector\Rector\AbstractRector;
|
||||||
|
|
||||||
|
final class RemoveConfiguratorConstantsRector extends AbstractRector
|
||||||
|
{
|
||||||
|
public function isCandidate(Node $node): bool
|
||||||
|
{
|
||||||
|
if ($node instanceof ClassConstFetch) {
|
||||||
|
// @todo: check FQN namespace
|
||||||
|
$className = (string) $node->class;
|
||||||
|
if (! in_array($className, ['Nette\Configurator', 'Configurator'], true)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! in_array((string) $node->name, ['DEVELOPMENT', 'PRODUCTION'], true)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ClassConstFetch $classConstFetchNode
|
||||||
|
*/
|
||||||
|
public function refactor($classConstFetchNode): ?Node
|
||||||
|
{
|
||||||
|
$constantName = (string) $classConstFetchNode->name;
|
||||||
|
$string = strtolower($constantName);
|
||||||
|
|
||||||
|
return new String_($string);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSetName(): string
|
||||||
|
{
|
||||||
|
return SetNames::NETTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sinceVersion(): float
|
||||||
|
{
|
||||||
|
return 2.3;
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,8 +5,8 @@ namespace Rector\Testing\Application;
|
||||||
use PhpParser\Lexer;
|
use PhpParser\Lexer;
|
||||||
use PhpParser\NodeTraverser;
|
use PhpParser\NodeTraverser;
|
||||||
use PhpParser\Parser;
|
use PhpParser\Parser;
|
||||||
use Rector\NodeTraverser\StateHolder;
|
use Rector\NodeTraverser\TokenSwitcher;
|
||||||
use Rector\Printer\CodeStyledPrinter;
|
use Rector\Printer\FormatPerservingPrinter;
|
||||||
use SplFileInfo;
|
use SplFileInfo;
|
||||||
|
|
||||||
final class FileReconstructor
|
final class FileReconstructor
|
||||||
|
@ -17,7 +17,7 @@ final class FileReconstructor
|
||||||
private $parser;
|
private $parser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var CodeStyledPrinter
|
* @var FormatPerservingPrinter
|
||||||
*/
|
*/
|
||||||
private $codeStyledPrinter;
|
private $codeStyledPrinter;
|
||||||
|
|
||||||
|
@ -32,22 +32,22 @@ final class FileReconstructor
|
||||||
private $nodeTraverser;
|
private $nodeTraverser;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var StateHolder
|
* @var TokenSwitcher
|
||||||
*/
|
*/
|
||||||
private $stateHolder;
|
private $tokenSwitcher;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
Parser $parser,
|
Parser $parser,
|
||||||
CodeStyledPrinter $codeStyledPrinter,
|
FormatPerservingPrinter $codeStyledPrinter,
|
||||||
Lexer $lexer,
|
Lexer $lexer,
|
||||||
NodeTraverser $nodeTraverser,
|
NodeTraverser $nodeTraverser,
|
||||||
StateHolder $stateHolder
|
TokenSwitcher $tokenSwitcher
|
||||||
) {
|
) {
|
||||||
$this->parser = $parser;
|
$this->parser = $parser;
|
||||||
$this->codeStyledPrinter = $codeStyledPrinter;
|
$this->codeStyledPrinter = $codeStyledPrinter;
|
||||||
$this->lexer = $lexer;
|
$this->lexer = $lexer;
|
||||||
$this->nodeTraverser = $nodeTraverser;
|
$this->nodeTraverser = $nodeTraverser;
|
||||||
$this->stateHolder = $stateHolder;
|
$this->tokenSwitcher = $tokenSwitcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ref: https://github.com/nikic/PHP-Parser/issues/344#issuecomment-298162516
|
// ref: https://github.com/nikic/PHP-Parser/issues/344#issuecomment-298162516
|
||||||
|
@ -59,8 +59,8 @@ final class FileReconstructor
|
||||||
$oldTokens = $this->lexer->getTokens();
|
$oldTokens = $this->lexer->getTokens();
|
||||||
$newStmts = $this->nodeTraverser->traverse($oldStmts);
|
$newStmts = $this->nodeTraverser->traverse($oldStmts);
|
||||||
|
|
||||||
if (! $this->stateHolder->isAfterTraverseCalled()) {
|
if ($this->tokenSwitcher->isEnabled()) {
|
||||||
[$newStmts, $oldStmts] = [$oldStmts, $newStmts];
|
[$oldStmts, $newStmts] = [$newStmts, $oldStmts];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->codeStyledPrinter->printToString($newStmts, $oldStmts, $oldTokens);
|
return $this->codeStyledPrinter->printToString($newStmts, $oldStmts, $oldTokens);
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
namespace Rector\Testing\PHPUnit;
|
namespace Rector\Testing\PHPUnit;
|
||||||
|
|
||||||
use PhpParser\NodeVisitor;
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
use Psr\Container\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
use Rector\DependencyInjection\ContainerFactory;
|
use Rector\DependencyInjection\ContainerFactory;
|
||||||
|
|
|
@ -5,7 +5,6 @@ parameters:
|
||||||
services:
|
services:
|
||||||
_defaults:
|
_defaults:
|
||||||
autowire: true
|
autowire: true
|
||||||
autoconfigure: true
|
|
||||||
|
|
||||||
# PSR-4 autodiscovery
|
# PSR-4 autodiscovery
|
||||||
Rector\:
|
Rector\:
|
||||||
|
@ -21,8 +20,10 @@ services:
|
||||||
factory: ['@Rector\Parser\LexerFactory', 'create']
|
factory: ['@Rector\Parser\LexerFactory', 'create']
|
||||||
PhpParser\BuilderFactory: ~
|
PhpParser\BuilderFactory: ~
|
||||||
|
|
||||||
|
PhpParser\NodeTraverser:
|
||||||
|
factory: ['@Rector\NodeTraverser\NodeTraverserFactory', 'create']
|
||||||
|
|
||||||
# Traverser
|
# Traverser
|
||||||
PhpParser\NodeTraverser: ~
|
PhpParser\ParserFactory: ~
|
||||||
# Printer
|
# Printer
|
||||||
PhpParser\NodeVisitor\CloningVisitor: ~
|
|
||||||
PhpParser\PrettyPrinter\Standard: ~
|
PhpParser\PrettyPrinter\Standard: ~
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
namespace Rector\Tests\NodeVisitor\DependencyInjection\InjectAnnotationToConstructorReconstructor;
|
namespace Rector\Tests\NodeVisitor\DependencyInjection\InjectAnnotationToConstructorRector;
|
||||||
|
|
||||||
use Rector\Testing\PHPUnit\AbstractReconstructorTestCase;
|
use Rector\Testing\PHPUnit\AbstractReconstructorTestCase;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
namespace Rector\Tests\NodeVisitor\DependencyInjection\NamedServicesToConstructorReconstructor\Source;
|
namespace Rector\Tests\NodeVisitor\DependencyInjection\NamedServicesToConstructorRector\Source;
|
||||||
|
|
||||||
use Symfony\Component\Config\Loader\LoaderInterface;
|
use Symfony\Component\Config\Loader\LoaderInterface;
|
||||||
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
|
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
|
|
@ -1,6 +1,6 @@
|
||||||
<?php declare(strict_types=1);
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
namespace Rector\Tests\NodeVisitor\DependencyInjection\NamedServicesToConstructorReconstructor;
|
namespace Rector\Tests\NodeVisitor\DependencyInjection\NamedServicesToConstructorRector;
|
||||||
|
|
||||||
use Rector\Testing\PHPUnit\AbstractReconstructorTestCase;
|
use Rector\Testing\PHPUnit\AbstractReconstructorTestCase;
|
||||||
|
|
16
tests/Rector/Contrib/Nette/FormCallbackRector/Test.php
Normal file
16
tests/Rector/Contrib/Nette/FormCallbackRector/Test.php
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\Tests\Rector\Contrib\Nette\FormCallbackRector;
|
||||||
|
|
||||||
|
use Rector\Testing\PHPUnit\AbstractReconstructorTestCase;
|
||||||
|
|
||||||
|
final class Test extends AbstractReconstructorTestCase
|
||||||
|
{
|
||||||
|
public function test(): void
|
||||||
|
{
|
||||||
|
$this->doTestFileMatchesExpectedContent(
|
||||||
|
__DIR__ . '/wrong/wrong.php.inc',
|
||||||
|
__DIR__ . '/correct/correct.php.inc'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
<?php declare (strict_types=1);
|
||||||
|
|
||||||
|
class SomePresenter
|
||||||
|
{
|
||||||
|
public function createForm()
|
||||||
|
{
|
||||||
|
$form = new Form;
|
||||||
|
|
||||||
|
$form->onSuccess[] = function (Form $form) {
|
||||||
|
$this->someMethod($form);
|
||||||
|
};
|
||||||
|
|
||||||
|
return $form;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?php declare (strict_types=1);
|
||||||
|
|
||||||
|
class SomePresenter
|
||||||
|
{
|
||||||
|
public function createForm()
|
||||||
|
{
|
||||||
|
$form = new Form;
|
||||||
|
|
||||||
|
$form->onSuccess[] = [$this, 'someMethod'];
|
||||||
|
|
||||||
|
return $form;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?php declare (strict_types=1);
|
||||||
|
|
||||||
|
class SomePresenter
|
||||||
|
{
|
||||||
|
public function createForm()
|
||||||
|
{
|
||||||
|
$form = new Form;
|
||||||
|
|
||||||
|
$form->onSuccess[] = $this->someMethod;
|
||||||
|
|
||||||
|
return $form;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\Tests\Rector\Contrib\NetteObjectToSmartTraitRector;
|
||||||
|
|
||||||
|
use Rector\Testing\PHPUnit\AbstractReconstructorTestCase;
|
||||||
|
|
||||||
|
final class Test extends AbstractReconstructorTestCase
|
||||||
|
{
|
||||||
|
public function test(): void
|
||||||
|
{
|
||||||
|
$this->doTestFileMatchesExpectedContent(
|
||||||
|
__DIR__ . '/wrong/wrong.php.inc',
|
||||||
|
__DIR__ . '/correct/correct.php.inc'
|
||||||
|
);
|
||||||
|
$this->doTestFileMatchesExpectedContent(
|
||||||
|
__DIR__ . '/wrong/wrong2.php.inc',
|
||||||
|
__DIR__ . '/correct/correct2.php.inc'
|
||||||
|
);
|
||||||
|
$this->doTestFileMatchesExpectedContent(
|
||||||
|
__DIR__ . '/wrong/wrong3.php.inc',
|
||||||
|
__DIR__ . '/correct/correct3.php.inc'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?php declare (strict_types=1);
|
||||||
|
|
||||||
|
class ClassWithExternalConstant
|
||||||
|
{
|
||||||
|
use \Nette\SmartObject;
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?php declare (strict_types=1);
|
||||||
|
|
||||||
|
class ClassWithExternalConstant
|
||||||
|
{
|
||||||
|
use \Nette\SmartObject;
|
||||||
|
use AnotherTrait;
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?php declare (strict_types=1);
|
||||||
|
|
||||||
|
class ClassWithExternalConstant
|
||||||
|
{
|
||||||
|
use \Nette\SmartObject;
|
||||||
|
public $property;
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?php declare (strict_types=1);
|
||||||
|
|
||||||
|
class ClassWithExternalConstant extends Nette\Object
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?php declare (strict_types=1);
|
||||||
|
|
||||||
|
class ClassWithExternalConstant extends Nette\Object
|
||||||
|
{
|
||||||
|
use AnotherTrait;
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?php declare (strict_types=1);
|
||||||
|
|
||||||
|
class ClassWithExternalConstant extends Nette\Object
|
||||||
|
{
|
||||||
|
public $property;
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Rector\Tests\Rector\Contrib\Nette\RemoveConfiguratorConstantsRector;
|
||||||
|
|
||||||
|
use Rector\Testing\PHPUnit\AbstractReconstructorTestCase;
|
||||||
|
|
||||||
|
final class Test extends AbstractReconstructorTestCase
|
||||||
|
{
|
||||||
|
public function test(): void
|
||||||
|
{
|
||||||
|
$this->doTestFileMatchesExpectedContent(
|
||||||
|
__DIR__ . '/wrong/wrong.php.inc',
|
||||||
|
__DIR__ . '/correct/correct.php.inc'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?php declare (strict_types=1);
|
||||||
|
|
||||||
|
use Nette\Configurator;
|
||||||
|
|
||||||
|
class ClassWithExternalConstant
|
||||||
|
{
|
||||||
|
public function getValue()
|
||||||
|
{
|
||||||
|
return 'development';
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?php declare (strict_types=1);
|
||||||
|
|
||||||
|
use Nette\Configurator;
|
||||||
|
|
||||||
|
class ClassWithExternalConstant
|
||||||
|
{
|
||||||
|
public function getValue()
|
||||||
|
{
|
||||||
|
return Configurator::DEVELOPMENT;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user