Skip to content

Add PhpVersion param on isSmallerThanOrEqual and isGreaterThanOrEqual #3478

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

Merged
merged 7 commits into from
Sep 25, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
@@ -178,3 +178,5 @@ As a replacement you can implement [`PHPStan\Type\ExpressionTypeResolverExtensio
* Parameter `$callableParameters` of [`MutatingScope::enterAnonymousFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterAnonymousFunction) and [`enterArrowFunction()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.MutatingScope.html#_enterArrowFunction) made required
* Parameter `StatementContext $context` of [`NodeScopeResolver::processStmtNodes()`](https://apiref.phpstan.org/2.0.x/PHPStan.Analyser.NodeScopeResolver.html#_processStmtNodes) made required
* ClassPropertiesNode - remove `$extensions` parameter from [`getUninitializedProperties()`](https://apiref.phpstan.org/2.0.x/PHPStan.Node.ClassPropertiesNode.html#_getUninitializedProperties)
* `Type::getSmallerType()`, `Type::getSmallerOrEqualType()`, `Type::getGreaterType()`, `Type::getGreaterOrEqualType()`, `Type::isSmallerThan()`, `Type::isSmallerThanOrEqual()` now require [`PhpVersion`](https://apiref.phpstan.org/2.0.x/PHPStan.Php.PhpVersion.html) as argument.
* `CompoundType::isGreaterThan()`, `CompoundType::isGreaterThanOrEqual()` now require [`PhpVersion`](https://apiref.phpstan.org/2.0.x/PHPStan.Php.PhpVersion.html) as argument.
8 changes: 4 additions & 4 deletions src/Analyser/MutatingScope.php
Original file line number Diff line number Diff line change
@@ -747,19 +747,19 @@ private function resolveType(string $exprString, Expr $node): Type
}

if ($node instanceof Expr\BinaryOp\Smaller) {
return $this->getType($node->left)->isSmallerThan($this->getType($node->right))->toBooleanType();
return $this->getType($node->left)->isSmallerThan($this->getType($node->right), $this->phpVersion)->toBooleanType();
}

if ($node instanceof Expr\BinaryOp\SmallerOrEqual) {
return $this->getType($node->left)->isSmallerThanOrEqual($this->getType($node->right))->toBooleanType();
return $this->getType($node->left)->isSmallerThanOrEqual($this->getType($node->right), $this->phpVersion)->toBooleanType();
}

if ($node instanceof Expr\BinaryOp\Greater) {
return $this->getType($node->right)->isSmallerThan($this->getType($node->left))->toBooleanType();
return $this->getType($node->right)->isSmallerThan($this->getType($node->left), $this->phpVersion)->toBooleanType();
}

if ($node instanceof Expr\BinaryOp\GreaterOrEqual) {
return $this->getType($node->right)->isSmallerThanOrEqual($this->getType($node->left))->toBooleanType();
return $this->getType($node->right)->isSmallerThanOrEqual($this->getType($node->left), $this->phpVersion)->toBooleanType();
}

if ($node instanceof Expr\BinaryOp\Equal) {
10 changes: 6 additions & 4 deletions src/Analyser/TypeSpecifier.php
Original file line number Diff line number Diff line change
@@ -22,6 +22,7 @@
use PHPStan\Node\Expr\AlwaysRememberedExpr;
use PHPStan\Node\IssetExpr;
use PHPStan\Node\Printer\ExprPrinter;
use PHPStan\Php\PhpVersion;
use PHPStan\Reflection\Assertions;
use PHPStan\Reflection\ParametersAcceptor;
use PHPStan\Reflection\ParametersAcceptorSelector;
@@ -100,6 +101,7 @@ final class TypeSpecifier
public function __construct(
private ExprPrinter $exprPrinter,
private ReflectionProvider $reflectionProvider,
private PhpVersion $phpVersion,
private array $functionTypeSpecifyingExtensions,
private array $methodTypeSpecifyingExtensions,
private array $staticMethodTypeSpecifyingExtensions,
@@ -406,7 +408,7 @@ public function specifyTypesInCondition(
$result = $result->unionWith(
$this->create(
$expr->left,
$orEqual ? $rightType->getSmallerOrEqualType() : $rightType->getSmallerType(),
$orEqual ? $rightType->getSmallerOrEqualType($this->phpVersion) : $rightType->getSmallerType($this->phpVersion),
TypeSpecifierContext::createTruthy(),
$scope,
)->setRootExpr($expr),
@@ -416,7 +418,7 @@ public function specifyTypesInCondition(
$result = $result->unionWith(
$this->create(
$expr->right,
$orEqual ? $leftType->getGreaterOrEqualType() : $leftType->getGreaterType(),
$orEqual ? $leftType->getGreaterOrEqualType($this->phpVersion) : $leftType->getGreaterType($this->phpVersion),
TypeSpecifierContext::createTruthy(),
$scope,
)->setRootExpr($expr),
@@ -427,7 +429,7 @@ public function specifyTypesInCondition(
$result = $result->unionWith(
$this->create(
$expr->left,
$orEqual ? $rightType->getGreaterType() : $rightType->getGreaterOrEqualType(),
$orEqual ? $rightType->getGreaterType($this->phpVersion) : $rightType->getGreaterOrEqualType($this->phpVersion),
TypeSpecifierContext::createTruthy(),
$scope,
)->setRootExpr($expr),
@@ -437,7 +439,7 @@ public function specifyTypesInCondition(
$result = $result->unionWith(
$this->create(
$expr->right,
$orEqual ? $leftType->getSmallerType() : $leftType->getSmallerOrEqualType(),
$orEqual ? $leftType->getSmallerType($this->phpVersion) : $leftType->getSmallerOrEqualType($this->phpVersion),
TypeSpecifierContext::createTruthy(),
$scope,
)->setRootExpr($expr),
2 changes: 2 additions & 0 deletions src/Analyser/TypeSpecifierFactory.php
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
use PHPStan\Broker\BrokerFactory;
use PHPStan\DependencyInjection\Container;
use PHPStan\Node\Printer\ExprPrinter;
use PHPStan\Php\PhpVersion;
use PHPStan\Reflection\ReflectionProvider;
use function array_merge;

@@ -24,6 +25,7 @@ public function create(): TypeSpecifier
$typeSpecifier = new TypeSpecifier(
$this->container->getByType(ExprPrinter::class),
$this->container->getByType(ReflectionProvider::class),
$this->container->getByType(PhpVersion::class),
$this->container->getServicesByTag(self::FUNCTION_TYPE_SPECIFYING_EXTENSION_TAG),
$this->container->getServicesByTag(self::METHOD_TYPE_SPECIFYING_EXTENSION_TAG),
$this->container->getServicesByTag(self::STATIC_METHOD_TYPE_SPECIFYING_EXTENSION_TAG),
8 changes: 4 additions & 4 deletions src/Reflection/InitializerExprTypeResolver.php
Original file line number Diff line number Diff line change
@@ -316,19 +316,19 @@ public function getType(Expr $expr, InitializerExprContext $context): Type
}

if ($expr instanceof Expr\BinaryOp\Smaller) {
return $this->getType($expr->left, $context)->isSmallerThan($this->getType($expr->right, $context))->toBooleanType();
return $this->getType($expr->left, $context)->isSmallerThan($this->getType($expr->right, $context), $this->phpVersion)->toBooleanType();
}

if ($expr instanceof Expr\BinaryOp\SmallerOrEqual) {
return $this->getType($expr->left, $context)->isSmallerThanOrEqual($this->getType($expr->right, $context))->toBooleanType();
return $this->getType($expr->left, $context)->isSmallerThanOrEqual($this->getType($expr->right, $context), $this->phpVersion)->toBooleanType();
}

if ($expr instanceof Expr\BinaryOp\Greater) {
return $this->getType($expr->right, $context)->isSmallerThan($this->getType($expr->left, $context))->toBooleanType();
return $this->getType($expr->right, $context)->isSmallerThan($this->getType($expr->left, $context), $this->phpVersion)->toBooleanType();
}

if ($expr instanceof Expr\BinaryOp\GreaterOrEqual) {
return $this->getType($expr->right, $context)->isSmallerThanOrEqual($this->getType($expr->left, $context))->toBooleanType();
return $this->getType($expr->right, $context)->isSmallerThanOrEqual($this->getType($expr->left, $context), $this->phpVersion)->toBooleanType();
}

if ($expr instanceof Expr\BinaryOp\LogicalXor) {
9 changes: 7 additions & 2 deletions src/Rules/Functions/RandomIntParametersRule.php
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
use PhpParser\Node;
use PhpParser\Node\Expr\FuncCall;
use PHPStan\Analyser\Scope;
use PHPStan\Php\PhpVersion;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
@@ -21,7 +22,11 @@
final class RandomIntParametersRule implements Rule
{

public function __construct(private ReflectionProvider $reflectionProvider, private bool $reportMaybes)
public function __construct(
private ReflectionProvider $reflectionProvider,
private PhpVersion $phpVersion,
private bool $reportMaybes,
)
{
}

@@ -55,7 +60,7 @@ public function processNode(Node $node, Scope $scope): array
return [];
}

$isSmaller = $maxType->isSmallerThan($minType);
$isSmaller = $maxType->isSmallerThan($minType, $this->phpVersion);

if ($isSmaller->yes() || $isSmaller->maybe() && $this->reportMaybes) {
$message = 'Parameter #1 $min (%s) of function random_int expects lower number than parameter #2 $max (%s).';
5 changes: 3 additions & 2 deletions src/Type/CompoundType.php
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@

namespace PHPStan\Type;

use PHPStan\Php\PhpVersion;
use PHPStan\TrinaryLogic;

/** @api */
@@ -14,8 +15,8 @@ public function isAcceptedBy(Type $acceptingType, bool $strictTypes): TrinaryLog

public function isAcceptedWithReasonBy(Type $acceptingType, bool $strictTypes): AcceptsResult;

public function isGreaterThan(Type $otherType): TrinaryLogic;
public function isGreaterThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic;

public function isGreaterThanOrEqual(Type $otherType): TrinaryLogic;
public function isGreaterThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic;

}
8 changes: 4 additions & 4 deletions src/Type/Constant/ConstantBooleanType.php
Original file line number Diff line number Diff line change
@@ -40,31 +40,31 @@ public function describe(VerbosityLevel $level): string
return $this->value ? 'true' : 'false';
}

public function getSmallerType(): Type
public function getSmallerType(PhpVersion $phpVersion): Type
{
if ($this->value) {
return StaticTypeFactory::falsey();
}
return new NeverType();
}

public function getSmallerOrEqualType(): Type
public function getSmallerOrEqualType(PhpVersion $phpVersion): Type
{
if ($this->value) {
return new MixedType();
}
return StaticTypeFactory::falsey();
}

public function getGreaterType(): Type
public function getGreaterType(PhpVersion $phpVersion): Type
{
if ($this->value) {
return new NeverType();
}
return StaticTypeFactory::truthy();
}

public function getGreaterOrEqualType(): Type
public function getGreaterOrEqualType(PhpVersion $phpVersion): Type
{
if ($this->value) {
return StaticTypeFactory::truthy();
9 changes: 5 additions & 4 deletions src/Type/Constant/ConstantStringType.php
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@
use Nette\Utils\Strings;
use PhpParser\Node\Name;
use PHPStan\Analyser\OutOfClassScope;
use PHPStan\Php\PhpVersion;
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprStringNode;
use PHPStan\PhpDocParser\Ast\Type\ConstTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
@@ -461,7 +462,7 @@ public function generalize(GeneralizePrecision $precision): Type
return new StringType();
}

public function getSmallerType(): Type
public function getSmallerType(PhpVersion $phpVersion): Type
{
$subtractedTypes = [
new ConstantBooleanType(true),
@@ -480,7 +481,7 @@ public function getSmallerType(): Type
return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes));
}

public function getSmallerOrEqualType(): Type
public function getSmallerOrEqualType(PhpVersion $phpVersion): Type
{
$subtractedTypes = [
IntegerRangeType::createAllGreaterThan((float) $this->value),
@@ -493,7 +494,7 @@ public function getSmallerOrEqualType(): Type
return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes));
}

public function getGreaterType(): Type
public function getGreaterType(PhpVersion $phpVersion): Type
{
$subtractedTypes = [
new ConstantBooleanType(false),
@@ -507,7 +508,7 @@ public function getGreaterType(): Type
return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes));
}

public function getGreaterOrEqualType(): Type
public function getGreaterOrEqualType(PhpVersion $phpVersion): Type
{
$subtractedTypes = [
IntegerRangeType::createAllSmallerThan((float) $this->value),
5 changes: 3 additions & 2 deletions src/Type/Enum/EnumCaseObjectType.php
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@

namespace PHPStan\Type\Enum;

use PHPStan\Php\PhpVersion;
use PHPStan\PhpDocParser\Ast\ConstExpr\ConstFetchNode;
use PHPStan\PhpDocParser\Ast\Type\ConstTypeNode;
use PHPStan\PhpDocParser\Ast\Type\TypeNode;
@@ -179,12 +180,12 @@ public function generalize(GeneralizePrecision $precision): Type
return new parent($this->getClassName(), null, $this->getClassReflection());
}

public function isSmallerThan(Type $otherType): TrinaryLogic
public function isSmallerThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic
{
return TrinaryLogic::createNo();
}

public function isSmallerThanOrEqual(Type $otherType): TrinaryLogic
public function isSmallerThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic
{
return TrinaryLogic::createNo();
}
34 changes: 17 additions & 17 deletions src/Type/IntegerRangeType.php
Original file line number Diff line number Diff line change
@@ -308,75 +308,75 @@ public function generalize(GeneralizePrecision $precision): Type
return new IntegerType();
}

public function isSmallerThan(Type $otherType): TrinaryLogic
public function isSmallerThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic
{
if ($this->min === null) {
$minIsSmaller = TrinaryLogic::createYes();
} else {
$minIsSmaller = (new ConstantIntegerType($this->min))->isSmallerThan($otherType);
$minIsSmaller = (new ConstantIntegerType($this->min))->isSmallerThan($otherType, $phpVersion);
}

if ($this->max === null) {
$maxIsSmaller = TrinaryLogic::createNo();
} else {
$maxIsSmaller = (new ConstantIntegerType($this->max))->isSmallerThan($otherType);
$maxIsSmaller = (new ConstantIntegerType($this->max))->isSmallerThan($otherType, $phpVersion);
}

return TrinaryLogic::extremeIdentity($minIsSmaller, $maxIsSmaller);
}

public function isSmallerThanOrEqual(Type $otherType): TrinaryLogic
public function isSmallerThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic
{
if ($this->min === null) {
$minIsSmaller = TrinaryLogic::createYes();
} else {
$minIsSmaller = (new ConstantIntegerType($this->min))->isSmallerThanOrEqual($otherType);
$minIsSmaller = (new ConstantIntegerType($this->min))->isSmallerThanOrEqual($otherType, $phpVersion);
}

if ($this->max === null) {
$maxIsSmaller = TrinaryLogic::createNo();
} else {
$maxIsSmaller = (new ConstantIntegerType($this->max))->isSmallerThanOrEqual($otherType);
$maxIsSmaller = (new ConstantIntegerType($this->max))->isSmallerThanOrEqual($otherType, $phpVersion);
}

return TrinaryLogic::extremeIdentity($minIsSmaller, $maxIsSmaller);
}

public function isGreaterThan(Type $otherType): TrinaryLogic
public function isGreaterThan(Type $otherType, PhpVersion $phpVersion): TrinaryLogic
{
if ($this->min === null) {
$minIsSmaller = TrinaryLogic::createNo();
} else {
$minIsSmaller = $otherType->isSmallerThan((new ConstantIntegerType($this->min)));
$minIsSmaller = $otherType->isSmallerThan((new ConstantIntegerType($this->min)), $phpVersion);
}

if ($this->max === null) {
$maxIsSmaller = TrinaryLogic::createYes();
} else {
$maxIsSmaller = $otherType->isSmallerThan((new ConstantIntegerType($this->max)));
$maxIsSmaller = $otherType->isSmallerThan((new ConstantIntegerType($this->max)), $phpVersion);
}

return TrinaryLogic::extremeIdentity($minIsSmaller, $maxIsSmaller);
}

public function isGreaterThanOrEqual(Type $otherType): TrinaryLogic
public function isGreaterThanOrEqual(Type $otherType, PhpVersion $phpVersion): TrinaryLogic
{
if ($this->min === null) {
$minIsSmaller = TrinaryLogic::createNo();
} else {
$minIsSmaller = $otherType->isSmallerThanOrEqual((new ConstantIntegerType($this->min)));
$minIsSmaller = $otherType->isSmallerThanOrEqual((new ConstantIntegerType($this->min)), $phpVersion);
}

if ($this->max === null) {
$maxIsSmaller = TrinaryLogic::createYes();
} else {
$maxIsSmaller = $otherType->isSmallerThanOrEqual((new ConstantIntegerType($this->max)));
$maxIsSmaller = $otherType->isSmallerThanOrEqual((new ConstantIntegerType($this->max)), $phpVersion);
}

return TrinaryLogic::extremeIdentity($minIsSmaller, $maxIsSmaller);
}

public function getSmallerType(): Type
public function getSmallerType(PhpVersion $phpVersion): Type
{
$subtractedTypes = [
new ConstantBooleanType(true),
@@ -389,7 +389,7 @@ public function getSmallerType(): Type
return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes));
}

public function getSmallerOrEqualType(): Type
public function getSmallerOrEqualType(PhpVersion $phpVersion): Type
{
$subtractedTypes = [];

@@ -400,7 +400,7 @@ public function getSmallerOrEqualType(): Type
return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes));
}

public function getGreaterType(): Type
public function getGreaterType(PhpVersion $phpVersion): Type
{
$subtractedTypes = [
new NullType(),
@@ -418,7 +418,7 @@ public function getGreaterType(): Type
return TypeCombinator::remove(new MixedType(), TypeCombinator::union(...$subtractedTypes));
}

public function getGreaterOrEqualType(): Type
public function getGreaterOrEqualType(PhpVersion $phpVersion): Type
{
$subtractedTypes = [];

@@ -692,7 +692,7 @@ public function toPhpDocNode(): TypeNode

public function looseCompare(Type $type, PhpVersion $phpVersion): BooleanType
{
if ($this->isSmallerThan($type)->yes() || $this->isGreaterThan($type)->yes()) {
if ($this->isSmallerThan($type, $phpVersion)->yes() || $this->isGreaterThan($type, $phpVersion)->yes()) {
return new ConstantBooleanType(false);
}

Loading
Loading