Skip to content

Commit

Permalink
remove TPositiveInt
Browse files Browse the repository at this point in the history
  • Loading branch information
orklah committed Jan 23, 2022
1 parent 7c4f080 commit 63b802b
Show file tree
Hide file tree
Showing 28 changed files with 144 additions and 418 deletions.
237 changes: 119 additions & 118 deletions 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
Expand Down
2 changes: 1 addition & 1 deletion docs/running_psalm/plugins/plugins_type_system.md
Expand Up @@ -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

Expand Down
Expand Up @@ -147,7 +147,7 @@ public static function analyze(
$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);
}

Expand Down Expand Up @@ -235,7 +235,7 @@ public static function analyze(
$item_value_type ?? Type::getMixed(),
]);

/** @psalm-suppress PossiblyInvalidPropertyAssignmentValue */
/** @psalm-suppress InvalidPropertyAssignmentValue */
$array_type->count = count($array_creation_info->property_types);

$stmt_type = new Union([
Expand Down
Expand Up @@ -40,7 +40,6 @@
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;
Expand Down Expand Up @@ -728,11 +727,11 @@ private static function analyzeOperands(
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;
Expand Down Expand Up @@ -772,17 +771,14 @@ private static function analyzeOperands(
}
} 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
);
}
Expand Down
Expand Up @@ -41,7 +41,6 @@
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;

Expand Down Expand Up @@ -373,15 +372,15 @@ private static function getReturnTypeFromCallMapWithArgs(
return new Union([
$atomic_types['array']->count !== null
? new TLiteralInt($atomic_types['array']->count)
: new TPositiveInt
: new TIntRange(1, null)
]);
}

if ($atomic_types['array'] instanceof TNonEmptyList) {
return new Union([
$atomic_types['array']->count !== null
? new TLiteralInt($atomic_types['array']->count)
: new TPositiveInt
: new TIntRange(1, null)
]);
}

Expand Down Expand Up @@ -422,8 +421,7 @@ private static function getReturnTypeFromCallMapWithArgs(
}

return new Union([
new TLiteralInt(0),
new TPositiveInt
new TIntRange(0, null)
]);
}
}
Expand Down
Expand Up @@ -72,7 +72,6 @@
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;
Expand Down Expand Up @@ -891,11 +890,6 @@ private static function checkLiteralIntArrayOffset(
$found_match = true;
break;
}

if ($offset_type_part instanceof TPositiveInt) {
$found_match = true;
break;
}
}

if (!$found_match) {
Expand Down
Expand Up @@ -16,7 +16,6 @@
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;

Expand Down Expand Up @@ -81,12 +80,6 @@ public static function analyze(
}
}

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;
Expand Down

0 comments on commit 63b802b

Please sign in to comment.