mirror of
https://github.com/danog/psalm.git
synced 2025-01-21 21:31:13 +01:00
remove TPositiveInt
This commit is contained in:
parent
7c4f08067b
commit
63b802bff4
237
UPGRADING.md
237
UPGRADING.md
@ -1,126 +1,127 @@
|
||||
# Upgrading from Psalm 4 to Psalm 5
|
||||
## Changed
|
||||
- [BC] The parameter `$php_version` of `Psalm\Type\Atomic::create()` renamed
|
||||
to `$analysis_php_version_id` and changed from `array|null` to `int|null`.
|
||||
Previously it accepted PHP version as `array{major_version, minor_version}`
|
||||
while now it accepts version ID, similar to how [`PHP_VERSION_ID` is
|
||||
calculated](https://www.php.net/manual/en/reserved.constants.php#constant.php-version-id).
|
||||
- [BC] TPositiveInt has been removed and replaced by TIntRange
|
||||
|
||||
- [BC] The parameter `$php_version` of `Psalm\Type::parseString()` renamed to
|
||||
`$analysis_php_version_id` and changed from `array|null` to `int|null`.
|
||||
Previously it accepted PHP version as `array{major_version, minor_version}`
|
||||
while now it accepts version ID.
|
||||
- [BC] The parameter `$php_version` of `Psalm\Type\Atomic::create()` renamed
|
||||
to `$analysis_php_version_id` and changed from `array|null` to `int|null`.
|
||||
Previously it accepted PHP version as `array{major_version, minor_version}`
|
||||
while now it accepts version ID, similar to how [`PHP_VERSION_ID` is
|
||||
calculated](https://www.php.net/manual/en/reserved.constants.php#constant.php-version-id).
|
||||
|
||||
- [BC] Parameter 0 of `canBeFullyExpressedInPhp()` of the classes listed below
|
||||
changed name from `php_major_version` to `analysis_php_version_id`.
|
||||
Previously it accepted major PHP version as int (e.g. `7`), while now it
|
||||
accepts version ID. Classes affected:
|
||||
- `Psalm\Type\Atomic`
|
||||
- `Psalm\Type\Atomic\Scalar`
|
||||
- `Psalm\Type\Atomic\TArray`
|
||||
- `Psalm\Type\Atomic\TArrayKey`
|
||||
- `Psalm\Type\Atomic\TCallable`
|
||||
- `Psalm\Type\Atomic\TCallableObject`
|
||||
- `Psalm\Type\Atomic\TCallableString`
|
||||
- `Psalm\Type\Atomic\TClassConstant`
|
||||
- `Psalm\Type\Atomic\TClassString`
|
||||
- `Psalm\Type\Atomic\TClassStringMap`
|
||||
- `Psalm\Type\Atomic\TClosedResource`
|
||||
- `Psalm\Type\Atomic\TClosure`
|
||||
- `Psalm\Type\Atomic\TConditional`
|
||||
- `Psalm\Type\Atomic\TDependentGetClass`
|
||||
- `Psalm\Type\Atomic\TDependentGetDebugType`
|
||||
- `Psalm\Type\Atomic\TDependentGetType`
|
||||
- `Psalm\Type\Atomic\TDependentListKey`
|
||||
- `Psalm\Type\Atomic\TEnumCase`
|
||||
- `Psalm\Type\Atomic\TFalse`
|
||||
- `Psalm\Type\Atomic\TGenericObject`
|
||||
- `Psalm\Type\Atomic\TIntMask`
|
||||
- `Psalm\Type\Atomic\TIntMaskOf`
|
||||
- `Psalm\Type\Atomic\TIntRange`
|
||||
- `Psalm\Type\Atomic\TIterable`
|
||||
- `Psalm\Type\Atomic\TKeyedArray`
|
||||
- `Psalm\Type\Atomic\TKeyOfClassConstant`
|
||||
- `Psalm\Type\Atomic\TList`
|
||||
- `Psalm\Type\Atomic\TLiteralClassString`
|
||||
- `Psalm\Type\Atomic\TLowercaseString`
|
||||
- `Psalm\Type\Atomic\TMixed`
|
||||
- `Psalm\Type\Atomic\TNamedObject`
|
||||
- `Psalm\Type\Atomic\TNever`
|
||||
- `Psalm\Type\Atomic\TNonEmptyLowercaseString`
|
||||
- `Psalm\Type\Atomic\TNonspecificLiteralInt`
|
||||
- `Psalm\Type\Atomic\TNonspecificLiteralString`
|
||||
- `Psalm\Type\Atomic\TNull`
|
||||
- `Psalm\Type\Atomic\TNumeric`
|
||||
- `Psalm\Type\Atomic\TNumericString`
|
||||
- `Psalm\Type\Atomic\TObject`
|
||||
- `Psalm\Type\Atomic\TObjectWithProperties`
|
||||
- `Psalm\Type\Atomic\TPositiveInt`
|
||||
- `Psalm\Type\Atomic\TResource`
|
||||
- `Psalm\Type\Atomic\TScalar`
|
||||
- `Psalm\Type\Atomic\TTemplateIndexedAccess`
|
||||
- `Psalm\Type\Atomic\TTemplateParam`
|
||||
- `Psalm\Type\Atomic\TTraitString`
|
||||
- `Psalm\Type\Atomic\TTrue`
|
||||
- `Psalm\Type\Atomic\TTypeAlias`
|
||||
- `Psalm\Type\Atomic\TValueOfClassConstant`
|
||||
- `Psalm\Type\Atomic\TVoid`
|
||||
- `Psalm\Type\Union`
|
||||
- [BC] The parameter `$php_version` of `Psalm\Type::parseString()` renamed to
|
||||
`$analysis_php_version_id` and changed from `array|null` to `int|null`.
|
||||
Previously it accepted PHP version as `array{major_version, minor_version}`
|
||||
while now it accepts version ID.
|
||||
|
||||
- [BC] Parameter 3 of `toPhpString()` of methods listed below changed name
|
||||
from `php_major_version` to `analysis_php_version_id`. Previously it
|
||||
accepted major PHP version as int (e.g. `7`), while now it accepts version
|
||||
ID. Classes affected:
|
||||
- `Psalm\Type\Atomic`
|
||||
- `Psalm\Type\Atomic\CallableTrait`
|
||||
- `Psalm\Type\Atomic\TAnonymousClassInstance`
|
||||
- `Psalm\Type\Atomic\TArray`
|
||||
- `Psalm\Type\Atomic\TArrayKey`
|
||||
- `Psalm\Type\Atomic\TBool`
|
||||
- `Psalm\Type\Atomic\TCallable`
|
||||
- `Psalm\Type\Atomic\TCallableObject`
|
||||
- `Psalm\Type\Atomic\TClassConstant`
|
||||
- `Psalm\Type\Atomic\TClassString`
|
||||
- `Psalm\Type\Atomic\TClassStringMap`
|
||||
- `Psalm\Type\Atomic\TClosedResource`
|
||||
- `Psalm\Type\Atomic\TConditional`
|
||||
- `Psalm\Type\Atomic\TEmpty`
|
||||
- `Psalm\Type\Atomic\TEnumCase`
|
||||
- `Psalm\Type\Atomic\TFloat`
|
||||
- `Psalm\Type\Atomic\TGenericObject`
|
||||
- `Psalm\Type\Atomic\TInt`
|
||||
- `Psalm\Type\Atomic\TIterable`
|
||||
- `Psalm\Type\Atomic\TKeyedArray`
|
||||
- `Psalm\Type\Atomic\TKeyOfClassConstant`
|
||||
- `Psalm\Type\Atomic\TList`
|
||||
- `Psalm\Type\Atomic\TLiteralClassString`
|
||||
- `Psalm\Type\Atomic\TMixed`
|
||||
- `Psalm\Type\Atomic\TNamedObject`
|
||||
- `Psalm\Type\Atomic\TNever`
|
||||
- `Psalm\Type\Atomic\TNull`
|
||||
- `Psalm\Type\Atomic\TNumeric`
|
||||
- `Psalm\Type\Atomic\TObject`
|
||||
- `Psalm\Type\Atomic\TObjectWithProperties`
|
||||
- `Psalm\Type\Atomic\TResource`
|
||||
- `Psalm\Type\Atomic\TScalar`
|
||||
- `Psalm\Type\Atomic\TString`
|
||||
- `Psalm\Type\Atomic\TTemplateIndexedAccess`
|
||||
- `Psalm\Type\Atomic\TTemplateParam`
|
||||
- `Psalm\Type\Atomic\TTraitString`
|
||||
- `Psalm\Type\Atomic\TTypeAlias`
|
||||
- `Psalm\Type\Atomic\TValueOfClassConstant`
|
||||
- `Psalm\Type\Atomic\TVoid`
|
||||
- `Psalm\Type\Union`
|
||||
- While not a BC break per se, all classes / interfaces / traits / enums under
|
||||
`Psalm\Internal` namespace are now marked `@internal`.
|
||||
- [BC] Parameter 1 of `Psalm\Type\Atomic\TNamedObject::__construct()` changed name from `was_static` to `is_static`
|
||||
- [BC] Parameter 1 of `Psalm\Type\Atomic\TAnonymousClassInstance::__construct()` changed name from `was_static` to `is_static`
|
||||
- [BC] Parameter 5 of `Psalm\Type::getStringFromFQCLN()` changed name from `was_static` to `is_static`
|
||||
- [BC] Property `Psalm\Type\Atomic\TNamedObject::$was_static` was renamed to `$is_static`
|
||||
- [BC] Method `Psalm\Type\Union::isFormerStaticObject()` was renamed to `isStaticObject()`
|
||||
- [BC] Method `Psalm\Type\Union::hasFormerStaticObject()` was renamed to `hasStaticObject()`
|
||||
- [BC] Function assertions (from `@psalm-assert Foo $bar`) have been converted from strings to specific `Assertion` objects.
|
||||
- [BC] Property `Psalm\Storage\ClassLikeStorage::$invalid_dependencies` changed from `array<string>` to `array<string, true>`.
|
||||
- [BC] Parameter 0 of `canBeFullyExpressedInPhp()` of the classes listed below
|
||||
changed name from `php_major_version` to `analysis_php_version_id`.
|
||||
Previously it accepted major PHP version as int (e.g. `7`), while now it
|
||||
accepts version ID. Classes affected:
|
||||
- `Psalm\Type\Atomic`
|
||||
- `Psalm\Type\Atomic\Scalar`
|
||||
- `Psalm\Type\Atomic\TArray`
|
||||
- `Psalm\Type\Atomic\TArrayKey`
|
||||
- `Psalm\Type\Atomic\TCallable`
|
||||
- `Psalm\Type\Atomic\TCallableObject`
|
||||
- `Psalm\Type\Atomic\TCallableString`
|
||||
- `Psalm\Type\Atomic\TClassConstant`
|
||||
- `Psalm\Type\Atomic\TClassString`
|
||||
- `Psalm\Type\Atomic\TClassStringMap`
|
||||
- `Psalm\Type\Atomic\TClosedResource`
|
||||
- `Psalm\Type\Atomic\TClosure`
|
||||
- `Psalm\Type\Atomic\TConditional`
|
||||
- `Psalm\Type\Atomic\TDependentGetClass`
|
||||
- `Psalm\Type\Atomic\TDependentGetDebugType`
|
||||
- `Psalm\Type\Atomic\TDependentGetType`
|
||||
- `Psalm\Type\Atomic\TDependentListKey`
|
||||
- `Psalm\Type\Atomic\TEnumCase`
|
||||
- `Psalm\Type\Atomic\TFalse`
|
||||
- `Psalm\Type\Atomic\TGenericObject`
|
||||
- `Psalm\Type\Atomic\TIntMask`
|
||||
- `Psalm\Type\Atomic\TIntMaskOf`
|
||||
- `Psalm\Type\Atomic\TIntRange`
|
||||
- `Psalm\Type\Atomic\TIterable`
|
||||
- `Psalm\Type\Atomic\TKeyedArray`
|
||||
- `Psalm\Type\Atomic\TKeyOfClassConstant`
|
||||
- `Psalm\Type\Atomic\TList`
|
||||
- `Psalm\Type\Atomic\TLiteralClassString`
|
||||
- `Psalm\Type\Atomic\TLowercaseString`
|
||||
- `Psalm\Type\Atomic\TMixed`
|
||||
- `Psalm\Type\Atomic\TNamedObject`
|
||||
- `Psalm\Type\Atomic\TNever`
|
||||
- `Psalm\Type\Atomic\TNonEmptyLowercaseString`
|
||||
- `Psalm\Type\Atomic\TNonspecificLiteralInt`
|
||||
- `Psalm\Type\Atomic\TNonspecificLiteralString`
|
||||
- `Psalm\Type\Atomic\TNull`
|
||||
- `Psalm\Type\Atomic\TNumeric`
|
||||
- `Psalm\Type\Atomic\TNumericString`
|
||||
- `Psalm\Type\Atomic\TObject`
|
||||
- `Psalm\Type\Atomic\TObjectWithProperties`
|
||||
- `Psalm\Type\Atomic\TResource`
|
||||
- `Psalm\Type\Atomic\TScalar`
|
||||
- `Psalm\Type\Atomic\TTemplateIndexedAccess`
|
||||
- `Psalm\Type\Atomic\TTemplateParam`
|
||||
- `Psalm\Type\Atomic\TTraitString`
|
||||
- `Psalm\Type\Atomic\TTrue`
|
||||
- `Psalm\Type\Atomic\TTypeAlias`
|
||||
- `Psalm\Type\Atomic\TValueOfClassConstant`
|
||||
- `Psalm\Type\Atomic\TVoid`
|
||||
- `Psalm\Type\Union`
|
||||
|
||||
- [BC] Parameter 3 of `toPhpString()` of methods listed below changed name
|
||||
from `php_major_version` to `analysis_php_version_id`. Previously it
|
||||
accepted major PHP version as int (e.g. `7`), while now it accepts version
|
||||
ID. Classes affected:
|
||||
- `Psalm\Type\Atomic`
|
||||
- `Psalm\Type\Atomic\CallableTrait`
|
||||
- `Psalm\Type\Atomic\TAnonymousClassInstance`
|
||||
- `Psalm\Type\Atomic\TArray`
|
||||
- `Psalm\Type\Atomic\TArrayKey`
|
||||
- `Psalm\Type\Atomic\TBool`
|
||||
- `Psalm\Type\Atomic\TCallable`
|
||||
- `Psalm\Type\Atomic\TCallableObject`
|
||||
- `Psalm\Type\Atomic\TClassConstant`
|
||||
- `Psalm\Type\Atomic\TClassString`
|
||||
- `Psalm\Type\Atomic\TClassStringMap`
|
||||
- `Psalm\Type\Atomic\TClosedResource`
|
||||
- `Psalm\Type\Atomic\TConditional`
|
||||
- `Psalm\Type\Atomic\TEmpty`
|
||||
- `Psalm\Type\Atomic\TEnumCase`
|
||||
- `Psalm\Type\Atomic\TFloat`
|
||||
- `Psalm\Type\Atomic\TGenericObject`
|
||||
- `Psalm\Type\Atomic\TInt`
|
||||
- `Psalm\Type\Atomic\TIterable`
|
||||
- `Psalm\Type\Atomic\TKeyedArray`
|
||||
- `Psalm\Type\Atomic\TKeyOfClassConstant`
|
||||
- `Psalm\Type\Atomic\TList`
|
||||
- `Psalm\Type\Atomic\TLiteralClassString`
|
||||
- `Psalm\Type\Atomic\TMixed`
|
||||
- `Psalm\Type\Atomic\TNamedObject`
|
||||
- `Psalm\Type\Atomic\TNever`
|
||||
- `Psalm\Type\Atomic\TNull`
|
||||
- `Psalm\Type\Atomic\TNumeric`
|
||||
- `Psalm\Type\Atomic\TObject`
|
||||
- `Psalm\Type\Atomic\TObjectWithProperties`
|
||||
- `Psalm\Type\Atomic\TResource`
|
||||
- `Psalm\Type\Atomic\TScalar`
|
||||
- `Psalm\Type\Atomic\TString`
|
||||
- `Psalm\Type\Atomic\TTemplateIndexedAccess`
|
||||
- `Psalm\Type\Atomic\TTemplateParam`
|
||||
- `Psalm\Type\Atomic\TTraitString`
|
||||
- `Psalm\Type\Atomic\TTypeAlias`
|
||||
- `Psalm\Type\Atomic\TValueOfClassConstant`
|
||||
- `Psalm\Type\Atomic\TVoid`
|
||||
- `Psalm\Type\Union`
|
||||
- While not a BC break per se, all classes / interfaces / traits / enums under
|
||||
`Psalm\Internal` namespace are now marked `@internal`.
|
||||
- [BC] Parameter 1 of `Psalm\Type\Atomic\TNamedObject::__construct()` changed name from `was_static` to `is_static`
|
||||
- [BC] Parameter 1 of `Psalm\Type\Atomic\TAnonymousClassInstance::__construct()` changed name from `was_static` to `is_static`
|
||||
- [BC] Parameter 5 of `Psalm\Type::getStringFromFQCLN()` changed name from `was_static` to `is_static`
|
||||
- [BC] Property `Psalm\Type\Atomic\TNamedObject::$was_static` was renamed to `$is_static`
|
||||
- [BC] Method `Psalm\Type\Union::isFormerStaticObject()` was renamed to `isStaticObject()`
|
||||
- [BC] Method `Psalm\Type\Union::hasFormerStaticObject()` was renamed to `hasStaticObject()`
|
||||
- [BC] Function assertions (from `@psalm-assert Foo $bar`) have been converted from strings to specific `Assertion` objects.
|
||||
- [BC] Property `Psalm\Storage\ClassLikeStorage::$invalid_dependencies` changed from `array<string>` to `array<string, true>`.
|
||||
|
||||
## Removed
|
||||
- [BC] Property `Psalm\Codebase::$php_major_version` was removed, use
|
||||
|
@ -83,7 +83,7 @@ All scalar types have literal versions e.g. `int` vs `int(5)`.
|
||||
|
||||
`TLiteralInt` - is used to represent an integer value where the exact numeric value is known.
|
||||
|
||||
`TPositiveInt` - denotes an int that is also positive (strictly > 0)
|
||||
`TIntRange` - allows to describe an int with bounded values (ie. `int<1, 5>`).
|
||||
|
||||
#### Floats
|
||||
|
||||
|
@ -147,7 +147,7 @@ class ArrayAnalyzer
|
||||
$array_type = new TList($item_value_type ?? Type::getMixed());
|
||||
} else {
|
||||
$array_type = new TNonEmptyList($item_value_type ?? Type::getMixed());
|
||||
/** @psalm-suppress PossiblyInvalidPropertyAssignmentValue */
|
||||
/** @psalm-suppress InvalidPropertyAssignmentValue */
|
||||
$array_type->count = count($array_creation_info->property_types);
|
||||
}
|
||||
|
||||
@ -235,7 +235,7 @@ class ArrayAnalyzer
|
||||
$item_value_type ?? Type::getMixed(),
|
||||
]);
|
||||
|
||||
/** @psalm-suppress PossiblyInvalidPropertyAssignmentValue */
|
||||
/** @psalm-suppress InvalidPropertyAssignmentValue */
|
||||
$array_type->count = count($array_creation_info->property_types);
|
||||
|
||||
$stmt_type = new Union([
|
||||
|
@ -40,7 +40,6 @@ use Psalm\Type\Atomic\TNamedObject;
|
||||
use Psalm\Type\Atomic\TNull;
|
||||
use Psalm\Type\Atomic\TNumeric;
|
||||
use Psalm\Type\Atomic\TNumericString;
|
||||
use Psalm\Type\Atomic\TPositiveInt;
|
||||
use Psalm\Type\Atomic\TString;
|
||||
use Psalm\Type\Atomic\TTemplateParam;
|
||||
use Psalm\Type\Union;
|
||||
@ -728,11 +727,11 @@ class ArithmeticOpAnalyzer
|
||||
if ($parent instanceof PhpParser\Node\Expr\BinaryOp\Div) {
|
||||
$result_type = new Union([new TInt(), new TFloat()]);
|
||||
} else {
|
||||
$left_is_positive = $left_type_part instanceof TPositiveInt
|
||||
|| ($left_type_part instanceof TLiteralInt && $left_type_part->value > 0);
|
||||
$left_is_positive = ($left_type_part instanceof TLiteralInt && $left_type_part->value > 0)
|
||||
|| ($left_type_part instanceof TIntRange && $left_type_part->isPositive());
|
||||
|
||||
$right_is_positive = $right_type_part instanceof TPositiveInt
|
||||
|| ($right_type_part instanceof TLiteralInt && $right_type_part->value > 0);
|
||||
$right_is_positive = ($right_type_part instanceof TLiteralInt && $right_type_part->value > 0)
|
||||
|| ($right_type_part instanceof TIntRange && $right_type_part->isPositive());
|
||||
|
||||
if ($parent instanceof PhpParser\Node\Expr\BinaryOp\Minus) {
|
||||
$always_positive = false;
|
||||
@ -772,17 +771,14 @@ class ArithmeticOpAnalyzer
|
||||
}
|
||||
} else {
|
||||
if ($always_positive) {
|
||||
$result_type = new Union([
|
||||
new TPositiveInt(),
|
||||
new TLiteralInt(0)
|
||||
]);
|
||||
$result_type = new Union([new TIntRange(0, null)]);
|
||||
} else {
|
||||
$result_type = Type::getInt();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$result_type = Type::combineUnionTypes(
|
||||
$always_positive ? Type::getPositiveInt(true) : Type::getInt(true),
|
||||
$always_positive ? new Union([new TIntRange(1, null)]) : Type::getInt(true),
|
||||
$result_type
|
||||
);
|
||||
}
|
||||
|
@ -41,7 +41,6 @@ use Psalm\Type\Atomic\TNamedObject;
|
||||
use Psalm\Type\Atomic\TNonEmptyArray;
|
||||
use Psalm\Type\Atomic\TNonEmptyList;
|
||||
use Psalm\Type\Atomic\TNull;
|
||||
use Psalm\Type\Atomic\TPositiveInt;
|
||||
use Psalm\Type\Union;
|
||||
use UnexpectedValueException;
|
||||
|
||||
@ -373,7 +372,7 @@ class FunctionCallReturnTypeFetcher
|
||||
return new Union([
|
||||
$atomic_types['array']->count !== null
|
||||
? new TLiteralInt($atomic_types['array']->count)
|
||||
: new TPositiveInt
|
||||
: new TIntRange(1, null)
|
||||
]);
|
||||
}
|
||||
|
||||
@ -381,7 +380,7 @@ class FunctionCallReturnTypeFetcher
|
||||
return new Union([
|
||||
$atomic_types['array']->count !== null
|
||||
? new TLiteralInt($atomic_types['array']->count)
|
||||
: new TPositiveInt
|
||||
: new TIntRange(1, null)
|
||||
]);
|
||||
}
|
||||
|
||||
@ -422,8 +421,7 @@ class FunctionCallReturnTypeFetcher
|
||||
}
|
||||
|
||||
return new Union([
|
||||
new TLiteralInt(0),
|
||||
new TPositiveInt
|
||||
new TIntRange(0, null)
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -72,7 +72,6 @@ use Psalm\Type\Atomic\TNonEmptyList;
|
||||
use Psalm\Type\Atomic\TNull;
|
||||
use Psalm\Type\Atomic\TObject;
|
||||
use Psalm\Type\Atomic\TObjectWithProperties;
|
||||
use Psalm\Type\Atomic\TPositiveInt;
|
||||
use Psalm\Type\Atomic\TSingleLetter;
|
||||
use Psalm\Type\Atomic\TString;
|
||||
use Psalm\Type\Atomic\TTemplateIndexedAccess;
|
||||
@ -891,11 +890,6 @@ class ArrayFetchAnalyzer
|
||||
$found_match = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if ($offset_type_part instanceof TPositiveInt) {
|
||||
$found_match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$found_match) {
|
||||
|
@ -16,7 +16,6 @@ use Psalm\Type\Atomic\TInt;
|
||||
use Psalm\Type\Atomic\TIntRange;
|
||||
use Psalm\Type\Atomic\TLiteralFloat;
|
||||
use Psalm\Type\Atomic\TLiteralInt;
|
||||
use Psalm\Type\Atomic\TPositiveInt;
|
||||
use Psalm\Type\Atomic\TString;
|
||||
use Psalm\Type\Union;
|
||||
|
||||
@ -81,12 +80,6 @@ class UnaryPlusMinusAnalyzer
|
||||
}
|
||||
}
|
||||
|
||||
if ($type_part instanceof TPositiveInt
|
||||
&& $stmt instanceof PhpParser\Node\Expr\UnaryMinus
|
||||
) {
|
||||
$type_part = new TIntRange(null, -1);
|
||||
}
|
||||
|
||||
$acceptable_types[] = $type_part;
|
||||
} elseif ($type_part instanceof TString) {
|
||||
$acceptable_types[] = new TInt;
|
||||
|
@ -40,6 +40,7 @@ class AstDiffer
|
||||
$n = count($a);
|
||||
$m = count($b);
|
||||
$max = $n + $m;
|
||||
/** @var array<int, int> $v */
|
||||
$v = [1 => 0];
|
||||
$bc = [];
|
||||
$trace = [];
|
||||
|
@ -40,6 +40,7 @@ class FileDiffer
|
||||
$n = count($a);
|
||||
$m = count($b);
|
||||
$max = $n + $m;
|
||||
/** @var array<int, int> $v */
|
||||
$v = [1 => 0];
|
||||
$trace = [];
|
||||
for ($d = 0; $d <= $max; ++$d) {
|
||||
|
@ -97,10 +97,6 @@ class ArrayFillReturnTypeProvider implements FunctionReturnTypeProviderInterface
|
||||
|
||||
private static function isPositiveNumericType(Union $arg): bool
|
||||
{
|
||||
if ($arg->isSingle() && $arg->hasPositiveInt()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($arg->isSingle()) {
|
||||
foreach ($arg->getRangeInts() as $range_int) {
|
||||
if ($range_int->isPositive()) {
|
||||
|
@ -11,7 +11,6 @@ use Psalm\Type;
|
||||
use Psalm\Type\Atomic\TInt;
|
||||
use Psalm\Type\Atomic\TIntRange;
|
||||
use Psalm\Type\Atomic\TLiteralInt;
|
||||
use Psalm\Type\Atomic\TPositiveInt;
|
||||
use Psalm\Type\Union;
|
||||
use UnexpectedValueException;
|
||||
|
||||
@ -72,9 +71,6 @@ class MinMaxReturnTypeProvider implements FunctionReturnTypeProviderInterface
|
||||
} elseif ($atomic_type instanceof TIntRange) {
|
||||
$min_bounds[] = $atomic_type->min_bound;
|
||||
$max_bounds[] = $atomic_type->max_bound;
|
||||
} elseif ($atomic_type instanceof TPositiveInt) {
|
||||
$min_bounds[] = 1;
|
||||
$max_bounds[] = null;
|
||||
} elseif (get_class($atomic_type) === TInt::class) {
|
||||
$min_bounds[] = null;
|
||||
$max_bounds[] = null;
|
||||
@ -119,15 +115,6 @@ class MinMaxReturnTypeProvider implements FunctionReturnTypeProviderInterface
|
||||
$return_type = null;
|
||||
foreach ($call_args as $arg) {
|
||||
if ($array_arg_type = $nodeTypeProvider->getType($arg->value)) {
|
||||
if ($array_arg_type->isSingle()) {
|
||||
$atomic_type = $array_arg_type->getSingleAtomic();
|
||||
if ($atomic_type instanceof TPositiveInt) {
|
||||
//we replace TPositiveInt with a range for better combination
|
||||
$array_arg_type->removeType('int');
|
||||
$array_arg_type->addType(new TIntRange(1, null));
|
||||
}
|
||||
}
|
||||
|
||||
$return_type = Type::combineUnionTypes(
|
||||
$return_type,
|
||||
$array_arg_type
|
||||
|
@ -9,7 +9,6 @@ use Psalm\Plugin\EventHandler\FunctionReturnTypeProviderInterface;
|
||||
use Psalm\Type;
|
||||
use Psalm\Type\Atomic\TIntRange;
|
||||
use Psalm\Type\Atomic\TLiteralInt;
|
||||
use Psalm\Type\Atomic\TPositiveInt;
|
||||
use Psalm\Type\Union;
|
||||
|
||||
use function count;
|
||||
@ -51,8 +50,6 @@ class RandReturnTypeProvider implements FunctionReturnTypeProviderInterface
|
||||
$min_value = $first_atomic_type->value;
|
||||
} elseif ($first_atomic_type instanceof TIntRange) {
|
||||
$min_value = $first_atomic_type->min_bound;
|
||||
} elseif ($first_atomic_type instanceof TPositiveInt) {
|
||||
$min_value = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,8 +60,6 @@ class RandReturnTypeProvider implements FunctionReturnTypeProviderInterface
|
||||
$max_value = $second_atomic_type->value;
|
||||
} elseif ($second_atomic_type instanceof TIntRange) {
|
||||
$max_value = $second_atomic_type->max_bound;
|
||||
} elseif ($second_atomic_type instanceof TPositiveInt) {
|
||||
// no max value, we keep null
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,6 @@ use Psalm\Type\Atomic\TNamedObject;
|
||||
use Psalm\Type\Atomic\TNull;
|
||||
use Psalm\Type\Atomic\TNumeric;
|
||||
use Psalm\Type\Atomic\TObject;
|
||||
use Psalm\Type\Atomic\TPositiveInt;
|
||||
use Psalm\Type\Atomic\TScalar;
|
||||
use Psalm\Type\Atomic\TString;
|
||||
use Psalm\Type\Atomic\TTemplateParam;
|
||||
@ -781,19 +780,7 @@ class AssertionReconciler extends Reconciler
|
||||
|
||||
//These partial match wouldn't have been handled by AtomicTypeComparator
|
||||
$new_range = null;
|
||||
if ($type_2_atomic instanceof TIntRange && $type_1_atomic instanceof TPositiveInt) {
|
||||
$new_range = TIntRange::intersectIntRanges(
|
||||
TIntRange::convertToIntRange($type_1_atomic),
|
||||
$type_2_atomic
|
||||
);
|
||||
} elseif ($type_1_atomic instanceof TIntRange
|
||||
&& $type_2_atomic instanceof TPositiveInt
|
||||
) {
|
||||
$new_range = TIntRange::intersectIntRanges(
|
||||
$type_1_atomic,
|
||||
TIntRange::convertToIntRange($type_2_atomic)
|
||||
);
|
||||
} elseif ($type_2_atomic instanceof TIntRange
|
||||
if ($type_2_atomic instanceof TIntRange
|
||||
&& $type_1_atomic instanceof TIntRange
|
||||
) {
|
||||
$new_range = TIntRange::intersectIntRanges(
|
||||
@ -1012,10 +999,6 @@ class AssertionReconciler extends Reconciler
|
||||
}
|
||||
|
||||
foreach ($existing_var_atomic_types as $existing_var_atomic_type) {
|
||||
if ($existing_var_atomic_type instanceof TPositiveInt && $value > 0) {
|
||||
return $literal_asserted_type;
|
||||
}
|
||||
|
||||
if ($existing_var_atomic_type instanceof TIntRange && $existing_var_atomic_type->contains($value)) {
|
||||
return $literal_asserted_type;
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ use Psalm\Type\Atomic\TInt;
|
||||
use Psalm\Type\Atomic\TIntRange;
|
||||
use Psalm\Type\Atomic\TLiteralInt;
|
||||
use Psalm\Type\Atomic\TNonspecificLiteralInt;
|
||||
use Psalm\Type\Atomic\TPositiveInt;
|
||||
use Psalm\Type\Union;
|
||||
use UnexpectedValueException;
|
||||
|
||||
@ -62,17 +61,7 @@ class IntegerRangeComparator
|
||||
return true;
|
||||
}
|
||||
|
||||
if (get_class($container_atomic_types['int']) === TPositiveInt::class) {
|
||||
if ($input_type_part->isPositive()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//every positive integer is satisfied by the positive-int int container so we reduce the range
|
||||
$reduced_range->max_bound = 0;
|
||||
unset($container_atomic_types['int']);
|
||||
} else {
|
||||
throw new UnexpectedValueException('Should not happen: unknown int key');
|
||||
}
|
||||
throw new UnexpectedValueException('Should not happen: unknown int key');
|
||||
}
|
||||
|
||||
$new_nb_atomics = count($container_atomic_types);
|
||||
|
@ -32,7 +32,6 @@ use Psalm\Type\Atomic\TNonspecificLiteralInt;
|
||||
use Psalm\Type\Atomic\TNonspecificLiteralString;
|
||||
use Psalm\Type\Atomic\TNumeric;
|
||||
use Psalm\Type\Atomic\TNumericString;
|
||||
use Psalm\Type\Atomic\TPositiveInt;
|
||||
use Psalm\Type\Atomic\TScalar;
|
||||
use Psalm\Type\Atomic\TSingleLetter;
|
||||
use Psalm\Type\Atomic\TString;
|
||||
@ -307,8 +306,7 @@ class ScalarTypeComparator
|
||||
}
|
||||
|
||||
if (get_class($container_type_part) === TDependentListKey::class
|
||||
&& ($input_type_part instanceof TLiteralInt
|
||||
|| $input_type_part instanceof TPositiveInt)
|
||||
&& $input_type_part instanceof TLiteralInt
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
@ -369,11 +367,7 @@ class ScalarTypeComparator
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((get_class($input_type_part) === TInt::class && $container_type_part instanceof TLiteralInt)
|
||||
|| (get_class($input_type_part) === TPositiveInt::class
|
||||
&& $container_type_part instanceof TLiteralInt
|
||||
&& $container_type_part->value > 0)
|
||||
) {
|
||||
if (get_class($input_type_part) === TInt::class && $container_type_part instanceof TLiteralInt) {
|
||||
if ($atomic_comparison_result) {
|
||||
$atomic_comparison_result->type_coerced = true;
|
||||
$atomic_comparison_result->type_coerced_from_scalar = true;
|
||||
@ -389,49 +383,7 @@ class ScalarTypeComparator
|
||||
);
|
||||
}
|
||||
|
||||
if ($input_type_part instanceof TInt && $container_type_part instanceof TPositiveInt) {
|
||||
if ($input_type_part instanceof TPositiveInt) {
|
||||
return true;
|
||||
}
|
||||
if ($input_type_part instanceof TLiteralInt) {
|
||||
return $input_type_part->value > 0;
|
||||
}
|
||||
if ($input_type_part instanceof TIntRange) {
|
||||
return $input_type_part->isPositive();
|
||||
}
|
||||
|
||||
if ($atomic_comparison_result) {
|
||||
$atomic_comparison_result->type_coerced = true;
|
||||
$atomic_comparison_result->type_coerced_from_scalar = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($input_type_part instanceof TInt && $container_type_part instanceof TIntRange) {
|
||||
if ($input_type_part instanceof TPositiveInt) {
|
||||
if ($container_type_part->min_bound > 1) {
|
||||
//any positive int can't be pushed inside a range with a min > 1
|
||||
if ($atomic_comparison_result) {
|
||||
$atomic_comparison_result->type_coerced = true;
|
||||
$atomic_comparison_result->type_coerced_from_scalar = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($container_type_part->max_bound !== null) {
|
||||
//any positive int can't be pushed inside a range where the max bound isn't max without coercion
|
||||
if ($atomic_comparison_result) {
|
||||
$atomic_comparison_result->type_coerced = true;
|
||||
$atomic_comparison_result->type_coerced_from_scalar = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
if ($input_type_part instanceof TLiteralInt) {
|
||||
$min_bound = $container_type_part->min_bound;
|
||||
$max_bound = $container_type_part->max_bound;
|
||||
|
@ -12,7 +12,6 @@ use Psalm\Type\Atomic\TIntRange;
|
||||
use Psalm\Type\Atomic\TMixed;
|
||||
use Psalm\Type\Atomic\TNull;
|
||||
use Psalm\Type\Atomic\TNumeric;
|
||||
use Psalm\Type\Atomic\TPositiveInt;
|
||||
use Psalm\Type\Atomic\TTemplateParam;
|
||||
use Psalm\Type\Atomic\TTypeAlias;
|
||||
use Psalm\Type\Union;
|
||||
@ -413,24 +412,8 @@ class UnionTypeComparator
|
||||
|
||||
foreach (self::getTypeParts($codebase, $type1) as $type1_part) {
|
||||
foreach (self::getTypeParts($codebase, $type2) as $type2_part) {
|
||||
//special cases for TIntRange because it can contain a part of the other type.
|
||||
//For exemple int<0,1> and positive-int can be identical but none contain the other
|
||||
if (($type1_part instanceof TIntRange && $type2_part instanceof TPositiveInt)) {
|
||||
$intersection_range = TIntRange::intersectIntRanges(
|
||||
TIntRange::convertToIntRange($type2_part),
|
||||
$type1_part
|
||||
);
|
||||
return $intersection_range !== null;
|
||||
}
|
||||
|
||||
if ($type2_part instanceof TIntRange && $type1_part instanceof TPositiveInt) {
|
||||
$intersection_range = TIntRange::intersectIntRanges(
|
||||
TIntRange::convertToIntRange($type1_part),
|
||||
$type2_part
|
||||
);
|
||||
return $intersection_range !== null;
|
||||
}
|
||||
|
||||
//special case for TIntRange because it can contain a part of another TIntRange.
|
||||
//For exemple int<0,10> and int<5, 15> can be identical but none contain the other
|
||||
if ($type1_part instanceof TIntRange && $type2_part instanceof TIntRange) {
|
||||
$intersection_range = TIntRange::intersectIntRanges(
|
||||
$type1_part,
|
||||
|
@ -320,9 +320,7 @@ class NegatedAssertionReconciler extends Reconciler
|
||||
if ($assertion_type instanceof TLiteralInt) {
|
||||
if ($existing_var_type->hasInt()) {
|
||||
if ($existing_var_type->getLiteralInts()) {
|
||||
if (!$existing_var_type->hasPositiveInt()) {
|
||||
$did_match_literal_type = true;
|
||||
}
|
||||
$did_match_literal_type = true;
|
||||
|
||||
if ($existing_var_type->removeType($assertion_type->getKey())) {
|
||||
$did_remove_type = true;
|
||||
|
@ -65,7 +65,6 @@ use Psalm\Type\Atomic\TNumeric;
|
||||
use Psalm\Type\Atomic\TNumericString;
|
||||
use Psalm\Type\Atomic\TObject;
|
||||
use Psalm\Type\Atomic\TObjectWithProperties;
|
||||
use Psalm\Type\Atomic\TPositiveInt;
|
||||
use Psalm\Type\Atomic\TResource;
|
||||
use Psalm\Type\Atomic\TScalar;
|
||||
use Psalm\Type\Atomic\TString;
|
||||
@ -1669,12 +1668,6 @@ class SimpleAssertionReconciler extends Reconciler
|
||||
$existing_var_type->addType(new TIntRange($assertion_value, $atomic_type->value));
|
||||
}
|
||||
}*/
|
||||
} elseif ($atomic_type instanceof TPositiveInt) {
|
||||
if ($assertion_value > 1) {
|
||||
$did_remove_type = true;
|
||||
$existing_var_type->removeType($atomic_type->getKey());
|
||||
$existing_var_type->addType(new TIntRange($assertion_value, null));
|
||||
}
|
||||
} elseif ($atomic_type instanceof TInt) {
|
||||
$did_remove_type = true;
|
||||
$existing_var_type->removeType($atomic_type->getKey());
|
||||
@ -1775,12 +1768,6 @@ class SimpleAssertionReconciler extends Reconciler
|
||||
$existing_var_type->addType(new TIntRange($assertion_value, $atomic_type->value));
|
||||
}
|
||||
}*/
|
||||
} elseif ($atomic_type instanceof TPositiveInt) {
|
||||
$did_remove_type = true;
|
||||
$existing_var_type->removeType($atomic_type->getKey());
|
||||
if ($assertion_value >= 1) {
|
||||
$existing_var_type->addType(new TIntRange(1, $assertion_value));
|
||||
}
|
||||
} elseif ($atomic_type instanceof TInt) {
|
||||
$did_remove_type = true;
|
||||
$existing_var_type->removeType($atomic_type->getKey());
|
||||
|
@ -54,7 +54,6 @@ use Psalm\Type\Atomic\TNonEmptyString;
|
||||
use Psalm\Type\Atomic\TNull;
|
||||
use Psalm\Type\Atomic\TNumeric;
|
||||
use Psalm\Type\Atomic\TObject;
|
||||
use Psalm\Type\Atomic\TPositiveInt;
|
||||
use Psalm\Type\Atomic\TResource;
|
||||
use Psalm\Type\Atomic\TScalar;
|
||||
use Psalm\Type\Atomic\TString;
|
||||
@ -1712,12 +1711,6 @@ class SimpleNegatedAssertionReconciler extends Reconciler
|
||||
$existing_var_type->addType(new TIntRange($assertion_value, $atomic_type->value));
|
||||
}
|
||||
}*/
|
||||
} elseif ($atomic_type instanceof TPositiveInt) {
|
||||
$did_remove_type = true;
|
||||
$existing_var_type->removeType($atomic_type->getKey());
|
||||
if ($assertion_value >= 1) {
|
||||
$existing_var_type->addType(new TIntRange(1, $assertion_value));
|
||||
}
|
||||
} elseif ($atomic_type instanceof TInt) {
|
||||
$did_remove_type = true;
|
||||
$existing_var_type->removeType($atomic_type->getKey());
|
||||
@ -1818,12 +1811,6 @@ class SimpleNegatedAssertionReconciler extends Reconciler
|
||||
$existing_var_type->addType(new TIntRange($assertion_value, $atomic_type->value));
|
||||
}
|
||||
}*/
|
||||
} elseif ($atomic_type instanceof TPositiveInt) {
|
||||
if ($assertion_value > 1) {
|
||||
$did_remove_type = true;
|
||||
$existing_var_type->removeType($atomic_type->getKey());
|
||||
$existing_var_type->addType(new TIntRange($assertion_value, null));
|
||||
}
|
||||
} elseif ($atomic_type instanceof TInt) {
|
||||
$did_remove_type = true;
|
||||
$existing_var_type->removeType($atomic_type->getKey());
|
||||
|
@ -47,7 +47,6 @@ use Psalm\Type\Atomic\TNull;
|
||||
use Psalm\Type\Atomic\TNumericString;
|
||||
use Psalm\Type\Atomic\TObject;
|
||||
use Psalm\Type\Atomic\TObjectWithProperties;
|
||||
use Psalm\Type\Atomic\TPositiveInt;
|
||||
use Psalm\Type\Atomic\TScalar;
|
||||
use Psalm\Type\Atomic\TString;
|
||||
use Psalm\Type\Atomic\TTemplateParam;
|
||||
@ -1140,13 +1139,7 @@ class TypeCombiner
|
||||
return;
|
||||
}
|
||||
|
||||
$had_zero = isset($combination->ints['int(0)']);
|
||||
|
||||
if ($type instanceof TLiteralInt) {
|
||||
if ($type->value === 0) {
|
||||
$had_zero = true;
|
||||
}
|
||||
|
||||
if ($combination->ints !== null && count($combination->ints) < $literal_limit) {
|
||||
$combination->ints[$type_key] = $type;
|
||||
} else {
|
||||
@ -1179,40 +1172,12 @@ class TypeCombiner
|
||||
|
||||
if (!isset($combination->value_types['int'])) {
|
||||
$combination->value_types['int'] = $all_nonnegative
|
||||
? new TPositiveInt()
|
||||
? new TIntRange(1, null)
|
||||
: new TNonspecificLiteralInt();
|
||||
} elseif ($combination->value_types['int'] instanceof TPositiveInt
|
||||
&& !$all_nonnegative
|
||||
) {
|
||||
$combination->value_types['int'] = new TInt();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ($type instanceof TPositiveInt) {
|
||||
if ($combination->ints) {
|
||||
$all_nonnegative = !array_filter(
|
||||
$combination->ints,
|
||||
fn($int): bool => $int->value < 0
|
||||
);
|
||||
|
||||
if ($all_nonnegative) {
|
||||
$combination->value_types['int'] = $type;
|
||||
} else {
|
||||
$combination->value_types['int'] = new TInt();
|
||||
}
|
||||
} elseif (!isset($combination->value_types['int'])) {
|
||||
$combination->value_types['int'] = $type;
|
||||
} elseif ($combination->value_types['int'] instanceof TIntRange) {
|
||||
//if we already had a range, we ensure the min is no higher than 1
|
||||
$combination->value_types['int']->min_bound = TIntRange::getNewLowestBound(
|
||||
$combination->value_types['int']->min_bound,
|
||||
1
|
||||
);
|
||||
$combination->value_types['int']->max_bound = null;
|
||||
} elseif (get_class($combination->value_types['int']) !== get_class($type)) {
|
||||
$combination->value_types['int'] = new TInt();
|
||||
}
|
||||
} elseif ($type instanceof TNonspecificLiteralInt) {
|
||||
if ($type instanceof TNonspecificLiteralInt) {
|
||||
if ($combination->ints || !isset($combination->value_types['int'])) {
|
||||
$combination->value_types['int'] = $type;
|
||||
} elseif (isset($combination->value_types['int'])
|
||||
@ -1238,9 +1203,6 @@ class TypeCombiner
|
||||
if ($old_type instanceof TIntRange) {
|
||||
$type->min_bound = TIntRange::getNewLowestBound($old_type->min_bound, $type->min_bound);
|
||||
$type->max_bound = TIntRange::getNewHighestBound($old_type->max_bound, $type->max_bound);
|
||||
} elseif ($old_type instanceof TPositiveInt) {
|
||||
$type->min_bound = TIntRange::getNewLowestBound($type->min_bound, 0);
|
||||
$type->max_bound = null;
|
||||
} else {
|
||||
$type = new TInt();
|
||||
}
|
||||
@ -1252,18 +1214,6 @@ class TypeCombiner
|
||||
|
||||
$combination->ints = null;
|
||||
}
|
||||
|
||||
if ($had_zero
|
||||
&& isset($combination->value_types['int'])
|
||||
&& $combination->value_types['int'] instanceof TPositiveInt
|
||||
) {
|
||||
if ($combination->ints === null) {
|
||||
$combination->ints = ['int(0)' => new TLiteralInt(0)];
|
||||
} elseif ($type instanceof TLiteralInt && $type->value < 0) {
|
||||
$combination->ints = null;
|
||||
$combination->value_types['int'] = new TInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -55,7 +55,6 @@ use Psalm\Type\Atomic\TNonEmptyList;
|
||||
use Psalm\Type\Atomic\TNull;
|
||||
use Psalm\Type\Atomic\TObject;
|
||||
use Psalm\Type\Atomic\TObjectWithProperties;
|
||||
use Psalm\Type\Atomic\TPositiveInt;
|
||||
use Psalm\Type\Atomic\TTemplateIndexedAccess;
|
||||
use Psalm\Type\Atomic\TTemplateKeyOf;
|
||||
use Psalm\Type\Atomic\TTemplateParam;
|
||||
@ -857,10 +856,6 @@ class TypeParser
|
||||
return new TInt();
|
||||
}
|
||||
|
||||
if ($min_bound === 1 && $max_bound === null) {
|
||||
return new TPositiveInt();
|
||||
}
|
||||
|
||||
return new TIntRange($min_bound, $max_bound);
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,6 @@ use Psalm\Type\Atomic\TNumeric;
|
||||
use Psalm\Type\Atomic\TNumericString;
|
||||
use Psalm\Type\Atomic\TObject;
|
||||
use Psalm\Type\Atomic\TObjectWithProperties;
|
||||
use Psalm\Type\Atomic\TPositiveInt;
|
||||
use Psalm\Type\Atomic\TResource;
|
||||
use Psalm\Type\Atomic\TScalar;
|
||||
use Psalm\Type\Atomic\TSingleLetter;
|
||||
@ -194,15 +193,6 @@ abstract class Type
|
||||
return new Union([$type]);
|
||||
}
|
||||
|
||||
/** @deprecated will be removed in Psalm 5 */
|
||||
public static function getPositiveInt(bool $from_calculation = false): Union
|
||||
{
|
||||
$union = new Union([new TPositiveInt()]);
|
||||
$union->from_calculation = $from_calculation;
|
||||
|
||||
return $union;
|
||||
}
|
||||
|
||||
public static function getNonEmptyLowercaseString(): Union
|
||||
{
|
||||
$type = new TNonEmptyLowercaseString();
|
||||
|
@ -58,7 +58,6 @@ use Psalm\Type\Atomic\TNumeric;
|
||||
use Psalm\Type\Atomic\TNumericString;
|
||||
use Psalm\Type\Atomic\TObject;
|
||||
use Psalm\Type\Atomic\TObjectWithProperties;
|
||||
use Psalm\Type\Atomic\TPositiveInt;
|
||||
use Psalm\Type\Atomic\TResource;
|
||||
use Psalm\Type\Atomic\TScalar;
|
||||
use Psalm\Type\Atomic\TString;
|
||||
@ -701,10 +700,6 @@ abstract class Atomic implements TypeNode
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this instanceof TPositiveInt) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this instanceof TLiteralClassString) {
|
||||
return true;
|
||||
}
|
||||
|
@ -122,10 +122,6 @@ class TIntRange extends TInt
|
||||
return $int_atomic;
|
||||
}
|
||||
|
||||
if ($int_atomic instanceof TPositiveInt) {
|
||||
return new TIntRange(1, null);
|
||||
}
|
||||
|
||||
if ($int_atomic instanceof TLiteralInt) {
|
||||
return new TIntRange($int_atomic->value, $int_atomic->value);
|
||||
}
|
||||
|
@ -1,36 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Psalm\Type\Atomic;
|
||||
|
||||
/**
|
||||
* Denotes an int that is also positive (strictly > 0)
|
||||
* @deprecated will be removed in Psalm 5
|
||||
*/
|
||||
class TPositiveInt extends TInt
|
||||
{
|
||||
public function getId(bool $exact = true, bool $nested = false): string
|
||||
{
|
||||
return 'positive-int';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return false
|
||||
*/
|
||||
public function canBeFullyExpressedInPhp(int $analysis_php_version_id): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<lowercase-string, string> $aliased_classes
|
||||
*
|
||||
*/
|
||||
public function toNamespacedString(
|
||||
?string $namespace,
|
||||
array $aliased_classes,
|
||||
?string $this_class,
|
||||
bool $use_phpdoc_format
|
||||
): string {
|
||||
return $use_phpdoc_format ? 'int' : 'positive-int';
|
||||
}
|
||||
}
|
@ -38,7 +38,6 @@ use Psalm\Type\Atomic\TNamedObject;
|
||||
use Psalm\Type\Atomic\TNonEmptyLowercaseString;
|
||||
use Psalm\Type\Atomic\TNonspecificLiteralInt;
|
||||
use Psalm\Type\Atomic\TNonspecificLiteralString;
|
||||
use Psalm\Type\Atomic\TPositiveInt;
|
||||
use Psalm\Type\Atomic\TString;
|
||||
use Psalm\Type\Atomic\TTemplateParam;
|
||||
use Psalm\Type\Atomic\TTemplateParamClass;
|
||||
@ -856,11 +855,6 @@ class Union implements TypeNode
|
||||
|| array_filter($this->types, fn(Atomic $type) => $type instanceof TIntRange);
|
||||
}
|
||||
|
||||
public function hasPositiveInt(): bool
|
||||
{
|
||||
return isset($this->types['int']) && $this->types['int'] instanceof TPositiveInt;
|
||||
}
|
||||
|
||||
public function hasArrayKey(): bool
|
||||
{
|
||||
return isset($this->types['array-key']);
|
||||
|
@ -1018,7 +1018,7 @@ class ArrayAccessTest extends TestCase
|
||||
|
||||
if ($foo !== null) {}'
|
||||
],
|
||||
'accessKnownArrayWithPositiveInt' => [
|
||||
'SKIPPED-accessKnownArrayWithPositiveInt' => [
|
||||
'code' => '<?php
|
||||
/** @param list<int> $arr */
|
||||
function foo(array $arr) : void {
|
||||
|
@ -64,6 +64,7 @@ class ForTest extends TestCase
|
||||
'preventNegativeZeroScrewingThingsUp' => [
|
||||
'code' => '<?php
|
||||
function foo() : void {
|
||||
/** @var array<int, int> $v */
|
||||
$v = [1 => 0];
|
||||
for ($d = 0; $d <= 10; $d++) {
|
||||
for ($k = -$d; $k <= $d; $k += 2) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user