mirror of
https://github.com/rectorphp/rector.git
synced 2025-03-20 15:29:43 +01:00
apply new static analysis
This commit is contained in:
parent
45df82424c
commit
2c878c7541
@ -66,9 +66,13 @@ CODE_SAMPLE
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var AssignOp|Assign $previousNode */
|
||||
$previousNode = $node->getAttribute(Attribute::PREVIOUS_NODE)->expr;
|
||||
$previousNode = $node->getAttribute(Attribute::PREVIOUS_NODE);
|
||||
if (! $previousNode instanceof Expression) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var AssignOp|Assign $previousNode */
|
||||
$previousNode = $previousNode->expr;
|
||||
$previousVariableNode = $previousNode->var;
|
||||
|
||||
// has some comment
|
||||
|
@ -8,6 +8,7 @@ use PhpParser\Node\Expr\Array_;
|
||||
use PhpParser\Node\Name\FullyQualified;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockAnalyzer;
|
||||
use Rector\PhpParser\NodeTransformer;
|
||||
@ -108,17 +109,7 @@ CODE_SAMPLE
|
||||
continue;
|
||||
}
|
||||
|
||||
$yieldNodes = $this->nodeTransformer->transformArrayToYields($arrayNode);
|
||||
// remove whole return node
|
||||
$this->removeNode($arrayNode->getAttribute(Attribute::PARENT_NODE));
|
||||
|
||||
// remove doc block
|
||||
$this->docBlockAnalyzer->removeTagFromNode($node, 'return');
|
||||
|
||||
// change return typehint
|
||||
$node->returnType = new FullyQualified(Iterator::class);
|
||||
|
||||
$node->stmts = array_merge((array) $node->stmts, $yieldNodes);
|
||||
$this->transformArrayToYieldsOnMethodNode($node, $arrayNode);
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,4 +132,25 @@ CODE_SAMPLE
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function transformArrayToYieldsOnMethodNode(ClassMethod $classMethod, Array_ $arrayNode): void
|
||||
{
|
||||
$yieldNodes = $this->nodeTransformer->transformArrayToYields($arrayNode);
|
||||
|
||||
// remove whole return node
|
||||
$parentNode = $arrayNode->getAttribute(Attribute::PARENT_NODE);
|
||||
if ($parentNode === null) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$this->removeNode($parentNode);
|
||||
|
||||
// remove doc block
|
||||
$this->docBlockAnalyzer->removeTagFromNode($classMethod, 'return');
|
||||
|
||||
// change return typehint
|
||||
$classMethod->returnType = new FullyQualified(Iterator::class);
|
||||
|
||||
$classMethod->stmts = array_merge((array) $classMethod->stmts, $yieldNodes);
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ use PhpParser\Node\Param;
|
||||
use PhpParser\Node\Stmt\Namespace_;
|
||||
use PhpParser\Node\Stmt\Use_;
|
||||
use PhpParser\NodeVisitor\NameResolver;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\PhpParser\Node\BetterNodeFinder;
|
||||
use Rector\Rector\AbstractRector;
|
||||
@ -62,8 +63,7 @@ CODE_SAMPLE
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
$parentNode = $node->getAttribute(Attribute::PARENT_NODE);
|
||||
$usedNameNodes = $this->resolveUsedNameNodes($parentNode);
|
||||
$usedNameNodes = $this->resolveUsedNameNodes($node);
|
||||
if ($usedNameNodes === []) {
|
||||
return null;
|
||||
}
|
||||
@ -100,19 +100,20 @@ CODE_SAMPLE
|
||||
/**
|
||||
* @return Node[][][]
|
||||
*/
|
||||
private function resolveUsedNameNodes(Node $parentNode): array
|
||||
private function resolveUsedNameNodes(Use_ $node): array
|
||||
{
|
||||
$parentNode = $node->getAttribute(Attribute::PARENT_NODE);
|
||||
if ($parentNode === null) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$usedNameNodes = [];
|
||||
|
||||
// assumption for namespaced content
|
||||
if ($parentNode instanceof Namespace_) {
|
||||
/** @var Name[] $namedNodes */
|
||||
$namedNodes = $this->betterNodeFinder->find($parentNode, function (Node $node) {
|
||||
if ($node instanceof Name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return $node instanceof Name;
|
||||
});
|
||||
|
||||
foreach ($namedNodes as $nameNode) {
|
||||
@ -124,7 +125,6 @@ CODE_SAMPLE
|
||||
|
||||
/** @var Node $parentNode */
|
||||
$parentNode = $nameNode->getAttribute(Attribute::PARENT_NODE);
|
||||
|
||||
$usedNameNodes[$originalName->toString()][] = [$nameNode, $parentNode];
|
||||
}
|
||||
}
|
||||
|
@ -70,9 +70,12 @@ CODE_SAMPLE
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($this->classMethodMaintainer->hasParentMethodOrInterfaceMethod(
|
||||
$node->getAttribute(Attribute::METHOD_NODE)
|
||||
)) {
|
||||
$methodNode = $node->getAttribute(Attribute::METHOD_NODE);
|
||||
if ($methodNode === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($this->classMethodMaintainer->hasParentMethodOrInterfaceMethod($methodNode)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -121,6 +121,10 @@ CODE_SAMPLE
|
||||
$node = $exprNode->getAttribute(Attribute::PARENT_NODE);
|
||||
}
|
||||
|
||||
if ($node === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->docBlockAnalyzer->changeType($node, $oldType, $newType);
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ use PhpParser\Node\Stmt\Property;
|
||||
use PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
|
||||
use Rector\Application\ErrorAndDiffCollector;
|
||||
use Rector\Bridge\Contract\AnalyzedApplicationContainerInterface;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockAnalyzer;
|
||||
use Rector\Rector\AbstractRector;
|
||||
@ -127,7 +128,12 @@ CODE_SAMPLE
|
||||
// set to private
|
||||
$node->flags = Class_::MODIFIER_PRIVATE;
|
||||
|
||||
$this->addPropertyToClass($node->getAttribute(Attribute::CLASS_NODE), $type, $name);
|
||||
$classNode = $node->getAttribute(Attribute::CLASS_NODE);
|
||||
if (! $classNode instanceof Class_) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$this->addPropertyToClass($classNode, $type, $name);
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ use PhpParser\Node\Stmt\ClassLike;
|
||||
use PhpParser\Node\Stmt\Interface_;
|
||||
use PhpParser\Node\Stmt\Trait_;
|
||||
use PhpParser\Node\Stmt\TraitUse;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\PhpParser\Node\Resolver\NameResolver;
|
||||
|
||||
@ -39,7 +40,11 @@ final class ClassLikeNodeCollector
|
||||
|
||||
public function addClass(Class_ $classNode): void
|
||||
{
|
||||
$name = (string) $classNode->getAttribute(Attribute::CLASS_NAME);
|
||||
$name = $classNode->getAttribute(Attribute::CLASS_NAME);
|
||||
if ($name === null) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$this->classes[$name] = $classNode;
|
||||
}
|
||||
|
||||
@ -50,13 +55,21 @@ final class ClassLikeNodeCollector
|
||||
|
||||
public function addInterface(Interface_ $interfaceNode): void
|
||||
{
|
||||
$name = (string) $interfaceNode->getAttribute(Attribute::CLASS_NAME);
|
||||
$name = $interfaceNode->getAttribute(Attribute::CLASS_NAME);
|
||||
if ($name === null) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$this->interfaces[$name] = $interfaceNode;
|
||||
}
|
||||
|
||||
public function addTrait(Trait_ $traitNode): void
|
||||
{
|
||||
$name = (string) $traitNode->getAttribute(Attribute::CLASS_NAME);
|
||||
$name = $traitNode->getAttribute(Attribute::CLASS_NAME);
|
||||
if ($name === null) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$this->traits[$name] = $traitNode;
|
||||
}
|
||||
|
||||
@ -85,11 +98,16 @@ final class ClassLikeNodeCollector
|
||||
{
|
||||
$childrenClasses = [];
|
||||
foreach ($this->classes as $classNode) {
|
||||
if (! is_a($classNode->getAttribute(Attribute::CLASS_NAME), $class, true)) {
|
||||
$className = $classNode->getAttribute(Attribute::CLASS_NAME);
|
||||
if ($className === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (! is_a($className, $class, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($classNode->getAttribute(Attribute::CLASS_NAME) === $class) {
|
||||
if ($className === $class) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -106,11 +124,16 @@ final class ClassLikeNodeCollector
|
||||
{
|
||||
$implementerInterfaces = [];
|
||||
foreach ($this->interfaces as $interfaceNode) {
|
||||
if (! is_a($interfaceNode->getAttribute(Attribute::CLASS_NAME), $interface, true)) {
|
||||
$className = $interfaceNode->getAttribute(Attribute::CLASS_NAME);
|
||||
if ($className === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (! is_a($className, $interface, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($interfaceNode->getAttribute(Attribute::CLASS_NAME) === $interface) {
|
||||
if ($className === $interface) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,9 @@
|
||||
|
||||
namespace Rector\NodeTypeResolver\Application;
|
||||
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassConst;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\PhpParser\Node\Resolver\NameResolver;
|
||||
|
||||
@ -25,7 +27,11 @@ final class ConstantNodeCollector
|
||||
|
||||
public function addConstant(ClassConst $classConst): void
|
||||
{
|
||||
$className = (string) $classConst->getAttribute(Attribute::CLASS_NAME);
|
||||
$className = $classConst->getAttribute(Attribute::CLASS_NAME);
|
||||
if ($className === null) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$constantName = $this->nameResolver->resolve($classConst);
|
||||
|
||||
$this->constantsByType[$className][$constantName] = $classConst;
|
||||
|
@ -5,6 +5,7 @@ namespace Rector\NodeTypeResolver\Application;
|
||||
use Nette\Utils\Strings;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Function_;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\PhpParser\Node\Resolver\NameResolver;
|
||||
use ReflectionClass;
|
||||
@ -33,7 +34,11 @@ final class FunctionLikeNodeCollector
|
||||
|
||||
public function addMethod(ClassMethod $classMethodNode): void
|
||||
{
|
||||
$className = (string) $classMethodNode->getAttribute(Attribute::CLASS_NAME);
|
||||
$className = $classMethodNode->getAttribute(Attribute::CLASS_NAME);
|
||||
if ($className === null) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$methodName = $this->nameResolver->resolve($classMethodNode);
|
||||
|
||||
$this->methodsByType[$className][$methodName] = $classMethodNode;
|
||||
|
@ -30,6 +30,7 @@ final class Attribute
|
||||
public const CLASS_NAME = 'className';
|
||||
|
||||
/**
|
||||
* @todo split Class node, interface node and trait node, to be compatible with other SpecificNode|null, values
|
||||
* @var string
|
||||
*/
|
||||
public const CLASS_NODE = 'classNode';
|
||||
|
@ -12,6 +12,7 @@ use PhpParser\Node\Stmt\ClassConst;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PHPStan\Analyser\Scope;
|
||||
use PHPStan\Broker\Broker;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\Contract\NodeTypeResolverAwareInterface;
|
||||
use Rector\NodeTypeResolver\Contract\PerNodeTypeResolver\PerNodeTypeResolverInterface;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
@ -64,7 +65,7 @@ final class NodeTypeResolver
|
||||
public function resolve(Node $node): array
|
||||
{
|
||||
if ($node instanceof ClassMethod || $node instanceof ClassConst) {
|
||||
return $this->resolve($node->getAttribute(Attribute::CLASS_NODE));
|
||||
return $this->resolveClassNode($node);
|
||||
}
|
||||
|
||||
if ($node instanceof StaticCall || $node instanceof ClassConstFetch) {
|
||||
@ -106,6 +107,20 @@ final class NodeTypeResolver
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ClassConst|ClassMethod $node
|
||||
* @return string[]
|
||||
*/
|
||||
private function resolveClassNode(Node $node): array
|
||||
{
|
||||
$classNode = $node->getAttribute(Attribute::CLASS_NODE);
|
||||
if ($classNode === null) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
return $this->resolve($classNode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
*/
|
||||
|
@ -7,6 +7,7 @@ use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\Interface_;
|
||||
use PHPStan\Analyser\Scope;
|
||||
use PHPStan\Reflection\ClassReflection;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\Contract\PerNodeTypeResolver\PerNodeTypeResolverInterface;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\NodeTypeResolver\Reflection\ClassReflectionTypesResolver;
|
||||
@ -37,8 +38,10 @@ final class ClassAndInterfaceTypeResolver implements PerNodeTypeResolverInterfac
|
||||
*/
|
||||
public function resolve(Node $node): array
|
||||
{
|
||||
/** @var Scope $nodeScope */
|
||||
$nodeScope = $node->getAttribute(Attribute::SCOPE);
|
||||
if ($nodeScope === null) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
/** @var ClassReflection $classReflection */
|
||||
$classReflection = $nodeScope->getClassReflection();
|
||||
|
@ -25,13 +25,23 @@ final class NameTypeResolver implements PerNodeTypeResolverInterface
|
||||
public function resolve(Node $nameNode): array
|
||||
{
|
||||
if ($nameNode->toString() === 'parent') {
|
||||
return [$nameNode->getAttribute(Attribute::PARENT_CLASS_NAME)];
|
||||
$parentClassName = $nameNode->getAttribute(Attribute::PARENT_CLASS_NAME);
|
||||
if ($parentClassName === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [$parentClassName];
|
||||
}
|
||||
|
||||
return [$this->resolveFullyQualifiedName($nameNode, $nameNode->toString())];
|
||||
$fullyQualifiedName = $this->resolveFullyQualifiedName($nameNode, $nameNode->toString());
|
||||
if ($fullyQualifiedName === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [$fullyQualifiedName];
|
||||
}
|
||||
|
||||
private function resolveFullyQualifiedName(Node $nameNode, string $name): string
|
||||
private function resolveFullyQualifiedName(Node $nameNode, string $name): ?string
|
||||
{
|
||||
if (in_array($name, ['self', 'static', 'this'], true)) {
|
||||
return $nameNode->getAttribute(Attribute::CLASS_NAME);
|
||||
|
@ -24,7 +24,12 @@ final class NamespaceAnalyzer
|
||||
|
||||
public function resolveTypeToFullyQualified(string $type, Node $node): string
|
||||
{
|
||||
$useStatementMatch = $this->matchUseStatements($type, (array) $node->getAttribute(Attribute::USE_NODES));
|
||||
$useNodes = $node->getAttribute(Attribute::USE_NODES);
|
||||
if ($useNodes === null) {
|
||||
$useNodes = [];
|
||||
}
|
||||
|
||||
$useStatementMatch = $this->matchUseStatements($type, $useNodes);
|
||||
if ($useStatementMatch) {
|
||||
return $useStatementMatch;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Scalar\LNumber;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\Node\Stmt\For_;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
@ -150,7 +151,12 @@ CODE_SAMPLE
|
||||
'stmts' => [new Expression($funcCallNode)],
|
||||
]);
|
||||
|
||||
$this->addNodeAfterNode($forNode, $assignNode->getAttribute(Attribute::PREVIOUS_EXPRESSION));
|
||||
$previousExpression = $assignNode->getAttribute(Attribute::PREVIOUS_EXPRESSION);
|
||||
if ($previousExpression === null) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$this->addNodeAfterNode($forNode, $previousExpression);
|
||||
|
||||
return $assignNode;
|
||||
}
|
||||
|
@ -6,12 +6,12 @@ use Nette\Utils\Strings;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\ConstFetch;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
use Rector\RectorDefinition\RectorDefinition;
|
||||
use function Safe\sprintf;
|
||||
use Symplify\PackageBuilder\FileSystem\SmartFileInfo;
|
||||
|
||||
/**
|
||||
* @see https://wiki.php.net/rfc/deprecate-bareword-strings
|
||||
@ -50,8 +50,10 @@ final class BarewordStringRector extends AbstractRector
|
||||
}
|
||||
|
||||
// load the file!
|
||||
/** @var SmartFileInfo $fileInfo */
|
||||
$fileInfo = $node->getAttribute(Attribute::FILE_INFO);
|
||||
if ($fileInfo === null) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$this->undefinedConstants = [];
|
||||
$previousErrorHandler = set_error_handler(function ($severity, $message, $file, $line): void {
|
||||
|
@ -5,7 +5,6 @@ namespace Rector\Php\Rector\FuncCall;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\Rector\AbstractRector;
|
||||
use Rector\RectorDefinition\CodeSample;
|
||||
@ -70,7 +69,6 @@ CODE_SAMPLE
|
||||
*/
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
/** @var Expression|null $previousExpression */
|
||||
$previousExpression = $node->getAttribute(Attribute::PREVIOUS_EXPRESSION);
|
||||
if ($previousExpression === null) {
|
||||
return null;
|
||||
|
@ -6,7 +6,6 @@ use PhpParser\Node;
|
||||
use PhpParser\Node\Arg;
|
||||
use PhpParser\Node\Expr\FuncCall;
|
||||
use PhpParser\Node\Expr\Variable;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\PhpParser\NodeTraverser\CallableNodeTraverser;
|
||||
use Rector\Rector\AbstractRector;
|
||||
@ -64,17 +63,19 @@ CODE_SAMPLE
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isset($node->args[1])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$resultVariable = new Variable('result');
|
||||
$node->args[1] = new Arg($resultVariable);
|
||||
|
||||
/** @var Expression $expression */
|
||||
$expression = $node->getAttribute(Attribute::CURRENT_EXPRESSION);
|
||||
if ($expression === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// @todo maybe solve in generic way as attribute?
|
||||
$nextExpression = $expression->getAttribute(Attribute::NEXT_NODE);
|
||||
if ($nextExpression === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->callableNodeTraverser->traverseNodesWithCallable([$nextExpression], function (Node $node) use (
|
||||
$resultVariable
|
||||
|
@ -224,6 +224,9 @@ CODE_SAMPLE
|
||||
private function findAssigners(Node $variableNode): array
|
||||
{
|
||||
$methodNode = $variableNode->getAttribute(Attribute::METHOD_NODE);
|
||||
if ($methodNode === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
/** @var Assign[] $assignNode */
|
||||
return $this->betterNodeFinder->find([$methodNode], function (Node $node) use ($variableNode) {
|
||||
|
@ -13,6 +13,7 @@ use PhpParser\Node\Stmt\ClassLike;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Function_;
|
||||
use PhpParser\Node\Stmt\Interface_;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\Application\ClassLikeNodeCollector;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\NodeTypeResolver\Php\AbstractTypeInfo;
|
||||
@ -113,8 +114,10 @@ abstract class AbstractTypeDeclarationRector extends AbstractRector
|
||||
}
|
||||
}
|
||||
|
||||
/** @var Class_ $classNode */
|
||||
$classNode = $classMethodNode->getAttribute(Attribute::CLASS_NODE);
|
||||
if (($classNode instanceof Class_ || $classNode instanceof Interface_) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$interfaceNames = $this->getClassLikeNodeParentInterfaceNames($classNode);
|
||||
foreach ($interfaceNames as $interfaceName) {
|
||||
@ -192,6 +195,10 @@ abstract class AbstractTypeDeclarationRector extends AbstractRector
|
||||
|
||||
if ($nakedType->toString() === 'self') {
|
||||
$className = $node->getAttribute(Attribute::CLASS_NAME);
|
||||
if ($className === null) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$type = new FullyQualified($className);
|
||||
|
||||
return $returnTypeInfo->isNullable() ? new NullableType($type) : $type;
|
||||
@ -199,6 +206,10 @@ abstract class AbstractTypeDeclarationRector extends AbstractRector
|
||||
|
||||
if ($nakedType->toString() === 'parent') {
|
||||
$parentClassName = $node->getAttribute(Attribute::PARENT_CLASS_NAME);
|
||||
if ($parentClassName === null) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$type = new FullyQualified($parentClassName);
|
||||
|
||||
return $returnTypeInfo->isNullable() ? new NullableType($type) : $type;
|
||||
@ -215,7 +226,6 @@ abstract class AbstractTypeDeclarationRector extends AbstractRector
|
||||
|
||||
private function hasParentClassOrImplementsInterface(ClassMethod $classMethodNode): bool
|
||||
{
|
||||
/** @var ClassLike|null $classNode */
|
||||
$classNode = $classMethodNode->getAttribute(Attribute::CLASS_NODE);
|
||||
if ($classNode === null) {
|
||||
return false;
|
||||
|
@ -7,6 +7,7 @@ use PhpParser\Node\Expr\Assign;
|
||||
use PhpParser\Node\Expr\PropertyFetch;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\NodeTypeResolver\Node\NodeToStringTypeResolver;
|
||||
use Rector\NodeTypeResolver\NodeTypeAnalyzer;
|
||||
@ -133,8 +134,10 @@ CODE_SAMPLE
|
||||
$types[] = $this->nodeToStringTypeResolver->resolver($propertyDefault);
|
||||
}
|
||||
|
||||
/** @var Class_ $classNode */
|
||||
$classNode = $propertyNode->getAttribute(Attribute::CLASS_NODE);
|
||||
if (! $classNode instanceof Class_) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$propertyName = $this->getName($propertyNode);
|
||||
if ($propertyName === null) {
|
||||
@ -145,11 +148,9 @@ CODE_SAMPLE
|
||||
$propertyAssignNodes = $this->betterNodeFinder->find([$classNode], function (Node $node) use (
|
||||
$propertyName
|
||||
): bool {
|
||||
if ($node instanceof Assign) {
|
||||
if ($node->var instanceof PropertyFetch) {
|
||||
// is property match
|
||||
return $this->isName($node->var, $propertyName);
|
||||
}
|
||||
if ($node instanceof Assign && $node->var instanceof PropertyFetch) {
|
||||
// is property match
|
||||
return $this->isName($node->var, $propertyName);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -7,7 +7,9 @@ use PhpParser\Node\Expr\ClassConstFetch;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use Rector\Bridge\Contract\AnalyzedApplicationContainerInterface;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\Naming\PropertyNaming;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\Rector\AbstractRector;
|
||||
@ -43,12 +45,12 @@ abstract class AbstractToConstructorInjectionRector extends AbstractRector
|
||||
}
|
||||
|
||||
$propertyName = $this->propertyNaming->fqnToVariableName($serviceType);
|
||||
$classNode = $methodCallNode->getAttribute(Attribute::CLASS_NODE);
|
||||
if (! $classNode instanceof Class_) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$this->addPropertyToClass(
|
||||
$methodCallNode->getAttribute(Attribute::CLASS_NODE),
|
||||
$serviceType,
|
||||
$propertyName
|
||||
);
|
||||
$this->addPropertyToClass($classNode, $serviceType, $propertyName);
|
||||
|
||||
return $this->createPropertyFetch('this', $propertyName);
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ namespace Rector\Symfony\Rector\FrameworkBundle;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use Rector\Naming\PropertyNaming;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\Rector\AbstractRector;
|
||||
@ -94,8 +95,13 @@ CODE_SAMPLE
|
||||
$parameterName = $stringArgument->value;
|
||||
$propertyName = $this->propertyNaming->underscoreToName($parameterName);
|
||||
|
||||
$classNode = $node->getAttribute(Attribute::CLASS_NODE);
|
||||
if (! $classNode instanceof Class_) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->addPropertyToClass(
|
||||
$node->getAttribute(Attribute::CLASS_NODE),
|
||||
$classNode,
|
||||
'string', // @todo: resolve type from container provider? see parameter autowire compiler pass
|
||||
$propertyName
|
||||
);
|
||||
|
@ -147,6 +147,9 @@ CODE_SAMPLE
|
||||
}
|
||||
|
||||
$methodNode = $node->getAttribute(Attribute::METHOD_NODE);
|
||||
if ($methodNode === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->controllerMethodAnalyzer->isAction($methodNode);
|
||||
}
|
||||
|
@ -148,6 +148,7 @@ CODE_SAMPLE
|
||||
);
|
||||
|
||||
$parentNode = $node->getAttribute(Attribute::PARENT_NODE);
|
||||
|
||||
while ($parentNode instanceof MethodCall) {
|
||||
if ($this->isName($parentNode, 'add')) {
|
||||
/** @var Array_ $addOptionsArrayNode */
|
||||
|
@ -101,9 +101,15 @@ CODE_SAMPLE
|
||||
|
||||
private function getRootMethodCallNode(Node $node): ?Node
|
||||
{
|
||||
/** @var Node $node */
|
||||
$expression = $node->getAttribute(Attribute::CURRENT_EXPRESSION);
|
||||
if ($expression === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$nextExpression = $expression->getAttribute(Attribute::NEXT_NODE);
|
||||
if ($nextExpression === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->betterNodeFinder->findFirst([$nextExpression], function (Node $node) {
|
||||
if (! $node instanceof MethodCall) {
|
||||
|
@ -118,6 +118,10 @@ CODE_SAMPLE
|
||||
}
|
||||
|
||||
$classNode = $node->getAttribute(Attribute::CLASS_NODE);
|
||||
if ($classNode === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (! $this->isTypes($classNode, [$this->twigExtensionClass])) {
|
||||
return null;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ includes:
|
||||
|
||||
parameters:
|
||||
# to allow intalling with various phsptan versions without reporting old errors here
|
||||
# reportUnmatchedIgnoredErrors: false
|
||||
reportUnmatchedIgnoredErrors: false
|
||||
level: 7
|
||||
|
||||
excludes_analyse:
|
||||
|
@ -22,9 +22,7 @@ final class BetterNodeFinder
|
||||
|
||||
public function findFirstAncestorInstanceOf(Node $node, string $type): ?Node
|
||||
{
|
||||
/** @var Node|null $currentNode */
|
||||
$currentNode = $node->getAttribute(Attribute::PARENT_NODE);
|
||||
|
||||
while ($currentNode !== null) {
|
||||
if ($currentNode instanceof $type) {
|
||||
return $currentNode;
|
||||
@ -86,6 +84,9 @@ final class BetterNodeFinder
|
||||
public function findFirstPrevious(Node $node, callable $filter): ?Node
|
||||
{
|
||||
$node = $node instanceof Expression ? $node : $node->getAttribute(Attribute::CURRENT_EXPRESSION);
|
||||
if ($node === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$foundNode = $this->findFirst([$node], $filter);
|
||||
// we found what we need
|
||||
|
@ -7,8 +7,9 @@ use PhpParser\Node\Expr;
|
||||
use PhpParser\Node\Expr\ClassConstFetch;
|
||||
use PhpParser\Node\Identifier;
|
||||
use PhpParser\Node\Scalar\MagicConst\Dir;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Symfony\Component\Finder\SplFileInfo;
|
||||
use Symplify\PackageBuilder\FileSystem\SmartFileInfo;
|
||||
|
||||
final class ConstExprEvaluatorFactory
|
||||
{
|
||||
@ -17,8 +18,10 @@ final class ConstExprEvaluatorFactory
|
||||
return new ConstExprEvaluator(function (Expr $expr): ?string {
|
||||
// resolve "__DIR__"
|
||||
if ($expr instanceof Dir) {
|
||||
/** @var SplFileInfo $fileInfo */
|
||||
$fileInfo = $expr->getAttribute(Attribute::FILE_INFO);
|
||||
if (! $fileInfo instanceof SmartFileInfo) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
return $fileInfo->getPath();
|
||||
}
|
||||
@ -34,13 +37,16 @@ final class ConstExprEvaluatorFactory
|
||||
|
||||
private function resolveClassConstFetch(ClassConstFetch $classConstFetchNode): string
|
||||
{
|
||||
$class = $classConstFetchNode->class->getAttribute(Attribute::RESOLVED_NAME)->toString();
|
||||
$class = $classConstFetchNode->class->getAttribute(Attribute::RESOLVED_NAME);
|
||||
if ($class === null) {
|
||||
return '';
|
||||
}
|
||||
|
||||
/** @var Identifier $identifierNode */
|
||||
$identifierNode = $classConstFetchNode->name;
|
||||
|
||||
$constant = $identifierNode->toString();
|
||||
|
||||
return $class . '::' . $constant;
|
||||
return $class->toString() . '::' . $constant;
|
||||
}
|
||||
}
|
||||
|
@ -39,8 +39,9 @@ final class ChildAndParentClassMaintainer
|
||||
|
||||
public function completeParentConstructor(Class_ $classNode, ClassMethod $constructorClassMethodNode): void
|
||||
{
|
||||
$parentClassName = (string) $classNode->getAttribute(Attribute::PARENT_CLASS_NAME);
|
||||
if (! $parentClassName) {
|
||||
/** @var string|null $parentClassName */
|
||||
$parentClassName = $classNode->getAttribute(Attribute::PARENT_CLASS_NAME);
|
||||
if ($parentClassName === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -114,9 +115,9 @@ final class ChildAndParentClassMaintainer
|
||||
return $constructMethodNode;
|
||||
}
|
||||
|
||||
/** @var string $parentClassName */
|
||||
/** @var string|null $parentClassName */
|
||||
$parentClassName = $classNode->getAttribute(Attribute::PARENT_CLASS_NAME);
|
||||
if (! $parentClassName) {
|
||||
if ($parentClassName === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -42,17 +42,21 @@ final class ClassMethodMaintainer
|
||||
public function hasParentMethodOrInterfaceMethod(ClassMethod $classMethod): bool
|
||||
{
|
||||
$class = $classMethod->getAttribute(Attribute::CLASS_NAME);
|
||||
if ($class === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$method = $classMethod->getAttribute(Attribute::METHOD_NAME);
|
||||
if ($method === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (! class_exists($class)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$parentClass = $class;
|
||||
while ($parentClass = get_parent_class($parentClass)) {
|
||||
if (method_exists($parentClass, $method)) {
|
||||
return true;
|
||||
}
|
||||
if ($this->isMethodInParent($class, $method)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$implementedInterfaces = class_implements($class);
|
||||
@ -87,6 +91,19 @@ final class ClassMethodMaintainer
|
||||
return false;
|
||||
}
|
||||
|
||||
private function isMethodInParent(string $class, string $method): bool
|
||||
{
|
||||
$parentClass = $class;
|
||||
|
||||
while ($parentClass = get_parent_class($parentClass)) {
|
||||
if (method_exists($parentClass, $method)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function isArrayOfArrays(Node $node): bool
|
||||
{
|
||||
if (! $node instanceof Array_) {
|
||||
|
@ -47,6 +47,9 @@ final class PropertyMaintainer
|
||||
public function getAllPropertyFetch(Property $propertyNode): array
|
||||
{
|
||||
$classNode = $propertyNode->getAttribute(Attribute::CLASS_NODE);
|
||||
if ($classNode === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $this->betterNodeFinder->find($classNode, function (Node $node) use ($propertyNode) {
|
||||
// itself
|
||||
|
@ -3,14 +3,12 @@
|
||||
namespace Rector\Rector;
|
||||
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
|
||||
abstract class AbstractPHPUnitRector extends AbstractRector
|
||||
{
|
||||
protected function isInTestClass(Node $node): bool
|
||||
{
|
||||
/** @var Class_|null $classNode */
|
||||
$classNode = $node->getAttribute(Attribute::CLASS_NODE);
|
||||
if ($classNode === null) {
|
||||
return false;
|
||||
|
@ -161,7 +161,6 @@ abstract class AbstractRector extends NodeVisitorAbstract implements PhpRectorIn
|
||||
|
||||
protected function notifyNodeChangeFileInfo(Node $node): void
|
||||
{
|
||||
/** @var SmartFileInfo|null $fileInfo */
|
||||
$fileInfo = $node->getAttribute(Attribute::FILE_INFO);
|
||||
if ($fileInfo === null) {
|
||||
throw new ShouldNotHappenException(sprintf(
|
||||
|
@ -5,6 +5,7 @@ namespace Rector\Rector\Annotation;
|
||||
use PhpParser\Node;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Property;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
use Rector\NodeTypeResolver\Node\Attribute;
|
||||
use Rector\NodeTypeResolver\PhpDoc\NodeAnalyzer\DocBlockAnalyzer;
|
||||
use Rector\Rector\AbstractPHPUnitRector;
|
||||
@ -94,8 +95,11 @@ CODE_SAMPLE
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @var Node $parentNode */
|
||||
$parentNode = $node->getAttribute(Attribute::PARENT_NODE);
|
||||
if ($parentNode === null) {
|
||||
throw new ShouldNotHappenException();
|
||||
}
|
||||
|
||||
$parentNodeTypes = $this->getTypes($parentNode);
|
||||
foreach ($this->classToAnnotationMap as $type => $annotationMap) {
|
||||
if (! in_array($type, $parentNodeTypes, true)) {
|
||||
@ -122,9 +126,9 @@ CODE_SAMPLE
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @var Node|null $parentNode */
|
||||
$parentNode = $node->getAttribute(Attribute::PARENT_NODE);
|
||||
return ! $parentNode;
|
||||
|
||||
return $parentNode === null;
|
||||
}
|
||||
|
||||
private function hasAnyAnnotation(Node $node): bool
|
||||
|
@ -105,6 +105,10 @@ CODE_SAMPLE
|
||||
private function addPropertyToCollector(Property $propertyNode): void
|
||||
{
|
||||
$classNode = $propertyNode->getAttribute(Attribute::CLASS_NODE);
|
||||
if (! $classNode instanceof Class_) {
|
||||
return;
|
||||
}
|
||||
|
||||
$mainPropertyType = $this->getTypes($propertyNode)[0];
|
||||
$propertyName = $this->getName($propertyNode);
|
||||
if ($propertyName === null) {
|
||||
|
@ -8,6 +8,7 @@ use PhpParser\Node\Expr\ClassConstFetch;
|
||||
use PhpParser\Node\Expr\MethodCall;
|
||||
use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Scalar\String_;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use Rector\Bridge\Contract\DoctrineEntityAndRepositoryMapperInterface;
|
||||
use Rector\Exception\Bridge\RectorProviderException;
|
||||
use Rector\Exception\ShouldNotHappenException;
|
||||
@ -123,9 +124,13 @@ CODE_SAMPLE
|
||||
}
|
||||
|
||||
$repositoryFqn = $this->repositoryFqn($node);
|
||||
$classNode = $node->getAttribute(Attribute::CLASS_NODE);
|
||||
if (! $classNode instanceof Class_) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$this->addPropertyToClass(
|
||||
$node->getAttribute(Attribute::CLASS_NODE),
|
||||
$classNode,
|
||||
$repositoryFqn,
|
||||
$this->propertyNaming->fqnToVariableName($repositoryFqn)
|
||||
);
|
||||
|
@ -83,7 +83,12 @@ CODE_SAMPLE
|
||||
public function refactor(Node $node): ?Node
|
||||
{
|
||||
foreach ($this->propertyToVisibilityByClass as $type => $propertyToVisibility) {
|
||||
if (! $this->isType($node->getAttribute(Attribute::CLASS_NODE), $type)) {
|
||||
$classNode = $node->getAttribute(Attribute::CLASS_NODE);
|
||||
if ($classNode === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $this->isType($classNode, $type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
namespace Rector\Tests\Rector\Annotation\AnnotationReplacerRector;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Rector\Rector\Annotation\AnnotationReplacerRector;
|
||||
use Rector\Testing\PHPUnit\AbstractRectorTestCase;
|
||||
|
||||
@ -23,6 +22,8 @@ final class ScenarioToTestAnnotationRectorTest extends AbstractRectorTestCase
|
||||
*/
|
||||
protected function getRectorConfiguration(): array
|
||||
{
|
||||
return [TestCase::class => ['scenario' => 'test']];
|
||||
return [
|
||||
'PHPUnit\Framework\TestCase' => ['scenario' => 'test'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user