Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement isOffsetAccessLegal #3045

Merged
merged 12 commits into from
May 7, 2024
2 changes: 1 addition & 1 deletion src/Rules/Arrays/NonexistentOffsetInArrayDimFetchRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public function processNode(Node $node, Scope $scope): array
return [];
}

if ($scope->isUndefinedExpressionAllowed($node) && !$isOffsetAccessible->no()) {
if ($scope->isUndefinedExpressionAllowed($node) && $isOffsetAccessibleType->isOffsetAccessLegal()->yes()) {
Copy link
Contributor Author

@rajyan rajyan May 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it's better to add a tip for !$isOffsetAccessibleType->isOffsetAccessLegal()->yes() case.

  • The isOffsetAccessibleType should be narrowed down to a type excluding ObjectType that do not implement ArrayAccess::class
  • The class implementing ArrayAccess::Class should be marked final

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The class implementing ArrayAccess::Class should be marked final

I don't get this part. It doesn't matter if a class is final when it already implements ArrayAccess. What a finality of such class would achieve?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was just a mistake. I was mixed up with the fact that we cant say isOffsetAccessLegal()->no() if the class is not final, because child class might implement ArrayClass.

phpstan/phpstan#10926 (comment)

return [];
}

Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/AccessoryArrayListType.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,11 @@ public function isOffsetAccessible(): TrinaryLogic
return TrinaryLogic::createYes();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createYes();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
return $this->getIterableKeyType()->isSuperTypeOf($offsetType)->and(TrinaryLogic::createMaybe());
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/AccessoryLiteralStringType.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,11 @@ public function isOffsetAccessible(): TrinaryLogic
return TrinaryLogic::createYes();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createYes();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
return $offsetType->isInteger()->and(TrinaryLogic::createMaybe());
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/AccessoryNonEmptyStringType.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,11 @@ public function isOffsetAccessible(): TrinaryLogic
return TrinaryLogic::createYes();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createYes();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
return $offsetType->isInteger()->and(TrinaryLogic::createMaybe());
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/AccessoryNonFalsyStringType.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,11 @@ public function isOffsetAccessible(): TrinaryLogic
return TrinaryLogic::createYes();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createYes();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
return $offsetType->isInteger()->and(TrinaryLogic::createMaybe());
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/AccessoryNumericStringType.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,11 @@ public function isOffsetAccessible(): TrinaryLogic
return TrinaryLogic::createYes();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createYes();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
return $offsetType->isInteger()->and(TrinaryLogic::createMaybe());
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/HasMethodType.php
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ public function describe(VerbosityLevel $level): string
return sprintf('hasMethod(%s)', $this->methodName);
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function hasMethod(string $methodName): TrinaryLogic
{
if ($this->getCanonicalMethodName() === strtolower($methodName)) {
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/HasOffsetType.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ public function isOffsetAccessible(): TrinaryLogic
return TrinaryLogic::createYes();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createYes();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
if ($offsetType->isConstantScalarValue()->yes() && $offsetType->equals($this->offsetType)) {
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/HasOffsetValueType.php
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,11 @@ public function isOffsetAccessible(): TrinaryLogic
return TrinaryLogic::createYes();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createYes();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
if ($offsetType->isConstantScalarValue()->yes() && $offsetType->equals($this->offsetType)) {
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/HasPropertyType.php
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ public function describe(VerbosityLevel $level): string
return sprintf('hasProperty(%s)', $this->propertyName);
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function hasProperty(string $propertyName): TrinaryLogic
{
if ($this->propertyName === $propertyName) {
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/NonEmptyArrayType.php
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,11 @@ public function isOffsetAccessible(): TrinaryLogic
return TrinaryLogic::createYes();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createYes();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
return TrinaryLogic::createMaybe();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Accessory/OversizedArrayType.php
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ public function isOffsetAccessible(): TrinaryLogic
return TrinaryLogic::createYes();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createYes();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
return TrinaryLogic::createMaybe();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/ArrayType.php
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,11 @@ public function isOffsetAccessible(): TrinaryLogic
return TrinaryLogic::createYes();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createYes();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
$offsetType = $offsetType->toArrayKey();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/BooleanType.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ public function toArrayKey(): Type
return new UnionType([new ConstantIntegerType(0), new ConstantIntegerType(1)]);
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createYes();
}

public function isNull(): TrinaryLogic
{
return TrinaryLogic::createNo();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/CallableType.php
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,11 @@ public function toArrayKey(): Type
return new ErrorType();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function getTemplateTypeMap(): TemplateTypeMap
{
return $this->templateTypeMap;
Expand Down
5 changes: 5 additions & 0 deletions src/Type/ClosureType.php
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,11 @@ function (): string {
);
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function isObject(): TrinaryLogic
{
return $this->objectType->isObject();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/FloatType.php
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ public function toArrayKey(): Type
return new IntegerType();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createYes();
}

public function isNull(): TrinaryLogic
{
return TrinaryLogic::createNo();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/IntegerType.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ public function toArrayKey(): Type
return $this;
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createYes();
}

public function isNull(): TrinaryLogic
{
return TrinaryLogic::createNo();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/IntersectionType.php
Original file line number Diff line number Diff line change
Expand Up @@ -672,6 +672,11 @@ public function isOffsetAccessible(): TrinaryLogic
return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->isOffsetAccessible());
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return $this->intersectResults(static fn (Type $type): TrinaryLogic => $type->isOffsetAccessLegal());
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
if ($this->isList()->yes() && $this->isIterableAtLeastOnce()->yes()) {
Expand Down
5 changes: 5 additions & 0 deletions src/Type/IterableType.php
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,11 @@ public function toArrayKey(): Type
return new ErrorType();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function isIterable(): TrinaryLogic
{
return TrinaryLogic::createYes();
Expand Down
10 changes: 10 additions & 0 deletions src/Type/MixedType.php
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,16 @@ public function isOffsetAccessible(): TrinaryLogic
return TrinaryLogic::createMaybe();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
if ($this->subtractedType !== null) {
if ($this->subtractedType->isSuperTypeOf(new ObjectWithoutClassType())->yes()) {
return TrinaryLogic::createYes();
}
}
return TrinaryLogic::createMaybe();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
if ($this->isOffsetAccessible()->no()) {
Expand Down
5 changes: 5 additions & 0 deletions src/Type/NeverType.php
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,11 @@ public function isOffsetAccessible(): TrinaryLogic
return TrinaryLogic::createYes();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createYes();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
return TrinaryLogic::createYes();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/NonexistentParentClassType.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,11 @@ public function toArrayKey(): Type
return new ErrorType();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function isScalar(): TrinaryLogic
{
return TrinaryLogic::createNo();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/NullType.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,11 @@ public function isOffsetAccessible(): TrinaryLogic
return TrinaryLogic::createYes();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createYes();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
return TrinaryLogic::createNo();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/ObjectShapeType.php
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,11 @@ public function describe(VerbosityLevel $level): string
);
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function getEnumCases(): array
{
return [];
Expand Down
5 changes: 5 additions & 0 deletions src/Type/ObjectType.php
Original file line number Diff line number Diff line change
Expand Up @@ -1099,6 +1099,11 @@ public function isOffsetAccessible(): TrinaryLogic
);
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return $this->isOffsetAccessible();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
if ($this->isInstanceOf(ArrayAccess::class)->yes()) {
Expand Down
5 changes: 5 additions & 0 deletions src/Type/ObjectWithoutClassType.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@ function () use ($level): string {
);
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createMaybe();
}

public function getEnumCases(): array
{
return [];
Expand Down
5 changes: 5 additions & 0 deletions src/Type/ResourceType.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ public function toArrayKey(): Type
return new ErrorType();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createYes();
}

public function isScalar(): TrinaryLogic
{
return TrinaryLogic::createNo();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/StaticType.php
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,11 @@ public function isOffsetAccessible(): TrinaryLogic
return $this->getStaticObjectType()->isOffsetAccessible();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return $this->getStaticObjectType()->isOffsetAccessLegal();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
return $this->getStaticObjectType()->hasOffsetValueType($offsetType);
Expand Down
5 changes: 5 additions & 0 deletions src/Type/StrictMixedType.php
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,11 @@ public function isOffsetAccessible(): TrinaryLogic
return TrinaryLogic::createNo();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
return TrinaryLogic::createNo();
Expand Down
5 changes: 5 additions & 0 deletions src/Type/StringType.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ public function isOffsetAccessible(): TrinaryLogic
return TrinaryLogic::createYes();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return TrinaryLogic::createYes();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
return $offsetType->isInteger()->and(TrinaryLogic::createMaybe());
Expand Down
5 changes: 5 additions & 0 deletions src/Type/Traits/LateResolvableTypeTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,11 @@ public function isOffsetAccessible(): TrinaryLogic
return $this->resolve()->isOffsetAccessible();
}

public function isOffsetAccessLegal(): TrinaryLogic
{
return $this->resolve()->isOffsetAccessLegal();
}

public function hasOffsetValueType(Type $offsetType): TrinaryLogic
{
return $this->resolve()->hasOffsetValueType($offsetType);
Expand Down
2 changes: 2 additions & 0 deletions src/Type/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ public function isList(): TrinaryLogic;

public function isOffsetAccessible(): TrinaryLogic;

public function isOffsetAccessLegal(): TrinaryLogic;

public function hasOffsetValueType(Type $offsetType): TrinaryLogic;

public function getOffsetValueType(Type $offsetType): Type;
Expand Down