Merge pull request #94 from RectorPHP/adder-tuning

Adder tuning
This commit is contained in:
Tomáš Votruba 2017-10-18 16:11:05 +02:00 committed by GitHub
commit dde6ef8108
18 changed files with 109 additions and 120 deletions

View File

@ -11,7 +11,7 @@
"beberlei/assert": "^2.7",
"doctrine/annotations": "^1.5",
"nette/utils": "^2.4",
"nikic/php-parser": "4.0.x-dev#3193f7a as 3.1.1",
"nikic/php-parser": "4.0.x-dev#f5de7f9 as 3.1.1",
"rector/better-reflection": "^3.0",
"symfony/console": "^3.3",
"symfony/dependency-injection": "^3.3",
@ -23,7 +23,7 @@
"symfony/expression-language": "^3.3",
"symfony/dependency-injection": "^3.3",
"symfony/form": "^3.3",
"symplify/easy-coding-standard": "^2.5",
"symplify/easy-coding-standard": "^2.5.4",
"tracy/tracy": "^2.4"
},
"autoload": {

View File

@ -13,8 +13,6 @@ checkers:
allowPartialUses: false
SlevomatCodingStandard\Sniffs\TypeHints\TypeHintDeclarationSniff:
enableEachParameterAndReturnInspection: true
usefulAnnotations:
- "@see"
# Metrics
PHP_CodeSniffer\Standards\Generic\Sniffs\Files\LineLengthSniff:
@ -32,16 +30,17 @@ checkers:
- 'PhpParser\Node\*'
- 'PhpParser\Comment\Doc'
- 'Rector\DeprecationExtractor\Deprecation\*'
# bugged: https://github.com/Symplify/Symplify/issues/372
- 'PhpParser\NodeTraverser'
Symplify\CodingStandard\Fixer\Naming\PropertyNameMatchingTypeFixer:
extra_skipped_classes:
- 'PhpParser\PrettyPrinter\Standard'
- 'PhpParser\Node'
parameters:
exclude_checkers:
# node style... add options to exclude naming, allow fnmatch as for New...Fixer
- Symplify\CodingStandard\Fixer\Naming\PropertyNameMatchingTypeFixer
# conflicting checkers
- PhpCsFixer\Fixer\ControlStructure\YodaStyleFixer
# Excluded from symfony-checkers.neon
# excluded from symfony-checkers.neon
- PhpCsFixer\Fixer\PhpTag\BlankLineAfterOpeningTagFixer
- PhpCsFixer\Fixer\Operator\NewWithBracesFixer
- PhpCsFixer\Fixer\Operator\UnaryOperatorSpacesFixer

View File

@ -10,17 +10,17 @@ final class MethodReflector
/**
* @var SmartClassReflector
*/
private $classReflector;
private $smartClassReflector;
public function __construct(SmartClassReflector $classReflector)
public function __construct(SmartClassReflector $smartClassReflector)
{
$this->classReflector = $classReflector;
$this->smartClassReflector = $smartClassReflector;
}
public function reflectClassMethod(string $class, string $method): ?ReflectionMethod
{
try {
$classReflection = $this->classReflector->reflect($class);
$classReflection = $this->smartClassReflector->reflect($class);
} catch (IdentifierNotFound $identifierNotFoundException) {
// class doesn't exist
return null;

View File

@ -22,7 +22,7 @@ final class SmartClassReflector
/**
* @var SmartClassReflector
*/
private $classReflector;
private $smartClassReflector;
/**
* @var SplFileInfo
@ -44,7 +44,7 @@ final class SmartClassReflector
$this->createNewClassReflector();
}
return $this->classReflector->reflect($className);
return $this->smartClassReflector->reflect($className);
} catch (TypeError $typeError) {
return null;
}
@ -55,16 +55,16 @@ final class SmartClassReflector
$currentFile = $this->currentFileProvider->getCurrentFile();
if ($currentFile === null) {
$this->classReflector = $this->classReflectorFactory->create();
$this->smartClassReflector = $this->classReflectorFactory->create();
} else {
$this->classReflector = $this->classReflectorFactory->createWithFile($currentFile);
$this->smartClassReflector = $this->classReflectorFactory->createWithFile($currentFile);
$this->classReflectorActiveFile = $currentFile;
}
}
private function shouldCreateNewClassReflector(): bool
{
if ($this->classReflector === null) {
if ($this->smartClassReflector === null) {
return true;
}

View File

@ -19,7 +19,7 @@ final class ClassReflectorOnSourceTest extends AbstractContainerAwareTestCase
/**
* @var SmartClassReflector
*/
private $currentFileAwareClassReflector;
private $smartClassReflector;
protected function setUp(): void
{
@ -27,19 +27,19 @@ final class ClassReflectorOnSourceTest extends AbstractContainerAwareTestCase
$classReflectorFactory = $this->container->get(ClassReflectorFactory::class);
$this->currentProcessedFileInfo = new SplFileInfo(__DIR__ . '/NotLoadedSource/SomeClass.php');
$this->currentFileAwareClassReflector = $classReflectorFactory->createWithFile($this->currentProcessedFileInfo);
$this->smartClassReflector = $classReflectorFactory->createWithFile($this->currentProcessedFileInfo);
}
public function test(): void
{
$this->assertInstanceOf(ClassReflector::class, $this->currentFileAwareClassReflector);
$this->assertInstanceOf(ClassReflector::class, $this->smartClassReflector);
}
public function testReflectClassThatIsNotLoaded(): void
{
$className = 'NotLoadedSource\SomeClass';
$classReflection = $this->currentFileAwareClassReflector->reflect($className);
$classReflection = $this->smartClassReflector->reflect($className);
$this->assertInstanceOf(ReflectionClass::class, $classReflection);
}

View File

@ -85,30 +85,30 @@ final class ExtractDeprecationsCommand extends Command
$input->getArgument(self::ARGUMENT_SOURCE_NAME)
);
$guessedRectors = $this->rectorGuesser->guessForDeprecations($this->deprecationCollector->getDeprecations());
$guessedRectors = $this->rectorGuessFilter->filterRectorGuessesToShow($guessedRectors);
$rectorGuesses = $this->rectorGuesser->guessForDeprecations($this->deprecationCollector->getDeprecations());
$rectorGuesses = $this->rectorGuessFilter->filterRectorGuessesToShow($rectorGuesses);
foreach ($guessedRectors as $guessedRector) {
foreach ($rectorGuesses as $guessedRector) {
$this->renderGuessedRector($guessedRector);
}
$this->symfonyStyle->success(sprintf(
'Found %d useful deprecations',
count($guessedRectors)
count($rectorGuesses)
));
return 0;
}
private function renderGuessedRector(RectorGuess $guessedRector): void
private function renderGuessedRector(RectorGuess $rectorGuess): void
{
$this->symfonyStyle->success($guessedRector->getGuessedRectorClass());
$this->symfonyStyle->success($rectorGuess->getGuessedRectorClass());
$this->symfonyStyle->writeln('<fg=yellow> ' . $guessedRector->getMessage() . '</>');
$this->symfonyStyle->writeln('<fg=yellow> ' . $rectorGuess->getMessage() . '</>');
$this->symfonyStyle->newLine();
$node = $guessedRector->getNode();
$node = $rectorGuess->getNode();
$this->symfonyStyle->writeln(' Namespace: ' . $node->getAttribute(Attribute::NAMESPACE));
$this->symfonyStyle->writeln(' Class: ' . $node->getAttribute(Attribute::CLASS_NAME));

View File

@ -37,13 +37,13 @@ final class RectorGuesser
*/
public function guessForDeprecations(array $deprecations): array
{
$guessedRectors = [];
$rectorGuesses = [];
foreach ($deprecations as $deprecation) {
$guessedRectors[] = $this->guessForDeprecation($deprecation);
$rectorGuesses[] = $this->guessForDeprecation($deprecation);
}
return $guessedRectors;
return $rectorGuesses;
}
private function guessForDeprecation(Deprecation $deprecation): ?RectorGuess

View File

@ -10,14 +10,14 @@ final class RectorGuessFilter
*/
public function filterRectorGuessesToShow(array $rectorGuesses): array
{
return $this->filterOutUsefulGuessedRectors($rectorGuesses);
return $this->filterOutUsefulRectorGuesses($rectorGuesses);
}
/**
* @param RectorGuess[] $rectorGuesses
* @return RectorGuess[]
*/
private function filterOutUsefulGuessedRectors(array $rectorGuesses): array
private function filterOutUsefulRectorGuesses(array $rectorGuesses): array
{
return array_filter($rectorGuesses, function (RectorGuess $rectorGuess) {
return $rectorGuess->isUseful();

View File

@ -25,11 +25,11 @@ final class FileProcessor
private $rectorNodeTraverser;
public function __construct(
FormatPerservingPrinter $codeStyledPrinter,
FormatPerservingPrinter $formatPerservingPrinter,
NodeTraverserQueue $nodeTraverserQueue,
RectorNodeTraverser $rectorNodeTraverser
) {
$this->formatPerservingPrinter = $codeStyledPrinter;
$this->formatPerservingPrinter = $formatPerservingPrinter;
$this->nodeTraverserQueue = $nodeTraverserQueue;
$this->rectorNodeTraverser = $rectorNodeTraverser;
}

View File

@ -2,10 +2,10 @@
namespace Rector\Builder;
use Nette\Utils\Arrays;
use PhpParser\Node;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Nop;
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\TraitUse;
@ -18,7 +18,7 @@ final class StatementGlue
{
foreach ($classNode->stmts as $key => $classElementNode) {
if ($classElementNode instanceof ClassMethod) {
$this->insertBefore($classNode, $node, $key);
$classNode->stmts = $this->insertBefore($classNode->stmts, $node, $key);
return;
}
@ -27,7 +27,7 @@ final class StatementGlue
$previousElement = null;
foreach ($classNode->stmts as $key => $classElementNode) {
if ($previousElement instanceof Property && ! $classElementNode instanceof Property) {
$this->insertBefore($classNode, $node, $key);
$classNode->stmts = $this->insertBefore($classNode->stmts, $node, $key);
return;
}
@ -43,12 +43,35 @@ final class StatementGlue
$this->addStatementToClassBeforeTypes($classNode, $node, TraitUse::class, Property::class);
}
/**
* @param Node[] $nodes
* @return Node[] $nodes
*/
public function insertBeforeAndFollowWithNewline(array $nodes, Node $node, int $key): array
{
$nodes = $this->insertBefore($nodes, $node, $key);
$nodes = $this->insertBefore($nodes, new Nop, $key);
return $nodes;
}
/**
* @param Node[] $nodes
* @return Node[] $nodes
*/
public function insertBefore(array $nodes, Node $node, int $key): array
{
array_splice($nodes, $key, 0, [$node]);
return $nodes;
}
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);
$classNode->stmts = $this->insertBefore($classNode->stmts, $node, $key);
return;
}
@ -57,16 +80,4 @@ final class StatementGlue
$classNode->stmts[] = $node;
}
/**
* @todo decouple to statements added
*
* @param int|string $key
*/
private function insertBefore(Class_ $classNode, Node $node, $key): void
{
Arrays::insertBefore($classNode->stmts, $key, [
'before_' . $key => $node,
]);
}
}

View File

@ -8,7 +8,6 @@ use PhpParser\NodeVisitorAbstract;
use Rector\Builder\Class_\ClassPropertyCollector;
use Rector\Builder\ConstructorMethodBuilder;
use Rector\Builder\PropertyBuilder;
use Rector\Node\Attribute;
/**
* Adds new properties to class and to contructor.
@ -65,9 +64,6 @@ final class PropertyToClassAdder extends NodeVisitorAbstract
return $classNode;
}
// prevents offset errors
$classNode->setAttribute(Attribute::ORIGINAL_NODE, null);
foreach ($propertiesForClass as $propertyType => $propertyName) {
$this->constructorMethodBuilder->addPropertyAssignToClass($classNode, $propertyType, $propertyName);
$this->propertyBuilder->addPropertyToClass($classNode, $propertyType, $propertyName);

View File

@ -41,7 +41,7 @@ final class MagicMethodRector extends AbstractRector
/**
* @var SmartClassReflector
*/
private $classReflector;
private $smartClassReflector;
/**
* @var MagicMethodMatcher
@ -51,12 +51,12 @@ final class MagicMethodRector extends AbstractRector
public function __construct(
MethodBuilder $methodBuilder,
DocBlockAnalyzer $docBlockAnalyzer,
SmartClassReflector $classReflector,
SmartClassReflector $smartClassReflector,
MagicMethodMatcher $magicMethodMatcher
) {
$this->methodBuilder = $methodBuilder;
$this->docBlockAnalyzer = $docBlockAnalyzer;
$this->classReflector = $classReflector;
$this->smartClassReflector = $smartClassReflector;
$this->magicMethodMatcher = $magicMethodMatcher;
}
@ -82,7 +82,7 @@ final class MagicMethodRector extends AbstractRector
$className = $node->getAttribute(Attribute::CLASS_NAME);
$this->magicMethods = $this->magicMethodMatcher->matchInContent(
$this->classReflector->reflect($className),
$this->smartClassReflector->reflect($className),
$docComments[0]->getText()
);
@ -110,8 +110,6 @@ final class MagicMethodRector extends AbstractRector
$this->docBlockAnalyzer->removeAnnotationFromNode($classNode, 'method', $methodName);
}
$classNode->setAttribute(Attribute::ORIGINAL_NODE, null);
return $classNode;
}

View File

@ -63,8 +63,6 @@ final class NetteObjectToSmartTraitRector extends AbstractRector
$this->removeParentClass($classNode);
$classNode->setAttribute(Attribute::ORIGINAL_NODE, null);
return $classNode;
}

View File

@ -69,7 +69,6 @@ final class NamespaceReplacerRector extends AbstractRector
}
$node->parts = explode('\\', $newName);
$node->setAttribute(Attribute::ORIGINAL_NODE, null);
return $node;
}

View File

@ -2,14 +2,13 @@
namespace Rector\Rector\Dynamic;
use Nette\Utils\Arrays;
use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Nop;
use PhpParser\Node\Stmt\UseUse;
use Rector\Builder\StatementGlue;
use Rector\Node\Attribute;
use Rector\Node\NodeFactory;
use Rector\Rector\AbstractRector;
@ -41,13 +40,19 @@ final class PseudoNamespaceToNamespaceRector extends AbstractRector
*/
private $nodeFactory;
/**
* @var StatementGlue
*/
private $statementGlue;
/**
* @param string[] $pseudoNamespacePrefixes
*/
public function __construct(array $pseudoNamespacePrefixes, NodeFactory $nodeFactory)
public function __construct(array $pseudoNamespacePrefixes, NodeFactory $nodeFactory, StatementGlue $statementGlue)
{
$this->pseudoNamespacePrefixes = $pseudoNamespacePrefixes;
$this->nodeFactory = $nodeFactory;
$this->statementGlue = $statementGlue;
}
/**
@ -89,8 +94,6 @@ final class PseudoNamespaceToNamespaceRector extends AbstractRector
if ($parentNode instanceof UseUse) {
$this->oldToNewUseStatements[$oldName] = $lastNewNamePart;
} elseif (isset($this->oldToNewUseStatements[$oldName])) {
// to prevent "getComments() on string" error
$nameOrIdentifierNode->setAttribute(Attribute::ORIGINAL_NODE, null);
$newNameParts = [$this->oldToNewUseStatements[$oldName]];
}
@ -124,8 +127,7 @@ final class PseudoNamespaceToNamespaceRector extends AbstractRector
foreach ($nodes as $key => $node) {
if ($node instanceof Class_) {
$nodes = $this->insertBefore($nodes, $namespaceNode, $key);
$nodes = $this->insertBefore($nodes, new Nop, $key);
$nodes = $this->statementGlue->insertBeforeAndFollowWithNewline($nodes, $namespaceNode, $key);
break;
}
@ -147,27 +149,4 @@ final class PseudoNamespaceToNamespaceRector extends AbstractRector
return null;
}
/**
* @param Node[] $nodes
* @param int|string $key
* @return Node[]
*/
private function insertBefore(array $nodes, Node $addedNode, $key): array
{
Arrays::insertBefore($nodes, $key, [
'before_' . $key => $addedNode,
]);
// recound ids
$recountedNodes = [];
$i = 0;
foreach ($nodes as $node) {
$recountedNodes[$i] = $node;
++$i;
}
return $recountedNodes;
}
}

View File

@ -33,7 +33,7 @@ final class GetAndSetToMethodCallRector extends AbstractRector
/**
* @var PropertyFetchAnalyzer
*/
private $propertyAccessAnalyzer;
private $propertyFetchAnalyzer;
/**
* @var NodeFactory
@ -57,12 +57,12 @@ final class GetAndSetToMethodCallRector extends AbstractRector
*/
public function __construct(
array $typeToMethodCalls,
PropertyFetchAnalyzer $propertyAccessAnalyzer,
PropertyFetchAnalyzer $propertyFetchAnalyzer,
NodeFactory $nodeFactory,
ExpressionAnalyzer $expressionAnalyzer
) {
$this->typeToMethodCalls = $typeToMethodCalls;
$this->propertyAccessAnalyzer = $propertyAccessAnalyzer;
$this->propertyFetchAnalyzer = $propertyFetchAnalyzer;
$this->nodeFactory = $nodeFactory;
$this->expressionAnalyzer = $expressionAnalyzer;
}
@ -77,7 +77,7 @@ final class GetAndSetToMethodCallRector extends AbstractRector
}
foreach ($this->typeToMethodCalls as $type => $transformation) {
if ($this->propertyAccessAnalyzer->isMagicPropertyFetchOnType($propertyFetchNode, $type)) {
if ($this->propertyFetchAnalyzer->isMagicPropertyFetchOnType($propertyFetchNode, $type)) {
$this->activeTransformation = $transformation;
return true;

View File

@ -35,19 +35,17 @@ final class UnsetAndIssetToMethodCallRector extends AbstractRector
private $nodeFactory;
/**
* @var mixed
* @var mixed[]
*/
private $activeTransformation;
private $activeTransformation = [];
/**
* Type to method call()
*
* @param string[] $typeToMethodCalls
*/
public function __construct(
array $typeToMethodCalls,
NodeFactory $nodeFactory
) {
public function __construct(array $typeToMethodCalls, NodeFactory $nodeFactory)
{
$this->typeToMethodCalls = $typeToMethodCalls;
$this->nodeFactory = $nodeFactory;
}
@ -64,17 +62,13 @@ final class UnsetAndIssetToMethodCallRector extends AbstractRector
return false;
}
/** @var ArrayDimFetch $var */
foreach ($node->vars as $var) {
$variableNode = $var->var;
$variableNodeType = $variableNode->getAttribute(Attribute::TYPE);
if (! $var instanceof ArrayDimFetch) {
continue;
}
foreach ($this->typeToMethodCalls as $type => $transformation) {
if ($variableNodeType === $type) {
$this->activeTransformation = $transformation;
return true;
}
if ($this->matchArrayDimFetch($var)) {
return true;
}
}
@ -123,4 +117,19 @@ final class UnsetAndIssetToMethodCallRector extends AbstractRector
return null;
}
private function matchArrayDimFetch(ArrayDimFetch $arrayDimFetchNode): bool
{
$variableNodeType = $arrayDimFetchNode->var->getAttribute(Attribute::TYPE);
foreach ($this->typeToMethodCalls as $type => $transformation) {
if ($variableNodeType === $type) {
$this->activeTransformation = $transformation;
return true;
}
}
return false;
}
}

View File

@ -23,7 +23,7 @@ final class MagicMethodMatcher
*
* @return mixed[]
*/
public function matchInContent(ReflectionClass $classReflection, string $text): array
public function matchInContent(ReflectionClass $reflectionClass, string $text): array
{
$matches = Strings::matchAll($text, self::MAGIC_METHODS_PATTERN, PREG_SET_ORDER);
@ -37,12 +37,12 @@ final class MagicMethodMatcher
$methodName = $operation . $propertyName;
$propertyName = strtolower($propertyName[0]) . substr($propertyName, 1) . ($operation === 'add' ? 's' : '');
if (! $classReflection->hasProperty($propertyName)) {
if (! $reflectionClass->hasProperty($propertyName)) {
continue;
}
/** @var ReflectionProperty $propertyReflection */
$propertyReflection = $classReflection->getProperty($propertyName);
$propertyReflection = $reflectionClass->getProperty($propertyName);
if ($propertyReflection->isStatic()) {
continue;
}
@ -64,7 +64,7 @@ final class MagicMethodMatcher
private function resolveType(
string $op,
string $type,
ReflectionProperty $propertyReflection,
ReflectionProperty $reflectionProperty,
array $match
): ?string {
if ($op === 'get' || $op === 'is') {
@ -74,7 +74,7 @@ final class MagicMethodMatcher
if (! $type && preg_match(
'#@var[ \t]+(\S+)' . ($op === 'add' ? '\[\]#' : '#'),
$propertyReflection->getDocComment(),
$reflectionProperty->getDocComment(),
$match
)) {
$type = $match[1];