From 2c878c7541bd171423d42e049a1f688a3374442e Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Fri, 25 Jan 2019 01:49:26 +0100 Subject: [PATCH] apply new static analysis --- .../Return_/SimplifyUselessVariableRector.php | 8 +++- .../ReturnArrayClassMethodToYieldRector.php | 34 +++++++++++------ .../Rector/Use_/RemoveUnusedAliasRector.php | 18 ++++----- .../RemoveParentCallWithoutParentRector.php | 9 +++-- .../ObjectToScalarDocBlockRector.php | 4 ++ .../Property/JmsInjectAnnotationRector.php | 8 +++- .../Application/ClassLikeNodeCollector.php | 37 +++++++++++++++---- .../src/Application/ConstantNodeCollector.php | 8 +++- .../Application/FunctionLikeNodeCollector.php | 7 +++- .../NodeTypeResolver/src/Node/Attribute.php | 1 + .../NodeTypeResolver/src/NodeTypeResolver.php | 17 ++++++++- .../ClassAndInterfaceTypeResolver.php | 5 ++- .../PerNodeTypeResolver/NameTypeResolver.php | 16 ++++++-- .../PhpDoc/NodeAnalyzer/NamespaceAnalyzer.php | 7 +++- .../Assign/MysqlAssignToMysqliRector.php | 8 +++- .../ConstFetch/BarewordStringRector.php | 6 ++- .../FuncCall/ArrayKeyFirstLastRector.php | 2 - .../ParseStrWithResultArgumentRector.php | 13 ++++--- .../Rector/FuncCall/RegexDashEscapeRector.php | 3 ++ .../AbstractTypeDeclarationRector.php | 14 ++++++- .../CompleteVarDocTypePropertyRector.php | 13 ++++--- .../AbstractToConstructorInjectionRector.php | 12 +++--- ...tParameterToConstructorInjectionRector.php | 8 +++- .../Rector/HttpKernel/GetRequestRector.php | 3 ++ .../CascadeValidationFormBuilderRector.php | 1 + .../Rector/New_/RootNodeTreeBuilderRector.php | 8 +++- .../Rector/SimpleFunctionAndFilterRector.php | 4 ++ phpstan.neon | 2 +- src/PhpParser/Node/BetterNodeFinder.php | 5 ++- .../Node/ConstExprEvaluatorFactory.php | 14 +++++-- .../ChildAndParentClassMaintainer.php | 9 +++-- .../Node/Maintainer/ClassMethodMaintainer.php | 27 +++++++++++--- .../Node/Maintainer/PropertyMaintainer.php | 3 ++ src/Rector/AbstractPHPUnitRector.php | 2 - src/Rector/AbstractRector.php | 1 - .../Annotation/AnnotationReplacerRector.php | 10 +++-- ...ertyInjectToConstructorInjectionRector.php | 4 ++ .../ServiceLocatorToDIRector.php | 7 +++- .../ChangePropertyVisibilityRector.php | 7 +++- .../ScenarioToTestAnnotationRectorTest.php | 5 ++- 40 files changed, 277 insertions(+), 93 deletions(-) diff --git a/packages/CodeQuality/src/Rector/Return_/SimplifyUselessVariableRector.php b/packages/CodeQuality/src/Rector/Return_/SimplifyUselessVariableRector.php index f51bc2c2999..225e57c9719 100644 --- a/packages/CodeQuality/src/Rector/Return_/SimplifyUselessVariableRector.php +++ b/packages/CodeQuality/src/Rector/Return_/SimplifyUselessVariableRector.php @@ -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 diff --git a/packages/CodingStyle/src/Rector/ClassMethod/ReturnArrayClassMethodToYieldRector.php b/packages/CodingStyle/src/Rector/ClassMethod/ReturnArrayClassMethodToYieldRector.php index bb99ebeea92..dead56b3a9f 100644 --- a/packages/CodingStyle/src/Rector/ClassMethod/ReturnArrayClassMethodToYieldRector.php +++ b/packages/CodingStyle/src/Rector/ClassMethod/ReturnArrayClassMethodToYieldRector.php @@ -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); + } } diff --git a/packages/CodingStyle/src/Rector/Use_/RemoveUnusedAliasRector.php b/packages/CodingStyle/src/Rector/Use_/RemoveUnusedAliasRector.php index 8cfa3a67705..e5f229cb545 100644 --- a/packages/CodingStyle/src/Rector/Use_/RemoveUnusedAliasRector.php +++ b/packages/CodingStyle/src/Rector/Use_/RemoveUnusedAliasRector.php @@ -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]; } } diff --git a/packages/DeadCode/src/Rector/StaticCall/RemoveParentCallWithoutParentRector.php b/packages/DeadCode/src/Rector/StaticCall/RemoveParentCallWithoutParentRector.php index 890b055a109..5c40009ffe1 100644 --- a/packages/DeadCode/src/Rector/StaticCall/RemoveParentCallWithoutParentRector.php +++ b/packages/DeadCode/src/Rector/StaticCall/RemoveParentCallWithoutParentRector.php @@ -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; } diff --git a/packages/DomainDrivenDesign/src/Rector/ObjectToScalar/ObjectToScalarDocBlockRector.php b/packages/DomainDrivenDesign/src/Rector/ObjectToScalar/ObjectToScalarDocBlockRector.php index 779f1c48f0c..e63db9e79c3 100644 --- a/packages/DomainDrivenDesign/src/Rector/ObjectToScalar/ObjectToScalarDocBlockRector.php +++ b/packages/DomainDrivenDesign/src/Rector/ObjectToScalar/ObjectToScalarDocBlockRector.php @@ -121,6 +121,10 @@ CODE_SAMPLE $node = $exprNode->getAttribute(Attribute::PARENT_NODE); } + if ($node === null) { + return; + } + $this->docBlockAnalyzer->changeType($node, $oldType, $newType); } diff --git a/packages/Jms/src/Rector/Property/JmsInjectAnnotationRector.php b/packages/Jms/src/Rector/Property/JmsInjectAnnotationRector.php index 30b781da594..2ed05e708f3 100644 --- a/packages/Jms/src/Rector/Property/JmsInjectAnnotationRector.php +++ b/packages/Jms/src/Rector/Property/JmsInjectAnnotationRector.php @@ -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; } diff --git a/packages/NodeTypeResolver/src/Application/ClassLikeNodeCollector.php b/packages/NodeTypeResolver/src/Application/ClassLikeNodeCollector.php index c0871f99ad4..6e08b850d0c 100644 --- a/packages/NodeTypeResolver/src/Application/ClassLikeNodeCollector.php +++ b/packages/NodeTypeResolver/src/Application/ClassLikeNodeCollector.php @@ -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; } diff --git a/packages/NodeTypeResolver/src/Application/ConstantNodeCollector.php b/packages/NodeTypeResolver/src/Application/ConstantNodeCollector.php index 3580834d946..c18d44761d9 100644 --- a/packages/NodeTypeResolver/src/Application/ConstantNodeCollector.php +++ b/packages/NodeTypeResolver/src/Application/ConstantNodeCollector.php @@ -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; diff --git a/packages/NodeTypeResolver/src/Application/FunctionLikeNodeCollector.php b/packages/NodeTypeResolver/src/Application/FunctionLikeNodeCollector.php index e89e3790884..20099102a3f 100644 --- a/packages/NodeTypeResolver/src/Application/FunctionLikeNodeCollector.php +++ b/packages/NodeTypeResolver/src/Application/FunctionLikeNodeCollector.php @@ -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; diff --git a/packages/NodeTypeResolver/src/Node/Attribute.php b/packages/NodeTypeResolver/src/Node/Attribute.php index 824c9046dbd..a870fe787f4 100644 --- a/packages/NodeTypeResolver/src/Node/Attribute.php +++ b/packages/NodeTypeResolver/src/Node/Attribute.php @@ -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'; diff --git a/packages/NodeTypeResolver/src/NodeTypeResolver.php b/packages/NodeTypeResolver/src/NodeTypeResolver.php index b50cecb5a42..d85ff3a43b6 100644 --- a/packages/NodeTypeResolver/src/NodeTypeResolver.php +++ b/packages/NodeTypeResolver/src/NodeTypeResolver.php @@ -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[] */ diff --git a/packages/NodeTypeResolver/src/PerNodeTypeResolver/ClassAndInterfaceTypeResolver.php b/packages/NodeTypeResolver/src/PerNodeTypeResolver/ClassAndInterfaceTypeResolver.php index 1b7b495287f..e8fbae8f32f 100644 --- a/packages/NodeTypeResolver/src/PerNodeTypeResolver/ClassAndInterfaceTypeResolver.php +++ b/packages/NodeTypeResolver/src/PerNodeTypeResolver/ClassAndInterfaceTypeResolver.php @@ -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(); diff --git a/packages/NodeTypeResolver/src/PerNodeTypeResolver/NameTypeResolver.php b/packages/NodeTypeResolver/src/PerNodeTypeResolver/NameTypeResolver.php index eb5fbfd1649..07063b44458 100644 --- a/packages/NodeTypeResolver/src/PerNodeTypeResolver/NameTypeResolver.php +++ b/packages/NodeTypeResolver/src/PerNodeTypeResolver/NameTypeResolver.php @@ -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); diff --git a/packages/NodeTypeResolver/src/PhpDoc/NodeAnalyzer/NamespaceAnalyzer.php b/packages/NodeTypeResolver/src/PhpDoc/NodeAnalyzer/NamespaceAnalyzer.php index 85d1d9a998d..b3bc166b45d 100644 --- a/packages/NodeTypeResolver/src/PhpDoc/NodeAnalyzer/NamespaceAnalyzer.php +++ b/packages/NodeTypeResolver/src/PhpDoc/NodeAnalyzer/NamespaceAnalyzer.php @@ -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; } diff --git a/packages/Php/src/Rector/Assign/MysqlAssignToMysqliRector.php b/packages/Php/src/Rector/Assign/MysqlAssignToMysqliRector.php index 76bbb9515c5..8f4479b5bd5 100644 --- a/packages/Php/src/Rector/Assign/MysqlAssignToMysqliRector.php +++ b/packages/Php/src/Rector/Assign/MysqlAssignToMysqliRector.php @@ -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; } diff --git a/packages/Php/src/Rector/ConstFetch/BarewordStringRector.php b/packages/Php/src/Rector/ConstFetch/BarewordStringRector.php index af557fb0f36..9f99adad121 100644 --- a/packages/Php/src/Rector/ConstFetch/BarewordStringRector.php +++ b/packages/Php/src/Rector/ConstFetch/BarewordStringRector.php @@ -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 { diff --git a/packages/Php/src/Rector/FuncCall/ArrayKeyFirstLastRector.php b/packages/Php/src/Rector/FuncCall/ArrayKeyFirstLastRector.php index 17ef5d95a83..f5dd3446fbf 100644 --- a/packages/Php/src/Rector/FuncCall/ArrayKeyFirstLastRector.php +++ b/packages/Php/src/Rector/FuncCall/ArrayKeyFirstLastRector.php @@ -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; diff --git a/packages/Php/src/Rector/FuncCall/ParseStrWithResultArgumentRector.php b/packages/Php/src/Rector/FuncCall/ParseStrWithResultArgumentRector.php index 8ab3a6aece7..18b465bcbc9 100644 --- a/packages/Php/src/Rector/FuncCall/ParseStrWithResultArgumentRector.php +++ b/packages/Php/src/Rector/FuncCall/ParseStrWithResultArgumentRector.php @@ -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 diff --git a/packages/Php/src/Rector/FuncCall/RegexDashEscapeRector.php b/packages/Php/src/Rector/FuncCall/RegexDashEscapeRector.php index 89b629ac798..26a0cb24d76 100644 --- a/packages/Php/src/Rector/FuncCall/RegexDashEscapeRector.php +++ b/packages/Php/src/Rector/FuncCall/RegexDashEscapeRector.php @@ -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) { diff --git a/packages/Php/src/Rector/FunctionLike/AbstractTypeDeclarationRector.php b/packages/Php/src/Rector/FunctionLike/AbstractTypeDeclarationRector.php index 6473a53ad9a..737b937bd81 100644 --- a/packages/Php/src/Rector/FunctionLike/AbstractTypeDeclarationRector.php +++ b/packages/Php/src/Rector/FunctionLike/AbstractTypeDeclarationRector.php @@ -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; diff --git a/packages/Php/src/Rector/Property/CompleteVarDocTypePropertyRector.php b/packages/Php/src/Rector/Property/CompleteVarDocTypePropertyRector.php index 765251ffea6..1e12aa6be71 100644 --- a/packages/Php/src/Rector/Property/CompleteVarDocTypePropertyRector.php +++ b/packages/Php/src/Rector/Property/CompleteVarDocTypePropertyRector.php @@ -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; diff --git a/packages/Symfony/src/Rector/FrameworkBundle/AbstractToConstructorInjectionRector.php b/packages/Symfony/src/Rector/FrameworkBundle/AbstractToConstructorInjectionRector.php index 9590a6ee405..9394db5bfaf 100644 --- a/packages/Symfony/src/Rector/FrameworkBundle/AbstractToConstructorInjectionRector.php +++ b/packages/Symfony/src/Rector/FrameworkBundle/AbstractToConstructorInjectionRector.php @@ -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); } diff --git a/packages/Symfony/src/Rector/FrameworkBundle/GetParameterToConstructorInjectionRector.php b/packages/Symfony/src/Rector/FrameworkBundle/GetParameterToConstructorInjectionRector.php index 81630267ac1..ebe561f31ed 100644 --- a/packages/Symfony/src/Rector/FrameworkBundle/GetParameterToConstructorInjectionRector.php +++ b/packages/Symfony/src/Rector/FrameworkBundle/GetParameterToConstructorInjectionRector.php @@ -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 ); diff --git a/packages/Symfony/src/Rector/HttpKernel/GetRequestRector.php b/packages/Symfony/src/Rector/HttpKernel/GetRequestRector.php index 95de0f7d7e6..d5a5f43e96f 100644 --- a/packages/Symfony/src/Rector/HttpKernel/GetRequestRector.php +++ b/packages/Symfony/src/Rector/HttpKernel/GetRequestRector.php @@ -147,6 +147,9 @@ CODE_SAMPLE } $methodNode = $node->getAttribute(Attribute::METHOD_NODE); + if ($methodNode === null) { + return false; + } return $this->controllerMethodAnalyzer->isAction($methodNode); } diff --git a/packages/Symfony/src/Rector/MethodCall/CascadeValidationFormBuilderRector.php b/packages/Symfony/src/Rector/MethodCall/CascadeValidationFormBuilderRector.php index a1f4185d799..d155f20980c 100644 --- a/packages/Symfony/src/Rector/MethodCall/CascadeValidationFormBuilderRector.php +++ b/packages/Symfony/src/Rector/MethodCall/CascadeValidationFormBuilderRector.php @@ -148,6 +148,7 @@ CODE_SAMPLE ); $parentNode = $node->getAttribute(Attribute::PARENT_NODE); + while ($parentNode instanceof MethodCall) { if ($this->isName($parentNode, 'add')) { /** @var Array_ $addOptionsArrayNode */ diff --git a/packages/Symfony/src/Rector/New_/RootNodeTreeBuilderRector.php b/packages/Symfony/src/Rector/New_/RootNodeTreeBuilderRector.php index 3c6756940bb..3a7f6960660 100644 --- a/packages/Symfony/src/Rector/New_/RootNodeTreeBuilderRector.php +++ b/packages/Symfony/src/Rector/New_/RootNodeTreeBuilderRector.php @@ -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) { diff --git a/packages/Twig/src/Rector/SimpleFunctionAndFilterRector.php b/packages/Twig/src/Rector/SimpleFunctionAndFilterRector.php index 4578b850576..99e58393552 100644 --- a/packages/Twig/src/Rector/SimpleFunctionAndFilterRector.php +++ b/packages/Twig/src/Rector/SimpleFunctionAndFilterRector.php @@ -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; } diff --git a/phpstan.neon b/phpstan.neon index 658c49ce83e..0430eb50f78 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -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: diff --git a/src/PhpParser/Node/BetterNodeFinder.php b/src/PhpParser/Node/BetterNodeFinder.php index 491a23981a7..a082bf855ea 100644 --- a/src/PhpParser/Node/BetterNodeFinder.php +++ b/src/PhpParser/Node/BetterNodeFinder.php @@ -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 diff --git a/src/PhpParser/Node/ConstExprEvaluatorFactory.php b/src/PhpParser/Node/ConstExprEvaluatorFactory.php index 5be9b0a1a3f..b7a9535e19e 100644 --- a/src/PhpParser/Node/ConstExprEvaluatorFactory.php +++ b/src/PhpParser/Node/ConstExprEvaluatorFactory.php @@ -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; } } diff --git a/src/PhpParser/Node/Maintainer/ChildAndParentClassMaintainer.php b/src/PhpParser/Node/Maintainer/ChildAndParentClassMaintainer.php index 9caea2c0750..76b8b2b150d 100644 --- a/src/PhpParser/Node/Maintainer/ChildAndParentClassMaintainer.php +++ b/src/PhpParser/Node/Maintainer/ChildAndParentClassMaintainer.php @@ -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; } diff --git a/src/PhpParser/Node/Maintainer/ClassMethodMaintainer.php b/src/PhpParser/Node/Maintainer/ClassMethodMaintainer.php index e6b904bb97a..6b0747c5c3b 100644 --- a/src/PhpParser/Node/Maintainer/ClassMethodMaintainer.php +++ b/src/PhpParser/Node/Maintainer/ClassMethodMaintainer.php @@ -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_) { diff --git a/src/PhpParser/Node/Maintainer/PropertyMaintainer.php b/src/PhpParser/Node/Maintainer/PropertyMaintainer.php index 68b08ac5a85..c090a73b554 100644 --- a/src/PhpParser/Node/Maintainer/PropertyMaintainer.php +++ b/src/PhpParser/Node/Maintainer/PropertyMaintainer.php @@ -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 diff --git a/src/Rector/AbstractPHPUnitRector.php b/src/Rector/AbstractPHPUnitRector.php index d273e25862c..7fd3a11351c 100644 --- a/src/Rector/AbstractPHPUnitRector.php +++ b/src/Rector/AbstractPHPUnitRector.php @@ -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; diff --git a/src/Rector/AbstractRector.php b/src/Rector/AbstractRector.php index aec68a470bf..d612cb3c419 100644 --- a/src/Rector/AbstractRector.php +++ b/src/Rector/AbstractRector.php @@ -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( diff --git a/src/Rector/Annotation/AnnotationReplacerRector.php b/src/Rector/Annotation/AnnotationReplacerRector.php index bf83c7dc391..aacbc54259e 100644 --- a/src/Rector/Annotation/AnnotationReplacerRector.php +++ b/src/Rector/Annotation/AnnotationReplacerRector.php @@ -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 diff --git a/src/Rector/Architecture/DependencyInjection/AnnotatedPropertyInjectToConstructorInjectionRector.php b/src/Rector/Architecture/DependencyInjection/AnnotatedPropertyInjectToConstructorInjectionRector.php index 3e0995b9a54..1f775eba2b2 100644 --- a/src/Rector/Architecture/DependencyInjection/AnnotatedPropertyInjectToConstructorInjectionRector.php +++ b/src/Rector/Architecture/DependencyInjection/AnnotatedPropertyInjectToConstructorInjectionRector.php @@ -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) { diff --git a/src/Rector/Architecture/RepositoryAsService/ServiceLocatorToDIRector.php b/src/Rector/Architecture/RepositoryAsService/ServiceLocatorToDIRector.php index d0c2b22a858..d618d2ddcee 100644 --- a/src/Rector/Architecture/RepositoryAsService/ServiceLocatorToDIRector.php +++ b/src/Rector/Architecture/RepositoryAsService/ServiceLocatorToDIRector.php @@ -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) ); diff --git a/src/Rector/Visibility/ChangePropertyVisibilityRector.php b/src/Rector/Visibility/ChangePropertyVisibilityRector.php index 96354ff865c..d118fec89c4 100644 --- a/src/Rector/Visibility/ChangePropertyVisibilityRector.php +++ b/src/Rector/Visibility/ChangePropertyVisibilityRector.php @@ -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; } diff --git a/tests/Rector/Annotation/AnnotationReplacerRector/ScenarioToTestAnnotationRectorTest.php b/tests/Rector/Annotation/AnnotationReplacerRector/ScenarioToTestAnnotationRectorTest.php index ea992e2ddf5..e661611c557 100644 --- a/tests/Rector/Annotation/AnnotationReplacerRector/ScenarioToTestAnnotationRectorTest.php +++ b/tests/Rector/Annotation/AnnotationReplacerRector/ScenarioToTestAnnotationRectorTest.php @@ -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'], + ]; } }