diff --git a/src/Analyser/NodeScopeResolver.php b/src/Analyser/NodeScopeResolver.php index 3b1d68d9b7..de33455730 100644 --- a/src/Analyser/NodeScopeResolver.php +++ b/src/Analyser/NodeScopeResolver.php @@ -557,6 +557,7 @@ private function processStmtNode( $scope->isInTrait(), $scope->getClassReflection()->isReadOnly(), false, + $scope->getClassReflection(), ), $methodScope); $methodScope = $methodScope->assignExpression(new PropertyInitializationExpr($param->var->name), new MixedType(), new MixedType()); } @@ -743,6 +744,7 @@ private function processStmtNode( $scope->isInTrait(), $scope->getClassReflection()->isReadOnly(), $isAllowedPrivateMutation, + $scope->getClassReflection(), ), $scope, ); diff --git a/src/Dependency/DependencyResolver.php b/src/Dependency/DependencyResolver.php index e7a07dc1f1..36f615c600 100644 --- a/src/Dependency/DependencyResolver.php +++ b/src/Dependency/DependencyResolver.php @@ -106,8 +106,8 @@ public function resolveDependencies(Node $node, Scope $scope): NodeDependencies } } elseif ($node instanceof ClassPropertyNode) { $nativeTypeNode = $node->getNativeType(); - if ($nativeTypeNode !== null && $scope->isInClass()) { - $nativeType = ParserNodeTypeToPHPStanType::resolve($nativeTypeNode, $scope->getClassReflection()); + if ($nativeTypeNode !== null) { + $nativeType = ParserNodeTypeToPHPStanType::resolve($nativeTypeNode, $node->getClassReflection()); foreach ($nativeType->getReferencedClasses() as $referencedClass) { $this->addClassToDependencies($referencedClass, $dependenciesReflections); } diff --git a/src/Node/ClassPropertyNode.php b/src/Node/ClassPropertyNode.php index 3b40086193..a7c81ff9d4 100644 --- a/src/Node/ClassPropertyNode.php +++ b/src/Node/ClassPropertyNode.php @@ -8,6 +8,7 @@ use PhpParser\Node\Name; use PhpParser\Node\Stmt\Class_; use PhpParser\NodeAbstract; +use PHPStan\Reflection\ClassReflection; use PHPStan\Type\Type; /** @api */ @@ -28,6 +29,7 @@ public function __construct( private bool $isDeclaredInTrait, private bool $isReadonlyClass, private bool $isAllowedPrivateMutation, + private ClassReflection $classReflection, ) { parent::__construct($originalNode->getAttributes()); @@ -117,6 +119,11 @@ public function getNativeType() return $this->type; } + public function getClassReflection(): ClassReflection + { + return $this->classReflection; + } + public function getType(): string { return 'PHPStan_Node_ClassPropertyNode'; diff --git a/src/Rules/Generics/PropertyVarianceRule.php b/src/Rules/Generics/PropertyVarianceRule.php index 5958436319..b62c494ba5 100644 --- a/src/Rules/Generics/PropertyVarianceRule.php +++ b/src/Rules/Generics/PropertyVarianceRule.php @@ -6,7 +6,6 @@ use PHPStan\Analyser\Scope; use PHPStan\Internal\SprintfHelper; use PHPStan\Node\ClassPropertyNode; -use PHPStan\Reflection\ClassReflection; use PHPStan\Rules\Rule; use PHPStan\Type\Generic\TemplateTypeVariance; use function sprintf; @@ -31,10 +30,7 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { - $classReflection = $scope->getClassReflection(); - if (!$classReflection instanceof ClassReflection) { - return []; - } + $classReflection = $node->getClassReflection(); if (!$classReflection->hasNativeProperty($node->getName())) { return []; diff --git a/src/Rules/PhpDoc/IncompatiblePropertyPhpDocTypeRule.php b/src/Rules/PhpDoc/IncompatiblePropertyPhpDocTypeRule.php index 0537392be2..10fe3f704d 100644 --- a/src/Rules/PhpDoc/IncompatiblePropertyPhpDocTypeRule.php +++ b/src/Rules/PhpDoc/IncompatiblePropertyPhpDocTypeRule.php @@ -9,7 +9,6 @@ use PHPStan\Rules\Generics\GenericObjectTypeCheck; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\ShouldNotHappenException; use PHPStan\Type\Generic\TemplateType; use PHPStan\Type\ParserNodeTypeToPHPStanType; use PHPStan\Type\VerbosityLevel; @@ -36,21 +35,20 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { - if (!$scope->isInClass()) { - throw new ShouldNotHappenException(); - } - - $propertyName = $node->getName(); $phpDocType = $node->getPhpDocType(); if ($phpDocType === null) { return []; } + $propertyName = $node->getName(); + $description = 'PHPDoc tag @var'; if ($node->isPromoted()) { $description = 'PHPDoc type'; } + $classReflection = $node->getClassReflection(); + $messages = []; if ( $this->unresolvableTypeHelper->containsUnresolvableType($phpDocType) @@ -58,18 +56,18 @@ public function processNode(Node $node, Scope $scope): array $messages[] = RuleErrorBuilder::message(sprintf( '%s for property %s::$%s contains unresolvable type.', $description, - $scope->getClassReflection()->getDisplayName(), + $classReflection->getDisplayName(), $propertyName, ))->build(); } - $nativeType = ParserNodeTypeToPHPStanType::resolve($node->getNativeType(), $scope->getClassReflection()); + $nativeType = ParserNodeTypeToPHPStanType::resolve($node->getNativeType(), $classReflection); $isSuperType = $nativeType->isSuperTypeOf($phpDocType); if ($isSuperType->no()) { $messages[] = RuleErrorBuilder::message(sprintf( '%s for property %s::$%s with type %s is incompatible with native type %s.', $description, - $scope->getClassReflection()->getDisplayName(), + $classReflection->getDisplayName(), $propertyName, $phpDocType->describe(VerbosityLevel::typeOnly()), $nativeType->describe(VerbosityLevel::typeOnly()), @@ -79,7 +77,7 @@ public function processNode(Node $node, Scope $scope): array $errorBuilder = RuleErrorBuilder::message(sprintf( '%s for property %s::$%s with type %s is not subtype of native type %s.', $description, - $scope->getClassReflection()->getDisplayName(), + $classReflection->getDisplayName(), $propertyName, $phpDocType->describe(VerbosityLevel::typeOnly()), $nativeType->describe(VerbosityLevel::typeOnly()), @@ -92,7 +90,7 @@ public function processNode(Node $node, Scope $scope): array $messages[] = $errorBuilder->build(); } - $className = SprintfHelper::escapeFormatString($scope->getClassReflection()->getDisplayName()); + $className = SprintfHelper::escapeFormatString($classReflection->getDisplayName()); $escapedPropertyName = SprintfHelper::escapeFormatString($propertyName); $messages = array_merge($messages, $this->genericObjectTypeCheck->check( diff --git a/src/Rules/Properties/DefaultValueTypesAssignedToPropertiesRule.php b/src/Rules/Properties/DefaultValueTypesAssignedToPropertiesRule.php index 697477c2ee..8ec66cb948 100644 --- a/src/Rules/Properties/DefaultValueTypesAssignedToPropertiesRule.php +++ b/src/Rules/Properties/DefaultValueTypesAssignedToPropertiesRule.php @@ -8,7 +8,6 @@ use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Rules\RuleLevelHelper; -use PHPStan\ShouldNotHappenException; use PHPStan\Type\MixedType; use PHPStan\Type\VerbosityLevel; use function sprintf; @@ -30,16 +29,13 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { - if (!$scope->isInClass()) { - throw new ShouldNotHappenException(); - } - - $classReflection = $scope->getClassReflection(); $default = $node->getDefault(); if ($default === null) { return []; } + $classReflection = $node->getClassReflection(); + $propertyReflection = $classReflection->getNativeProperty($node->getName()); $propertyType = $propertyReflection->getWritableType(); if ($propertyReflection->getNativeType() instanceof MixedType) { diff --git a/src/Rules/Properties/ExistingClassesInPropertiesRule.php b/src/Rules/Properties/ExistingClassesInPropertiesRule.php index 1f4780b33b..2f8d69599d 100644 --- a/src/Rules/Properties/ExistingClassesInPropertiesRule.php +++ b/src/Rules/Properties/ExistingClassesInPropertiesRule.php @@ -12,7 +12,6 @@ use PHPStan\Rules\PhpDoc\UnresolvableTypeHelper; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\ShouldNotHappenException; use function array_map; use function array_merge; use function sprintf; @@ -41,11 +40,7 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { - if (!$scope->isInClass()) { - throw new ShouldNotHappenException(); - } - - $propertyReflection = $scope->getClassReflection()->getNativeProperty($node->getName()); + $propertyReflection = $node->getClassReflection()->getNativeProperty($node->getName()); if ($this->checkThisOnly) { $referencedClasses = $propertyReflection->getNativeType()->getReferencedClasses(); } else { diff --git a/src/Rules/Properties/MissingPropertyTypehintRule.php b/src/Rules/Properties/MissingPropertyTypehintRule.php index 367809b83f..b77fa6d94c 100644 --- a/src/Rules/Properties/MissingPropertyTypehintRule.php +++ b/src/Rules/Properties/MissingPropertyTypehintRule.php @@ -8,7 +8,6 @@ use PHPStan\Rules\MissingTypehintCheck; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\ShouldNotHappenException; use PHPStan\Type\MixedType; use PHPStan\Type\VerbosityLevel; use function implode; @@ -31,11 +30,7 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { - if (!$scope->isInClass()) { - throw new ShouldNotHappenException(); - } - - $propertyReflection = $scope->getClassReflection()->getNativeProperty($node->getName()); + $propertyReflection = $node->getClassReflection()->getNativeProperty($node->getName()); if ($propertyReflection->isPromoted()) { return []; diff --git a/src/Rules/Properties/OverridingPropertyRule.php b/src/Rules/Properties/OverridingPropertyRule.php index e8749b62f0..d4677ca63e 100644 --- a/src/Rules/Properties/OverridingPropertyRule.php +++ b/src/Rules/Properties/OverridingPropertyRule.php @@ -9,7 +9,6 @@ use PHPStan\Reflection\Php\PhpPropertyReflection; use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; -use PHPStan\ShouldNotHappenException; use PHPStan\Type\ParserNodeTypeToPHPStanType; use PHPStan\Type\VerbosityLevel; use function array_merge; @@ -36,11 +35,7 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { - if (!$scope->isInClass()) { - throw new ShouldNotHappenException(); - } - - $classReflection = $scope->getClassReflection(); + $classReflection = $node->getClassReflection(); $prototype = $this->findPrototype($classReflection, $node->getName()); if ($prototype === null) { return []; @@ -121,7 +116,7 @@ public function processNode(Node $node, Scope $scope): array $prototype->getNativeType()->describe(VerbosityLevel::typeOnly()), ))->nonIgnorable()->build(); } else { - $nativeType = ParserNodeTypeToPHPStanType::resolve($node->getNativeType(), $scope->getClassReflection()); + $nativeType = ParserNodeTypeToPHPStanType::resolve($node->getNativeType(), $classReflection); if (!$prototype->getNativeType()->equals($nativeType)) { $typeErrors[] = RuleErrorBuilder::message(sprintf( 'Type %s of property %s::$%s is not the same as type %s of overridden property %s::$%s.', @@ -139,7 +134,7 @@ public function processNode(Node $node, Scope $scope): array 'Property %s::$%s (%s) overriding property %s::$%s should not have a native type.', $classReflection->getDisplayName(), $node->getName(), - ParserNodeTypeToPHPStanType::resolve($node->getNativeType(), $scope->getClassReflection())->describe(VerbosityLevel::typeOnly()), + ParserNodeTypeToPHPStanType::resolve($node->getNativeType(), $classReflection)->describe(VerbosityLevel::typeOnly()), $prototype->getDeclaringClass()->getDisplayName(), $node->getName(), ))->nonIgnorable()->build();