Merge pull request #1882 from rectorphp/import-same-class-fix

[CodingStyle] Import short classes as well [ref #1877]
This commit is contained in:
Tomáš Votruba 2019-08-21 19:19:05 +02:00 committed by GitHub
commit b82d6dc8af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 102 additions and 51 deletions

View File

@ -3,7 +3,12 @@
namespace Rector\CodeQuality\Rector\Catch_;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt\Catch_;
use PhpParser\Node\Stmt\Throw_;
use PhpParser\NodeTraverser;
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\CodeSample;
@ -69,15 +74,15 @@ CODE_SAMPLE
$catchedThrowableVariable = $node->var;
$this->traverseNodesWithCallable($node->stmts, function (Node $node) use ($catchedThrowableVariable): ?int {
if (! $node instanceof Node\Stmt\Throw_) {
if (! $node instanceof Throw_) {
return null;
}
if (! $node->expr instanceof Node\Expr\New_) {
if (! $node->expr instanceof New_) {
return null;
}
if (! $node->expr->class instanceof Node\Name) {
if (! $node->expr->class instanceof Name) {
return null;
}
@ -88,10 +93,10 @@ CODE_SAMPLE
if (! isset($node->expr->args[1])) {
// get previous code
$node->expr->args[1] = new Node\Arg(new Node\Expr\MethodCall($catchedThrowableVariable, 'getCode'));
$node->expr->args[1] = new Arg(new MethodCall($catchedThrowableVariable, 'getCode'));
}
$node->expr->args[2] = new Node\Arg($catchedThrowableVariable);
$node->expr->args[2] = new Arg($catchedThrowableVariable);
// nothing more to add
return NodeTraverser::STOP_TRAVERSAL;

View File

@ -8,8 +8,10 @@ use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\BinaryOp;
use PhpParser\Node\Expr\BinaryOp\BooleanAnd;
use PhpParser\Node\Expr\BinaryOp\NotIdentical;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\Property;
use PhpParser\Node\Stmt\PropertyProperty;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockManipulator;
@ -129,7 +131,7 @@ CODE_SAMPLE
return null;
}
/** @var Node\Stmt\Property $property */
/** @var Property $property */
$property = $node->getAttribute(AttributeKey::PARENT_NODE);
// we need docblock
@ -222,7 +224,7 @@ CODE_SAMPLE
$isNextNodeCountingProperty = (bool) $this->betterNodeFinder->findFirst($node->right, function (Node $node) use (
$propertyNames
): ?bool {
if (! $node instanceof Expr\FuncCall) {
if (! $node instanceof FuncCall) {
return null;
}

View File

@ -4,6 +4,7 @@ namespace Rector\CodingStyle\Rector\Namespace_;
use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Expr\ConstFetch;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt\Namespace_;
@ -150,12 +151,7 @@ CODE_SAMPLE
{
$originalName = $name->getAttribute('originalName');
if ($originalName instanceof Name) {
// already short
if (! Strings::contains($originalName->toString(), '\\')) {
return null;
}
} else {
if (! $originalName instanceof Name) {
// not sure what to do
return null;
}
@ -163,6 +159,7 @@ CODE_SAMPLE
// the short name is already used, skip it
// @todo this is duplicated check of - $this->useAddingCommander->isShortImported?
$shortName = $this->classNaming->getShortName($name->toString());
if ($this->isShortNameAlreadyUsedForDifferentFqn($name, $shortName)) {
return null;
}
@ -203,16 +200,25 @@ CODE_SAMPLE
// 1. name is fully qualified → import it
private function shouldSkipName(Name $name, string $fullyQualifiedName): bool
{
// not namespaced class
if (! Strings::contains($fullyQualifiedName, '\\')) {
$shortName = $this->classNaming->getShortName($fullyQualifiedName);
$parentNode = $name->getAttribute(AttributeKey::PARENT_NODE);
if ($parentNode instanceof ConstFetch) { // is true, false, null etc.
return true;
}
$shortName = $this->classNaming->getShortName($fullyQualifiedName);
if ($this->isNames($name, ['self', 'parent', 'static'])) {
return true;
}
// skip native function calls
if ($parentNode instanceof FuncCall && ! Strings::contains($fullyQualifiedName, '\\')) {
return true;
}
// nothing to change
if ($shortName === $fullyQualifiedName) {
return true;
return false;
}
return $this->useAddingCommander->canImportBeAdded($name, $fullyQualifiedName);

View File

@ -35,6 +35,7 @@ final class StockRepository
namespace Rector\CodingStyle\Tests\Rector\Namespace_\ImportFullyQualifiedNamesRector\Source;
use Rector\CodingStyle\Tests\Rector\Namespace_\ImportFullyQualifiedNamesRector\Source\Stock\Query;
use InvalidArgumentException;
use Doctrine\DBAL\Connection;
final class StockRepository
{
@ -44,7 +45,7 @@ final class StockRepository
$query = 5;
if (!($query instanceof Stock\Querying\Query)) {
throw new \InvalidArgumentException('Wrong query provided');
throw new InvalidArgumentException('Wrong query provided');
}
/** @var Querying\Query $query */

View File

@ -0,0 +1,20 @@
<?php
namespace Rector\CodingStyle\Tests\Rector\Namespace_\ImportFullyQualifiedNamesRector\Fixture;
class SomeException extends \Exception
{
}
?>
-----
<?php
namespace Rector\CodingStyle\Tests\Rector\Namespace_\ImportFullyQualifiedNamesRector\Fixture;
use Exception;
class SomeException extends Exception
{
}
?>

View File

@ -32,6 +32,7 @@ final class ImportFullyQualifiedNamesRectorTest extends AbstractRectorTestCase
yield [__DIR__ . '/Fixture/already_with_use.php.inc'];
yield [__DIR__ . '/Fixture/already_class_name.php.inc'];
yield [__DIR__ . '/Fixture/no_class.php.inc'];
yield [__DIR__ . '/Fixture/short.php.inc'];
// keep
yield [__DIR__ . '/Fixture/keep.php.inc'];

View File

@ -3,7 +3,9 @@
namespace Rector\DeadCode\Rector\ClassMethod;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\Return_;
@ -117,8 +119,8 @@ CODE_SAMPLE
}
/**
* @param Node\Arg[] $args
* @param Node\Param[] $params
* @param Arg[] $args
* @param Param[] $params
*/
private function areArgsAndParamsEqual(array $args, array $params): bool
{

View File

@ -3,6 +3,7 @@
namespace Rector\DeadCode\Rector\Switch_;
use PhpParser\Node;
use PhpParser\Node\Stmt\Case_;
use PhpParser\Node\Stmt\Switch_;
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\CodeSample;
@ -74,7 +75,7 @@ CODE_SAMPLE
return null;
}
/** @var Node\Stmt\Case_|null $previousCase */
/** @var Case_|null $previousCase */
$previousCase = null;
foreach ($node->cases as $case) {
if ($previousCase && $this->areNodesEqual($case->stmts, $previousCase->stmts)) {

View File

@ -3,7 +3,9 @@
namespace Rector\Nette\Rector\FuncCall;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr\FuncCall;
use PhpParser\Node\Expr\StaticCall;
use Rector\Rector\AbstractRector;
use Rector\RectorDefinition\CodeSample;
use Rector\RectorDefinition\RectorDefinition;
@ -89,7 +91,7 @@ CODE_SAMPLE
return null;
}
private function refactorJsonEncode(Node\Expr\FuncCall $funcCall): Node\Expr\StaticCall
private function refactorJsonEncode(FuncCall $funcCall): StaticCall
{
$args = $funcCall->args;
if (isset($args[1])) {
@ -97,14 +99,14 @@ CODE_SAMPLE
if ($this->isName($secondArgumentValue, 'JSON_PRETTY_PRINT')) {
$prettyClassConstant = $this->createClassConstant('Nette\Utils\Json', 'PRETTY');
$args[1] = new Node\Arg($prettyClassConstant);
$args[1] = new Arg($prettyClassConstant);
}
}
return $this->createStaticCall('Nette\Utils\Json', 'encode', $args);
}
private function refactorJsonDecode(Node\Expr\FuncCall $funcCall): Node\Expr\StaticCall
private function refactorJsonDecode(FuncCall $funcCall): StaticCall
{
$args = $funcCall->args;
@ -115,7 +117,7 @@ CODE_SAMPLE
unset($args[1]);
} elseif ($this->isTrue($secondArgumentValue)) {
$forceArrayClassConstant = $this->createClassConstant('Nette\Utils\Json', 'FORCE_ARRAY');
$args[1] = new Node\Arg($forceArrayClassConstant);
$args[1] = new Arg($forceArrayClassConstant);
}
}

View File

@ -15,6 +15,7 @@ use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Param;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\Class_;
@ -607,7 +608,7 @@ final class NodeTypeResolver
$this->callableNodeTraverser->traverseNodesWithCallable(
(array) $classMethod->stmts,
function (Node $node) use ($paramName, &$paramStaticType): ?int {
if (! $node instanceof Node\Expr\Variable) {
if (! $node instanceof Variable) {
return null;
}

View File

@ -4,11 +4,13 @@ namespace Rector\SymfonyCodeQuality\Rector\Class_;
use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\ArrayItem;
use PhpParser\Node\Expr\ClassConstFetch;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\Scalar\LNumber;
use PhpParser\Node\Scalar\String_;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
@ -306,7 +308,7 @@ CODE_SAMPLE
*/
private function createSingleMethod(
array $methodNamesWithPriorities,
Node\Expr $expr,
Expr $expr,
Array_ $eventsToMethodsArray
): void {
[$methodName, $priority] = $methodNamesWithPriorities[0];
@ -314,7 +316,7 @@ CODE_SAMPLE
if ($priority) {
$methodNameWithPriorityArray = new Array_();
$methodNameWithPriorityArray->items[] = new ArrayItem(new String_($methodName));
$methodNameWithPriorityArray->items[] = new ArrayItem(new Node\Scalar\LNumber((int) $priority));
$methodNameWithPriorityArray->items[] = new ArrayItem(new LNumber((int) $priority));
$eventsToMethodsArray->items[] = new ArrayItem($methodNameWithPriorityArray, $expr);
} else {
@ -328,7 +330,7 @@ CODE_SAMPLE
*/
private function createMultipleMethods(
array $methodNamesWithPriorities,
Node\Expr $expr,
Expr $expr,
Array_ $eventsToMethodsArray
): void {
$multipleMethodsArray = new Array_();
@ -339,7 +341,7 @@ CODE_SAMPLE
if ($priority) {
$methodNameWithPriorityArray = new Array_();
$methodNameWithPriorityArray->items[] = new ArrayItem(new String_($methodName));
$methodNameWithPriorityArray->items[] = new ArrayItem(new Node\Scalar\LNumber((int) $priority));
$methodNameWithPriorityArray->items[] = new ArrayItem(new LNumber((int) $priority));
$multipleMethodsArray->items[] = new ArrayItem($methodNameWithPriorityArray);
} else {

View File

@ -3,6 +3,7 @@
namespace Rector\TypeDeclaration\TypeInferer;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\ArrayDimFetch;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\PropertyFetch;
@ -60,7 +61,7 @@ final class AssignToPropertyTypeInferer extends AbstractTypeInferer
* - $this->propertyName = $expr;
* - $this->propertyName[] = $expr;
*/
private function matchPropertyAssignExpr(Assign $assign, string $propertyName): ?Node\Expr
private function matchPropertyAssignExpr(Assign $assign, string $propertyName): ?Expr
{
if ($assign->var instanceof PropertyFetch) {
if (! $this->nameResolver->isName($assign->var, $propertyName)) {

View File

@ -6,6 +6,7 @@ use PhpParser\Node;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Type\ArrayType;
use PHPStan\Type\Type;
use Rector\NodeTypeResolver\Node\AttributeKey;
@ -38,7 +39,7 @@ final class PropertyNodeParamTypeInferer extends AbstractTypeInferer implements
$paramName = $this->nameResolver->getName($param);
/** @var Node\Stmt\ClassMethod $classMethod */
/** @var ClassMethod $classMethod */
$classMethod = $param->getAttribute(AttributeKey::PARENT_NODE);
$propertyStaticTypes = [];

View File

@ -2,8 +2,8 @@
namespace Rector\TypeDeclaration\TypeInferer\PropertyTypeInferer;
use PhpParser\Node;
use PhpParser\Node\Stmt\ClassLike;
use PhpParser\Node\Stmt\Property;
use PHPStan\Type\IntersectionType;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\TypeDeclaration\Contract\TypeInferer\PropertyTypeInfererInterface;
@ -25,7 +25,7 @@ final class AllAssignNodePropertyTypeInferer extends AbstractTypeInferer impleme
/**
* @return string[]
*/
public function inferProperty(Node\Stmt\Property $property): array
public function inferProperty(Property $property): array
{
/** @var ClassLike $class */
$class = $property->getAttribute(AttributeKey::CLASS_NODE);

View File

@ -6,9 +6,13 @@ use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Name;
use PhpParser\Node\Name\FullyQualified;
use PhpParser\Node\NullableType;
use PhpParser\Node\Param;
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Property;
use PhpParser\NodeTraverser;
use PHPStan\Type\NullType;
use PHPStan\Type\Type;
@ -22,9 +26,9 @@ final class ConstructorPropertyTypeInferer extends AbstractTypeInferer implement
/**
* @return string[]|IdentifierValueObject[]
*/
public function inferProperty(Node\Stmt\Property $property): array
public function inferProperty(Property $property): array
{
/** @var Node\Stmt\Class_ $class */
/** @var Class_ $class */
$class = $property->getAttribute(AttributeKey::CLASS_NODE);
$classMethod = $class->getMethod('__construct');
@ -192,11 +196,11 @@ final class ConstructorPropertyTypeInferer extends AbstractTypeInferer implement
}
// special case for alias
if ($param->type instanceof Node\Name\FullyQualified) {
if ($param->type instanceof FullyQualified) {
$fullyQualifiedName = $param->type->toString();
$originalName = $param->type->getAttribute('originalName');
if ($fullyQualifiedName && $originalName instanceof Node\Name) {
if ($fullyQualifiedName && $originalName instanceof Name) {
// if the FQN has different ending than the original, it was aliased and we need to return the alias
if (! Strings::endsWith($fullyQualifiedName, '\\' . $originalName->toString())) {
return new IdentifierValueObject($originalName->toString(), true);

View File

@ -8,13 +8,9 @@ parameters:
# autoload-buggy cases
- "*.php.inc"
# string might not exist for SplitStringClassConstantToClassConstFetchRector
- "packages/Symfony/src/Rector/Console/ConsoleExceptionToErrorEventConstantRector.php"
- "tests/Rector/Argument/ArgumentRemoverRector/ArgumentRemoverRectorTest.php"
- "tests/Rector/Argument/ArgumentDefaultValueReplacerRector/ArgumentDefaultValueReplacerRectorTest.php"
# so Rector code is still PHP 7.1 compatible
php_version_features: '7.1'
services:
# Rector\TypeDeclaration\Rector\ClassMethod\AddArrayReturnDocTypeRector:
# Rector\CodingStyle\Rector\Namespace_\ImportFullyQualifiedNamesRector: ~

View File

@ -4,6 +4,7 @@ namespace Rector\PhpParser\Node\Manipulator;
use Iterator;
use PhpParser\Node;
use PhpParser\Node\Expr\ArrowFunction;
use PhpParser\Node\Expr\Closure;
use PhpParser\Node\Expr\Yield_;
use PhpParser\Node\FunctionLike;
@ -213,7 +214,7 @@ final class FunctionLikeManipulator
$this->callableNodeTraverser->traverseNodesWithCallable((array) $functionLike->stmts, function (Node $node) use (
&$localReturnNodes
): ?int {
if ($node instanceof Function_ || $node instanceof Closure || $node instanceof Node\Expr\ArrowFunction) {
if ($node instanceof Function_ || $node instanceof Closure || $node instanceof ArrowFunction) {
// skip Return_ nodes in nested functions
return NodeTraverser::DONT_TRAVERSE_CHILDREN;
}

View File

@ -4,7 +4,9 @@ namespace Rector\PhpParser\Node\Manipulator;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Stmt\Class_;
use PHPStan\Analyser\Scope;
use PHPStan\Broker\Broker;
@ -109,7 +111,7 @@ final class PropertyFetchManipulator
return null;
}
/** @var Node\Expr\Assign $node */
/** @var Assign $node */
$propertyName = $this->nameResolver->getName($node->expr);
if ($propertyName) {
$propertyNames[] = $propertyName;
@ -127,11 +129,11 @@ final class PropertyFetchManipulator
*/
public function isVariableAssignToThisPropertyFetch(Node $node, string $variableName): bool
{
if (! $node instanceof Node\Expr\Assign) {
if (! $node instanceof Assign) {
return false;
}
if (! $node->expr instanceof Node\Expr\Variable) {
if (! $node->expr instanceof Variable) {
return false;
}

View File

@ -4,7 +4,10 @@ namespace Rector\Rector\MethodBody;
use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\Variable;
use Rector\Exception\ShouldNotHappenException;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\Rector\AbstractRector;
@ -115,16 +118,16 @@ CODE_SAMPLE
/**
* @param MethodCall[] $methodCalls
* @return Node\Expr\Variable|Node\Expr\PropertyFetch
* @return Variable|PropertyFetch
*/
private function extractRootVariable(array $methodCalls): Node\Expr
private function extractRootVariable(array $methodCalls): Expr
{
foreach ($methodCalls as $methodCall) {
if ($methodCall->var instanceof Node\Expr\Variable) {
if ($methodCall->var instanceof Variable) {
return $methodCall->var;
}
if ($methodCall->var instanceof Node\Expr\PropertyFetch) {
if ($methodCall->var instanceof PropertyFetch) {
return $methodCall->var;
}
}