diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index b69e02a10b..3b1d68d9b7 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -595,12 +595,22 @@ private function processStmtNode( $gatheredReturnStatements[] = new ReturnStatement($scope, $node); }, StatementContext::createTopLevel()); + + $classReflection = $scope->getClassReflection(); + + $methodReflection = $methodScope->getFunction(); + if (!$methodReflection instanceof MethodReflection) { + throw new ShouldNotHappenException(); + } + $nodeCallback(new MethodReturnStatementsNode( $stmt, $gatheredReturnStatements, $gatheredYieldStatements, $statementResult, $executionEnds, + $classReflection, + $methodReflection, ), $methodScope); } } elseif ($stmt instanceof Echo_) { @@ -696,8 +706,8 @@ private function processStmtNode( $this->processStmtNodes($stmt, $stmt->stmts, $classScope, $classStatementsGatherer, $context); $nodeCallback(new ClassPropertiesNode($stmt, $this->readWritePropertiesExtensionProvider, $classStatementsGatherer->getProperties(), $classStatementsGatherer->getPropertyUsages(), $classStatementsGatherer->getMethodCalls(), $classStatementsGatherer->getReturnStatementsNodes(), $classReflection), $classScope); - $nodeCallback(new ClassMethodsNode($stmt, $classStatementsGatherer->getMethods(), $classStatementsGatherer->getMethodCalls()), $classScope); - $nodeCallback(new ClassConstantsNode($stmt, $classStatementsGatherer->getConstants(), $classStatementsGatherer->getConstantFetches()), $classScope); + $nodeCallback(new ClassMethodsNode($stmt, $classStatementsGatherer->getMethods(), $classStatementsGatherer->getMethodCalls(), $classReflection), $classScope); + $nodeCallback(new ClassConstantsNode($stmt, $classStatementsGatherer->getConstants(), $classStatementsGatherer->getConstantFetches(), $classReflection), $classScope); $classReflection->evictPrivateSymbols(); $this->calledMethodResults = []; } elseif ($stmt instanceof Node\Stmt\Property) { @@ -4423,11 +4433,7 @@ private function processCalledMethod(MethodReflection $methodReflection): ?Mutat return; } - if (!$scope->isInClass()) { - return; - } - - if ($scope->getClassReflection()->getName() !== $methodReflection->getDeclaringClass()->getName()) { + if ($node->getClassReflection()->getName() !== $methodReflection->getDeclaringClass()->getName()) { return; } diff --git a/src/Node/ClassConstantsNode.php b/src/Node/ClassConstantsNode.php index 4572ff79eb..dee7d0019a 100644 --- a/src/Node/ClassConstantsNode.php +++ b/src/Node/ClassConstantsNode.php @@ -6,6 +6,7 @@ use PhpParser\Node\Stmt\ClassLike; use PhpParser\NodeAbstract; use PHPStan\Node\Constant\ClassConstantFetch; +use PHPStan\Reflection\ClassReflection; /** @api */ class ClassConstantsNode extends NodeAbstract implements VirtualNode @@ -15,7 +16,7 @@ class ClassConstantsNode extends NodeAbstract implements VirtualNode * @param ClassConst[] $constants * @param ClassConstantFetch[] $fetches */ - public function __construct(private ClassLike $class, private array $constants, private array $fetches) + public function __construct(private ClassLike $class, private array $constants, private array $fetches, private ClassReflection $classReflection) { parent::__construct($class->getAttributes()); } @@ -54,4 +55,9 @@ public function getSubNodeNames(): array return []; } + public function getClassReflection(): ClassReflection + { + return $this->classReflection; + } + } diff --git a/src/Node/ClassMethodsNode.php b/src/Node/ClassMethodsNode.php index 0b5c616c34..e02620532b 100644 --- a/src/Node/ClassMethodsNode.php +++ b/src/Node/ClassMethodsNode.php @@ -5,6 +5,7 @@ use PhpParser\Node\Stmt\ClassLike; use PhpParser\NodeAbstract; use PHPStan\Node\Method\MethodCall; +use PHPStan\Reflection\ClassReflection; /** @api */ class ClassMethodsNode extends NodeAbstract implements VirtualNode @@ -14,7 +15,7 @@ class ClassMethodsNode extends NodeAbstract implements VirtualNode * @param ClassMethod[] $methods * @param array $methodCalls */ - public function __construct(private ClassLike $class, private array $methods, private array $methodCalls) + public function __construct(private ClassLike $class, private array $methods, private array $methodCalls, private ClassReflection $classReflection) { parent::__construct($class->getAttributes()); } @@ -53,4 +54,9 @@ public function getSubNodeNames(): array return []; } + public function getClassReflection(): ClassReflection + { + return $this->classReflection; + } + } diff --git a/src/Node/MethodReturnStatementsNode.php b/src/Node/MethodReturnStatementsNode.php index fc39507c05..fe7aa691fb 100644 --- a/src/Node/MethodReturnStatementsNode.php +++ b/src/Node/MethodReturnStatementsNode.php @@ -7,6 +7,8 @@ use PhpParser\Node\Stmt\ClassMethod; use PhpParser\NodeAbstract; use PHPStan\Analyser\StatementResult; +use PHPStan\Reflection\ClassReflection; +use PHPStan\Reflection\MethodReflection; use function count; /** @api */ @@ -26,6 +28,8 @@ public function __construct( private array $yieldStatements, private StatementResult $statementResult, private array $executionEnds, + private ClassReflection $classReflection, + private MethodReflection $methodReflection, ) { parent::__construct($method->getAttributes()); @@ -67,6 +71,16 @@ public function getYieldStatements(): array return $this->yieldStatements; } + public function getClassReflection(): ClassReflection + { + return $this->classReflection; + } + + public function getMethodReflection(): MethodReflection + { + return $this->methodReflection; + } + public function isGenerator(): bool { return count($this->yieldStatements) > 0; diff --git a/src/Rules/DeadCode/UnusedPrivateConstantRule.php b/src/Rules/DeadCode/UnusedPrivateConstantRule.php index e9c44a8fd8..b456b7d307 100644 --- a/src/Rules/DeadCode/UnusedPrivateConstantRule.php +++ b/src/Rules/DeadCode/UnusedPrivateConstantRule.php @@ -8,7 +8,6 @@ use PHPStan\Rules\Constants\AlwaysUsedClassConstantsExtensionProvider; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\ShouldNotHappenException; use function sprintf; /** @@ -31,11 +30,8 @@ public function processNode(Node $node, Scope $scope): array if (!$node->getClass() instanceof Node\Stmt\Class_ && !$node->getClass() instanceof Node\Stmt\Enum_) { return []; } - if (!$scope->isInClass()) { - throw new ShouldNotHappenException(); - } - $classReflection = $scope->getClassReflection(); + $classReflection = $node->getClassReflection(); $constants = []; foreach ($node->getConstants() as $constant) { diff --git a/src/Rules/DeadCode/UnusedPrivateMethodRule.php b/src/Rules/DeadCode/UnusedPrivateMethodRule.php index 1fff998256..4fde3bb26b 100644 --- a/src/Rules/DeadCode/UnusedPrivateMethodRule.php +++ b/src/Rules/DeadCode/UnusedPrivateMethodRule.php @@ -9,7 +9,6 @@ use PHPStan\Reflection\MethodReflection; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\ShouldNotHappenException; use PHPStan\Type\Constant\ConstantStringType; use function array_map; use function count; @@ -32,10 +31,7 @@ public function processNode(Node $node, Scope $scope): array if (!$node->getClass() instanceof Node\Stmt\Class_ && !$node->getClass() instanceof Node\Stmt\Enum_) { return []; } - if (!$scope->isInClass()) { - throw new ShouldNotHappenException(); - } - $classReflection = $scope->getClassReflection(); + $classReflection = $node->getClassReflection(); $constructor = null; if ($classReflection->hasConstructor()) { $constructor = $classReflection->getConstructor(); diff --git a/src/Rules/Exceptions/MissingCheckedExceptionInMethodThrowsRule.php b/src/Rules/Exceptions/MissingCheckedExceptionInMethodThrowsRule.php index 9dde83ee0c..e07e30d4ad 100644 --- a/src/Rules/Exceptions/MissingCheckedExceptionInMethodThrowsRule.php +++ b/src/Rules/Exceptions/MissingCheckedExceptionInMethodThrowsRule.php @@ -5,10 +5,8 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; use PHPStan\Node\MethodReturnStatementsNode; -use PHPStan\Reflection\MethodReflection; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\ShouldNotHappenException; use function sprintf; /** @@ -29,10 +27,7 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { $statementResult = $node->getStatementResult(); - $methodReflection = $scope->getFunction(); - if (!$methodReflection instanceof MethodReflection) { - throw new ShouldNotHappenException(); - } + $methodReflection = $node->getMethodReflection(); $errors = []; foreach ($this->check->check($methodReflection->getThrowType(), $statementResult->getThrowPoints()) as [$className, $throwPointNode]) { diff --git a/src/Rules/Exceptions/ThrowsVoidMethodWithExplicitThrowPointRule.php b/src/Rules/Exceptions/ThrowsVoidMethodWithExplicitThrowPointRule.php index 144385780f..70da4575dd 100644 --- a/src/Rules/Exceptions/ThrowsVoidMethodWithExplicitThrowPointRule.php +++ b/src/Rules/Exceptions/ThrowsVoidMethodWithExplicitThrowPointRule.php @@ -5,10 +5,8 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; use PHPStan\Node\MethodReturnStatementsNode; -use PHPStan\Reflection\MethodReflection; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\ShouldNotHappenException; use PHPStan\TrinaryLogic; use PHPStan\Type\TypeUtils; use PHPStan\Type\VerbosityLevel; @@ -35,10 +33,7 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { $statementResult = $node->getStatementResult(); - $methodReflection = $scope->getFunction(); - if (!$methodReflection instanceof MethodReflection) { - throw new ShouldNotHappenException(); - } + $methodReflection = $node->getMethodReflection(); if ($methodReflection->getThrowType() === null || !$methodReflection->getThrowType()->isVoid()->yes()) { return []; diff --git a/src/Rules/Exceptions/TooWideMethodThrowTypeRule.php b/src/Rules/Exceptions/TooWideMethodThrowTypeRule.php index e3c6599508..c9a5f231b6 100644 --- a/src/Rules/Exceptions/TooWideMethodThrowTypeRule.php +++ b/src/Rules/Exceptions/TooWideMethodThrowTypeRule.php @@ -5,10 +5,8 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; use PHPStan\Node\MethodReturnStatementsNode; -use PHPStan\Reflection\MethodReflection; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\ShouldNotHappenException; use PHPStan\Type\FileTypeMapper; use function sprintf; @@ -29,21 +27,14 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { - $statementResult = $node->getStatementResult(); - $methodReflection = $scope->getFunction(); - if (!$methodReflection instanceof MethodReflection) { - throw new ShouldNotHappenException(); - } - if (!$scope->isInClass()) { - throw new ShouldNotHappenException(); - } - $docComment = $node->getDocComment(); if ($docComment === null) { return []; } - $classReflection = $scope->getClassReflection(); + $statementResult = $node->getStatementResult(); + $methodReflection = $node->getMethodReflection(); + $classReflection = $node->getClassReflection(); $resolvedPhpDoc = $this->fileTypeMapper->getResolvedPhpDoc( $scope->getFile(), $classReflection->getName(), diff --git a/src/Rules/Playground/MethodNeverRule.php b/src/Rules/Playground/MethodNeverRule.php index 7bba0df997..443a31112f 100644 --- a/src/Rules/Playground/MethodNeverRule.php +++ b/src/Rules/Playground/MethodNeverRule.php @@ -5,11 +5,9 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; use PHPStan\Node\MethodReturnStatementsNode; -use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\ParametersAcceptorSelector; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\ShouldNotHappenException; use function count; use function sprintf; @@ -34,10 +32,7 @@ public function processNode(Node $node, Scope $scope): array return []; } - $method = $scope->getFunction(); - if (!$method instanceof MethodReflection) { - throw new ShouldNotHappenException(); - } + $method = $node->getMethodReflection(); $returnType = ParametersAcceptorSelector::selectSingle($method->getVariants())->getReturnType(); $helperResult = $this->helper->shouldReturnNever($node, $returnType); diff --git a/src/Rules/TooWideTypehints/TooWideMethodReturnTypehintRule.php b/src/Rules/TooWideTypehints/TooWideMethodReturnTypehintRule.php index 0d97170dd3..933979eaad 100644 --- a/src/Rules/TooWideTypehints/TooWideMethodReturnTypehintRule.php +++ b/src/Rules/TooWideTypehints/TooWideMethodReturnTypehintRule.php @@ -5,11 +5,9 @@ use PhpParser\Node; use PHPStan\Analyser\Scope; use PHPStan\Node\MethodReturnStatementsNode; -use PHPStan\Reflection\MethodReflection; use PHPStan\Reflection\ParametersAcceptorSelector; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\ShouldNotHappenException; use PHPStan\Type\Constant\ConstantBooleanType; use PHPStan\Type\TypeCombinator; use PHPStan\Type\UnionType; @@ -34,10 +32,7 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { - $method = $scope->getFunction(); - if (!$method instanceof MethodReflection) { - throw new ShouldNotHappenException(); - } + $method = $node->getMethodReflection(); $isFirstDeclaration = $method->getPrototype()->getDeclaringClass() === $method->getDeclaringClass(); if (!$method->isPrivate()) { if (!$this->checkProtectedAndPublicMethods) {