Skip to content

Commit

Permalink
[BCB] ClassPropertyNode::getNativeType() return type changed from A…
Browse files Browse the repository at this point in the history
…ST node to Type
  • Loading branch information
ondrejmirtes committed Oct 1, 2024
1 parent 5eacc66 commit 9e7f39e
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 48 deletions.
1 change: 1 addition & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -299,3 +299,4 @@ Instead of `PHPStanTestCase::createBroker()`, call `PHPStanTestCase::createRefle
* Added more methods around PHPDoc types and native types to the (new) `ClassConstantReflection`
* Interface `GlobalConstantReflection` renamed to `ConstantReflection`
* Renamed interfaces and classes from `*WithPhpDocs` to `Extended*`
* `ClassPropertyNode::getNativeType()` return type changed from AST node to `Type|null
7 changes: 4 additions & 3 deletions src/Analyser/NodeScopeResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@
use PHPStan\Type\NullType;
use PHPStan\Type\ObjectType;
use PHPStan\Type\ObjectWithoutClassType;
use PHPStan\Type\ParserNodeTypeToPHPStanType;
use PHPStan\Type\ResourceType;
use PHPStan\Type\StaticType;
use PHPStan\Type\StaticTypeFactory;
Expand Down Expand Up @@ -648,7 +649,7 @@ private function processStmtNode(
$nodeCallback(new ClassPropertyNode(
$param->var->name,
$param->flags,
$param->type,
$param->type !== null ? ParserNodeTypeToPHPStanType::resolve($param->type, $scope->getClassReflection()) : null,
null,
$phpDoc,
$phpDocParameterTypes[$param->var->name] ?? null,
Expand Down Expand Up @@ -899,13 +900,13 @@ private function processStmtNode(
new ClassPropertyNode(
$propertyName,
$stmt->flags,
$stmt->type,
$stmt->type !== null ? ParserNodeTypeToPHPStanType::resolve($stmt->type, $scope->getClassReflection()) : null,
$prop->default,
$docComment,
$phpDocType,
false,
false,
$prop,
$stmt,
$isReadOnly,
$scope->isInTrait(),
$scope->getClassReflection()->isReadOnly(),
Expand Down
6 changes: 2 additions & 4 deletions src/Dependency/DependencyResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Type\ClosureType;
use PHPStan\Type\FileTypeMapper;
use PHPStan\Type\ParserNodeTypeToPHPStanType;
use PHPStan\Type\Type;
use function array_merge;
use function count;
Expand Down Expand Up @@ -85,9 +84,8 @@ public function resolveDependencies(Node $node, Scope $scope): NodeDependencies
}
}
} elseif ($node instanceof ClassPropertyNode) {
$nativeTypeNode = $node->getNativeType();
if ($nativeTypeNode !== null) {
$nativeType = ParserNodeTypeToPHPStanType::resolve($nativeTypeNode, $node->getClassReflection());
$nativeType = $node->getNativeType();
if ($nativeType !== null) {
foreach ($nativeType->getReferencedClasses() as $referencedClass) {
$this->addClassToDependencies($referencedClass, $dependenciesReflections);
}
Expand Down
17 changes: 10 additions & 7 deletions src/Node/ClassPropertyNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
use PhpParser\Modifiers;
use PhpParser\Node;
use PhpParser\Node\Expr;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\NodeAbstract;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Type\Type;
Expand All @@ -20,13 +18,13 @@ final class ClassPropertyNode extends NodeAbstract implements VirtualNode
public function __construct(
private string $name,
private int $flags,
private Identifier|Name|Node\ComplexType|null $type,
private ?Type $type,
private ?Expr $default,
private ?string $phpDoc,
private ?Type $phpDocType,
private bool $isPromoted,
private bool $isPromotedFromTrait,
Node $originalNode,
private Node\Stmt\Property|Node\Param $originalNode,
private bool $isReadonlyByPhpDoc,
private bool $isDeclaredInTrait,
private bool $isReadonlyClass,
Expand Down Expand Up @@ -113,12 +111,17 @@ public function isAllowedPrivateMutation(): bool
return $this->isAllowedPrivateMutation;
}

public function getNativeType(): ?Type
{
return $this->type;
}

/**
* @return Identifier|Name|Node\ComplexType|null
* @return Node\Identifier|Node\Name|Node\ComplexType|null
*/
public function getNativeType()
public function getNativeTypeNode()
{
return $this->type;
return $this->originalNode->type;
}

public function getClassReflection(): ClassReflection
Expand Down
55 changes: 28 additions & 27 deletions src/Rules/PhpDoc/IncompatiblePropertyPhpDocTypeRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\Type\Generic\TemplateType;
use PHPStan\Type\ParserNodeTypeToPHPStanType;
use PHPStan\Type\VerbosityLevel;
use function array_merge;
use function sprintf;
Expand Down Expand Up @@ -62,33 +61,35 @@ public function processNode(Node $node, Scope $scope): array
))->identifier('property.unresolvableType')->build();
}

$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,
$classReflection->getDisplayName(),
$propertyName,
$phpDocType->describe(VerbosityLevel::typeOnly()),
$nativeType->describe(VerbosityLevel::typeOnly()),
))->identifier('property.phpDocType')->build();

} elseif ($isSuperType->maybe()) {
$errorBuilder = RuleErrorBuilder::message(sprintf(
'%s for property %s::$%s with type %s is not subtype of native type %s.',
$description,
$classReflection->getDisplayName(),
$propertyName,
$phpDocType->describe(VerbosityLevel::typeOnly()),
$nativeType->describe(VerbosityLevel::typeOnly()),
))->identifier('property.phpDocType');

if ($phpDocType instanceof TemplateType) {
$errorBuilder->tip(sprintf('Write @template %s of %s to fix this.', $phpDocType->getName(), $nativeType->describe(VerbosityLevel::typeOnly())));
$nativeType = $node->getNativeType();
if ($nativeType !== null) {
$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,
$classReflection->getDisplayName(),
$propertyName,
$phpDocType->describe(VerbosityLevel::typeOnly()),
$nativeType->describe(VerbosityLevel::typeOnly()),
))->identifier('property.phpDocType')->build();

} elseif ($isSuperType->maybe()) {
$errorBuilder = RuleErrorBuilder::message(sprintf(
'%s for property %s::$%s with type %s is not subtype of native type %s.',
$description,
$classReflection->getDisplayName(),
$propertyName,
$phpDocType->describe(VerbosityLevel::typeOnly()),
$nativeType->describe(VerbosityLevel::typeOnly()),
))->identifier('property.phpDocType');

if ($phpDocType instanceof TemplateType) {
$errorBuilder->tip(sprintf('Write @template %s of %s to fix this.', $phpDocType->getName(), $nativeType->describe(VerbosityLevel::typeOnly())));
}

$messages[] = $errorBuilder->build();
}

$messages[] = $errorBuilder->build();
}

$className = SprintfHelper::escapeFormatString($classReflection->getDisplayName());
Expand Down
9 changes: 4 additions & 5 deletions src/Rules/Properties/OverridingPropertyRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
use PHPStan\Reflection\Php\PhpPropertyReflection;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\Type\ParserNodeTypeToPHPStanType;
use PHPStan\Type\VerbosityLevel;
use function array_merge;
use function count;
Expand Down Expand Up @@ -104,8 +103,9 @@ public function processNode(Node $node, Scope $scope): array
}

$typeErrors = [];
$nativeType = $node->getNativeType();
if ($prototype->hasNativeType()) {
if ($node->getNativeType() === null) {
if ($nativeType === null) {
$typeErrors[] = RuleErrorBuilder::message(sprintf(
'Property %s::$%s overriding property %s::$%s (%s) should also have native type %s.',
$classReflection->getDisplayName(),
Expand All @@ -116,7 +116,6 @@ public function processNode(Node $node, Scope $scope): array
$prototype->getNativeType()->describe(VerbosityLevel::typeOnly()),
))->identifier('property.missingNativeType')->nonIgnorable()->build();
} else {
$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.',
Expand All @@ -129,12 +128,12 @@ public function processNode(Node $node, Scope $scope): array
))->identifier('property.nativeType')->nonIgnorable()->build();
}
}
} elseif ($node->getNativeType() !== null) {
} elseif ($nativeType !== null) {
$typeErrors[] = RuleErrorBuilder::message(sprintf(
'Property %s::$%s (%s) overriding property %s::$%s should not have a native type.',
$classReflection->getDisplayName(),
$node->getName(),
ParserNodeTypeToPHPStanType::resolve($node->getNativeType(), $classReflection)->describe(VerbosityLevel::typeOnly()),
$nativeType->describe(VerbosityLevel::typeOnly()),
$prototype->getDeclaringClass()->getDisplayName(),
$node->getName(),
))->identifier('property.extraNativeType')->nonIgnorable()->build();
Expand Down
4 changes: 2 additions & 2 deletions src/Rules/Types/InvalidTypesInUnionRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ private function processFunctionLikeNode(Node\FunctionLike $functionLike): array
*/
private function processClassPropertyNode(ClassPropertyNode $classPropertyNode): array
{
if (!$classPropertyNode->getNativeType() instanceof Node\ComplexType) {
if (!$classPropertyNode->getNativeTypeNode() instanceof Node\ComplexType) {
return [];
}

return $this->processComplexType($classPropertyNode->getNativeType());
return $this->processComplexType($classPropertyNode->getNativeTypeNode());
}

/**
Expand Down

0 comments on commit 9e7f39e

Please sign in to comment.