From c61f66d973ba4827e6a0a5df462716329de5267d Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 11 Feb 2021 15:40:37 +0000 Subject: [PATCH] Removed ext-ds dependency --- composer.json | 1 - composer.lock | 3 +- phpstan.neon.dist | 1 - src/PocketMine.php | 1 - src/crafting/CraftingManager.php | 12 ++-- src/crafting/FurnaceRecipeManager.php | 12 ++-- src/entity/effect/EffectManager.php | 26 ++++---- src/inventory/BaseInventory.php | 10 +-- src/inventory/Inventory.php | 8 +-- src/inventory/PlayerInventory.php | 14 ++--- src/item/Item.php | 61 +++++++++--------- src/network/mcpe/NetworkSession.php | 8 +-- src/permission/Permissible.php | 8 +-- src/permission/PermissibleBase.php | 14 ++--- src/permission/PermissibleDelegateTrait.php | 8 +-- src/scheduler/TaskScheduler.php | 8 +-- src/utils/DestructorCallbackTrait.php | 12 ++-- src/utils/ObjectSet.php | 70 +++++++++++++++++++++ tests/phpstan/configs/phpstan-bugs.neon | 60 ++++++++++++++++++ 19 files changed, 231 insertions(+), 106 deletions(-) create mode 100644 src/utils/ObjectSet.php diff --git a/composer.json b/composer.json index 676553a74..8c82ca36e 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,6 @@ "ext-ctype": "*", "ext-curl": "*", "ext-date": "*", - "ext-ds": "^1.2.7", "ext-gmp": "*", "ext-hash": "*", "ext-igbinary": "^3.0.1", diff --git a/composer.lock b/composer.lock index 52454f969..8129a33e7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "18b4c55f8ac6014140b7fa575b6795bb", + "content-hash": "2032ba311a20918843c0cbffdc6058e4", "packages": [ { "name": "adhocore/json-comment", @@ -3333,7 +3333,6 @@ "ext-ctype": "*", "ext-curl": "*", "ext-date": "*", - "ext-ds": "^1.2.7", "ext-gmp": "*", "ext-hash": "*", "ext-igbinary": "^3.0.1", diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 6ac4a2b95..4175fb24d 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -2,7 +2,6 @@ includes: - tests/phpstan/configs/actual-problems.neon - tests/phpstan/configs/check-explicit-mixed-baseline.neon - tests/phpstan/configs/com-dotnet-magic.neon - - tests/phpstan/configs/ds-bugs.neon - tests/phpstan/configs/gc-hacks.neon - tests/phpstan/configs/impossible-generics.neon - tests/phpstan/configs/l7-baseline.neon diff --git a/src/PocketMine.php b/src/PocketMine.php index 5740b20cf..09908d97d 100644 --- a/src/PocketMine.php +++ b/src/PocketMine.php @@ -79,7 +79,6 @@ namespace pocketmine { "crypto" => "php-crypto", "ctype" => "ctype", "date" => "Date", - "ds" => "Data Structures", "gmp" => "GMP", "hash" => "Hash", "igbinary" => "igbinary", diff --git a/src/crafting/CraftingManager.php b/src/crafting/CraftingManager.php index b6720a3e9..709480506 100644 --- a/src/crafting/CraftingManager.php +++ b/src/crafting/CraftingManager.php @@ -23,9 +23,9 @@ declare(strict_types=1); namespace pocketmine\crafting; -use Ds\Set; use pocketmine\item\Item; use pocketmine\utils\DestructorCallbackTrait; +use pocketmine\utils\ObjectSet; use function json_encode; use function usort; @@ -41,13 +41,13 @@ class CraftingManager{ protected $furnaceRecipeManager; /** - * @var Set - * @phpstan-var Set<\Closure() : void> + * @var ObjectSet + * @phpstan-var ObjectSet<\Closure() : void> */ private $recipeRegisteredCallbacks; public function __construct(){ - $this->recipeRegisteredCallbacks = new Set(); + $this->recipeRegisteredCallbacks = new ObjectSet(); $this->furnaceRecipeManager = new FurnaceRecipeManager(); $this->furnaceRecipeManager->getRecipeRegisteredCallbacks()->add(function(FurnaceRecipe $recipe) : void{ foreach($this->recipeRegisteredCallbacks as $callback){ @@ -56,8 +56,8 @@ class CraftingManager{ }); } - /** @phpstan-return Set<\Closure() : void> */ - public function getRecipeRegisteredCallbacks() : Set{ return $this->recipeRegisteredCallbacks; } + /** @phpstan-return ObjectSet<\Closure() : void> */ + public function getRecipeRegisteredCallbacks() : ObjectSet{ return $this->recipeRegisteredCallbacks; } /** * Function used to arrange Shapeless Recipe ingredient lists into a consistent order. diff --git a/src/crafting/FurnaceRecipeManager.php b/src/crafting/FurnaceRecipeManager.php index 18b520476..9cb9c6eef 100644 --- a/src/crafting/FurnaceRecipeManager.php +++ b/src/crafting/FurnaceRecipeManager.php @@ -23,27 +23,27 @@ declare(strict_types=1); namespace pocketmine\crafting; -use Ds\Set; use pocketmine\item\Item; +use pocketmine\utils\ObjectSet; final class FurnaceRecipeManager{ /** @var FurnaceRecipe[] */ protected $furnaceRecipes = []; /** - * @var Set - * @phpstan-var Set<\Closure(FurnaceRecipe) : void> + * @var ObjectSet + * @phpstan-var ObjectSet<\Closure(FurnaceRecipe) : void> */ private $recipeRegisteredCallbacks; public function __construct(){ - $this->recipeRegisteredCallbacks = new Set(); + $this->recipeRegisteredCallbacks = new ObjectSet(); } /** - * @phpstan-return Set<\Closure(FurnaceRecipe) : void> + * @phpstan-return ObjectSet<\Closure(FurnaceRecipe) : void> */ - public function getRecipeRegisteredCallbacks() : Set{ + public function getRecipeRegisteredCallbacks() : ObjectSet{ return $this->recipeRegisteredCallbacks; } diff --git a/src/entity/effect/EffectManager.php b/src/entity/effect/EffectManager.php index 93404120a..d9933d16d 100644 --- a/src/entity/effect/EffectManager.php +++ b/src/entity/effect/EffectManager.php @@ -23,11 +23,11 @@ declare(strict_types=1); namespace pocketmine\entity\effect; -use Ds\Set; use pocketmine\color\Color; use pocketmine\entity\Living; use pocketmine\event\entity\EntityEffectAddEvent; use pocketmine\event\entity\EntityEffectRemoveEvent; +use pocketmine\utils\ObjectSet; use function abs; use function count; @@ -45,21 +45,21 @@ class EffectManager{ protected $onlyAmbientEffects = false; /** - * @var \Closure[]|Set - * @phpstan-var Set<\Closure(EffectInstance, bool $replacesOldEffect) : void> + * @var \Closure[]|ObjectSet + * @phpstan-var ObjectSet<\Closure(EffectInstance, bool $replacesOldEffect) : void> */ protected $effectAddHooks; /** - * @var \Closure[]|Set - * @phpstan-var Set<\Closure(EffectInstance) : void> + * @var \Closure[]|ObjectSet + * @phpstan-var ObjectSet<\Closure(EffectInstance) : void> */ protected $effectRemoveHooks; public function __construct(Living $entity){ $this->entity = $entity; $this->bubbleColor = new Color(0, 0, 0, 0); - $this->effectAddHooks = new Set(); - $this->effectRemoveHooks = new Set(); + $this->effectAddHooks = new ObjectSet(); + $this->effectRemoveHooks = new ObjectSet(); } /** @@ -225,18 +225,18 @@ class EffectManager{ } /** - * @return \Closure[]|Set - * @phpstan-return Set<\Closure(EffectInstance, bool $replacesOldEffect) : void> + * @return \Closure[]|ObjectSet + * @phpstan-return ObjectSet<\Closure(EffectInstance, bool $replacesOldEffect) : void> */ - public function getEffectAddHooks() : Set{ + public function getEffectAddHooks() : ObjectSet{ return $this->effectAddHooks; } /** - * @return \Closure[]|Set - * @phpstan-return Set<\Closure(EffectInstance) : void> + * @return \Closure[]|ObjectSet + * @phpstan-return ObjectSet<\Closure(EffectInstance) : void> */ - public function getEffectRemoveHooks() : Set{ + public function getEffectRemoveHooks() : ObjectSet{ return $this->effectRemoveHooks; } } diff --git a/src/inventory/BaseInventory.php b/src/inventory/BaseInventory.php index 70c03f2b0..5e2ed288c 100644 --- a/src/inventory/BaseInventory.php +++ b/src/inventory/BaseInventory.php @@ -23,10 +23,10 @@ declare(strict_types=1); namespace pocketmine\inventory; -use Ds\Set; use pocketmine\item\Item; use pocketmine\item\ItemFactory; use pocketmine\player\Player; +use pocketmine\utils\ObjectSet; use function array_map; use function array_slice; use function count; @@ -46,14 +46,14 @@ abstract class BaseInventory implements Inventory{ /** @var Player[] */ protected $viewers = []; /** - * @var InventoryListener[]|Set - * @phpstan-var Set + * @var InventoryListener[]|ObjectSet + * @phpstan-var ObjectSet */ protected $listeners; public function __construct(int $size){ $this->slots = new \SplFixedArray($size); - $this->listeners = new Set(); + $this->listeners = new ObjectSet(); } /** @@ -380,7 +380,7 @@ abstract class BaseInventory implements Inventory{ return $slot >= 0 and $slot < $this->slots->getSize(); } - public function getListeners() : Set{ + public function getListeners() : ObjectSet{ return $this->listeners; } } diff --git a/src/inventory/Inventory.php b/src/inventory/Inventory.php index e2226f82f..0a5e3b766 100644 --- a/src/inventory/Inventory.php +++ b/src/inventory/Inventory.php @@ -26,9 +26,9 @@ declare(strict_types=1); */ namespace pocketmine\inventory; -use Ds\Set; use pocketmine\item\Item; use pocketmine\player\Player; +use pocketmine\utils\ObjectSet; interface Inventory{ public const MAX_STACK = 64; @@ -156,8 +156,8 @@ interface Inventory{ public function slotExists(int $slot) : bool; /** - * @return InventoryListener[]|Set - * @phpstan-return Set + * @return InventoryListener[]|ObjectSet + * @phpstan-return ObjectSet */ - public function getListeners() : Set; + public function getListeners() : ObjectSet; } diff --git a/src/inventory/PlayerInventory.php b/src/inventory/PlayerInventory.php index 07befe054..4f76ec258 100644 --- a/src/inventory/PlayerInventory.php +++ b/src/inventory/PlayerInventory.php @@ -23,10 +23,10 @@ declare(strict_types=1); namespace pocketmine\inventory; -use Ds\Set; use pocketmine\entity\Human; use pocketmine\item\Item; use pocketmine\player\Player; +use pocketmine\utils\ObjectSet; class PlayerInventory extends BaseInventory{ @@ -37,14 +37,14 @@ class PlayerInventory extends BaseInventory{ protected $itemInHandIndex = 0; /** - * @var \Closure[]|Set - * @phpstan-var Set<\Closure(int $oldIndex) : void> + * @var \Closure[]|ObjectSet + * @phpstan-var ObjectSet<\Closure(int $oldIndex) : void> */ protected $heldItemIndexChangeListeners; public function __construct(Human $player){ $this->holder = $player; - $this->heldItemIndexChangeListeners = new Set(); + $this->heldItemIndexChangeListeners = new ObjectSet(); parent::__construct(36); } @@ -97,10 +97,10 @@ class PlayerInventory extends BaseInventory{ } /** - * @return \Closure[]|Set - * @phpstan-return Set<\Closure(int $oldIndex) : void> + * @return \Closure[]|ObjectSet + * @phpstan-return ObjectSet<\Closure(int $oldIndex) : void> */ - public function getHeldItemIndexChangeListeners() : Set{ return $this->heldItemIndexChangeListeners; } + public function getHeldItemIndexChangeListeners() : ObjectSet{ return $this->heldItemIndexChangeListeners; } /** * Returns the currently-held item. diff --git a/src/item/Item.php b/src/item/Item.php index 76989bcc5..afa34d8c8 100644 --- a/src/item/Item.php +++ b/src/item/Item.php @@ -26,7 +26,6 @@ declare(strict_types=1); */ namespace pocketmine\item; -use Ds\Set; use pocketmine\block\Block; use pocketmine\block\BlockBreakInfo; use pocketmine\block\BlockToolType; @@ -86,13 +85,13 @@ class Item implements \JsonSerializable{ protected $blockEntityTag = null; /** - * @var Set|string[] - * @phpstan-var Set + * @var string[] + * @phpstan-var array */ - protected $canPlaceOn; + protected $canPlaceOn = []; /** - * @var Set|string[] - * @phpstan-var Set + * @var string[] + * @phpstan-var array */ protected $canDestroy; @@ -107,8 +106,8 @@ class Item implements \JsonSerializable{ $this->identifier = $identifier; $this->name = $name; - $this->canPlaceOn = new Set(); - $this->canDestroy = new Set(); + $this->canPlaceOn = []; + $this->canDestroy = []; $this->nbt = new CompoundTag(); } @@ -186,35 +185,39 @@ class Item implements \JsonSerializable{ } /** - * @return Set|string[] - * @phpstan-return Set + * @return string[] + * @phpstan-return array */ - public function getCanPlaceOn() : Set{ + public function getCanPlaceOn() : array{ return $this->canPlaceOn; } /** - * @param Set|string[] $canPlaceOn - * @phpstan-param Set $canPlaceOn + * @param string[] $canPlaceOn */ - public function setCanPlaceOn(Set $canPlaceOn) : void{ - $this->canPlaceOn = $canPlaceOn; + public function setCanPlaceOn(array $canPlaceOn) : void{ + $this->canPlaceOn = []; + foreach($canPlaceOn as $value){ + $this->canPlaceOn[$value] = $value; + } } /** - * @return Set|string[] - * @phpstan-return Set + * @return string[] + * @phpstan-return array */ - public function getCanDestroy() : Set{ + public function getCanDestroy() : array{ return $this->canDestroy; } /** - * @param Set|string[] $canDestroy - * @phpstan-param Set $canDestroy + * @param string[] $canDestroy */ - public function setCanDestroy(Set $canDestroy) : void{ - $this->canDestroy = $canDestroy; + public function setCanDestroy(array $canDestroy) : void{ + $this->canDestroy = []; + foreach($canDestroy as $value){ + $this->canDestroy[$value] = $value; + } } /** @@ -294,20 +297,20 @@ class Item implements \JsonSerializable{ $this->blockEntityTag = $tag->getCompoundTag(self::TAG_BLOCK_ENTITY_TAG); - $this->canPlaceOn = new Set(); + $this->canPlaceOn = []; $canPlaceOn = $tag->getListTag("CanPlaceOn"); if($canPlaceOn !== null){ /** @var StringTag $entry */ foreach($canPlaceOn as $entry){ - $this->canPlaceOn->add($entry->getValue()); + $this->canPlaceOn[$entry->getValue()] = $entry->getValue(); } } - $this->canDestroy = new Set(); + $this->canDestroy = []; $canDestroy = $tag->getListTag("CanDestroy"); if($canDestroy !== null){ /** @var StringTag $entry */ foreach($canDestroy as $entry){ - $this->canDestroy->add($entry->getValue()); + $this->canDestroy[$entry->getValue()] = $entry->getValue(); } } } @@ -349,7 +352,7 @@ class Item implements \JsonSerializable{ $tag->setTag(self::TAG_BLOCK_ENTITY_TAG, clone $blockData) : $tag->removeTag(self::TAG_BLOCK_ENTITY_TAG); - if(!$this->canPlaceOn->isEmpty()){ + if(count($this->canPlaceOn) > 0){ $canPlaceOn = new ListTag(); foreach($this->canPlaceOn as $item){ $canPlaceOn->push(new StringTag($item)); @@ -358,7 +361,7 @@ class Item implements \JsonSerializable{ }else{ $tag->removeTag("CanPlaceOn"); } - if(!$this->canDestroy->isEmpty()){ + if(count($this->canDestroy) > 0){ $canDestroy = new ListTag(); foreach($this->canDestroy as $item){ $canDestroy->push(new StringTag($item)); @@ -691,7 +694,5 @@ class Item implements \JsonSerializable{ if($this->blockEntityTag !== null){ $this->blockEntityTag = clone $this->blockEntityTag; } - $this->canPlaceOn = $this->canPlaceOn->copy(); - $this->canDestroy = $this->canDestroy->copy(); } } diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index cc33695e6..501c5f1be 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -23,7 +23,6 @@ declare(strict_types=1); namespace pocketmine\network\mcpe; -use Ds\Set; use Mdanter\Ecc\Crypto\Key\PublicKeyInterface; use pocketmine\data\bedrock\EffectIdMap; use pocketmine\entity\Attribute; @@ -103,6 +102,7 @@ use pocketmine\player\PlayerInfo; use pocketmine\player\XboxLivePlayerInfo; use pocketmine\Server; use pocketmine\timings\Timings; +use pocketmine\utils\ObjectSet; use pocketmine\utils\TextFormat; use pocketmine\utils\Utils; use pocketmine\world\Position; @@ -184,8 +184,8 @@ class NetworkSession{ private $broadcaster; /** - * @var \Closure[]|Set - * @phpstan-var Set<\Closure() : void> + * @var \Closure[]|ObjectSet + * @phpstan-var ObjectSet<\Closure() : void> */ private $disposeHooks; @@ -203,7 +203,7 @@ class NetworkSession{ $this->compressor = $compressor; $this->packetPool = $packetPool; - $this->disposeHooks = new Set(); + $this->disposeHooks = new ObjectSet(); $this->connectTime = time(); diff --git a/src/permission/Permissible.php b/src/permission/Permissible.php index 5fca2b14f..81fc23fea 100644 --- a/src/permission/Permissible.php +++ b/src/permission/Permissible.php @@ -23,8 +23,8 @@ declare(strict_types=1); namespace pocketmine\permission; -use Ds\Set; use pocketmine\plugin\Plugin; +use pocketmine\utils\ObjectSet; interface Permissible{ @@ -73,10 +73,10 @@ interface Permissible{ public function recalculatePermissions() : array; /** - * @return Set|\Closure[] - * @phpstan-return Set<\Closure(array $changedPermissionsOldValues) : void> + * @return ObjectSet|\Closure[] + * @phpstan-return ObjectSet<\Closure(array $changedPermissionsOldValues) : void> */ - public function getPermissionRecalculationCallbacks() : Set; + public function getPermissionRecalculationCallbacks() : ObjectSet; /** * @return PermissionAttachmentInfo[] diff --git a/src/permission/PermissibleBase.php b/src/permission/PermissibleBase.php index 0f8f82163..a1b43bfd3 100644 --- a/src/permission/PermissibleBase.php +++ b/src/permission/PermissibleBase.php @@ -23,10 +23,10 @@ declare(strict_types=1); namespace pocketmine\permission; -use Ds\Set; use pocketmine\plugin\Plugin; use pocketmine\plugin\PluginException; use pocketmine\timings\Timings; +use pocketmine\utils\ObjectSet; use function count; use function spl_object_id; @@ -44,8 +44,8 @@ class PermissibleBase implements Permissible{ private $permissions = []; /** - * @var Set|\Closure[] - * @phpstan-var Set<\Closure(array $changedPermissionsOldValues) : void> + * @var ObjectSet|\Closure[] + * @phpstan-var ObjectSet<\Closure(array $changedPermissionsOldValues) : void> */ private $permissionRecalculationCallbacks; @@ -54,7 +54,7 @@ class PermissibleBase implements Permissible{ * @phpstan-param array $basePermissions */ public function __construct(array $basePermissions){ - $this->permissionRecalculationCallbacks = new Set(); + $this->permissionRecalculationCallbacks = new ObjectSet(); //TODO: we can't setBasePermission here directly due to bad architecture that causes recalculatePermissions to explode //so, this hack has to be done here to prevent permission recalculations until it's fixed... @@ -198,10 +198,10 @@ class PermissibleBase implements Permissible{ } /** - * @return \Closure[]|Set - * @phpstan-return Set<\Closure(array $changedPermissionsOldValues) : void> + * @return \Closure[]|ObjectSet + * @phpstan-return ObjectSet<\Closure(array $changedPermissionsOldValues) : void> */ - public function getPermissionRecalculationCallbacks() : Set{ return $this->permissionRecalculationCallbacks; } + public function getPermissionRecalculationCallbacks() : ObjectSet{ return $this->permissionRecalculationCallbacks; } /** * @return PermissionAttachmentInfo[] diff --git a/src/permission/PermissibleDelegateTrait.php b/src/permission/PermissibleDelegateTrait.php index e38762efe..be3e8da91 100644 --- a/src/permission/PermissibleDelegateTrait.php +++ b/src/permission/PermissibleDelegateTrait.php @@ -23,8 +23,8 @@ declare(strict_types=1); namespace pocketmine\permission; -use Ds\Set; use pocketmine\plugin\Plugin; +use pocketmine\utils\ObjectSet; trait PermissibleDelegateTrait{ @@ -72,10 +72,10 @@ trait PermissibleDelegateTrait{ } /** - * @return Set|\Closure[] - * @phpstan-return Set<\Closure(array $changedPermissionsOldValues) : void> + * @return ObjectSet|\Closure[] + * @phpstan-return ObjectSet<\Closure(array $changedPermissionsOldValues) : void> */ - public function getPermissionRecalculationCallbacks() : Set{ + public function getPermissionRecalculationCallbacks() : ObjectSet{ return $this->perm->getPermissionRecalculationCallbacks(); } diff --git a/src/scheduler/TaskScheduler.php b/src/scheduler/TaskScheduler.php index 32d2d2784..9b1eb9c9f 100644 --- a/src/scheduler/TaskScheduler.php +++ b/src/scheduler/TaskScheduler.php @@ -27,7 +27,7 @@ declare(strict_types=1); namespace pocketmine\scheduler; -use Ds\Set; +use pocketmine\utils\ObjectSet; use pocketmine\utils\ReversePriorityQueue; class TaskScheduler{ @@ -44,8 +44,8 @@ class TaskScheduler{ protected $queue; /** - * @var Set|TaskHandler[] - * @phpstan-var Set + * @var ObjectSet|TaskHandler[] + * @phpstan-var ObjectSet */ protected $tasks; @@ -55,7 +55,7 @@ class TaskScheduler{ public function __construct(?string $owner = null){ $this->owner = $owner; $this->queue = new ReversePriorityQueue(); - $this->tasks = new Set(); + $this->tasks = new ObjectSet(); } public function scheduleTask(Task $task) : TaskHandler{ diff --git a/src/utils/DestructorCallbackTrait.php b/src/utils/DestructorCallbackTrait.php index 63e3e3402..3653cfa05 100644 --- a/src/utils/DestructorCallbackTrait.php +++ b/src/utils/DestructorCallbackTrait.php @@ -23,8 +23,6 @@ declare(strict_types=1); namespace pocketmine\utils; -use Ds\Set; - /** * This trait provides destructor callback functionality to objects which use it. This enables a weakmap-like system * to function without actually having weak maps. @@ -32,14 +30,14 @@ use Ds\Set; */ trait DestructorCallbackTrait{ /** - * @var Set - * @phpstan-var Set<\Closure() : void>|null + * @var ObjectSet + * @phpstan-var ObjectSet<\Closure() : void>|null */ private $destructorCallbacks = null; - /** @phpstan-return Set<\Closure() : void> */ - public function getDestructorCallbacks() : Set{ - return $this->destructorCallbacks === null ? ($this->destructorCallbacks = new Set()) : $this->destructorCallbacks; + /** @phpstan-return ObjectSet<\Closure() : void> */ + public function getDestructorCallbacks() : ObjectSet{ + return $this->destructorCallbacks === null ? ($this->destructorCallbacks = new ObjectSet()) : $this->destructorCallbacks; } public function __destruct(){ diff --git a/src/utils/ObjectSet.php b/src/utils/ObjectSet.php new file mode 100644 index 000000000..adb0ad1c2 --- /dev/null +++ b/src/utils/ObjectSet.php @@ -0,0 +1,70 @@ + + */ +final class ObjectSet implements \IteratorAggregate{ + /** + * @var object[] + * @phpstan-var array + */ + private array $objects = []; + + /** @phpstan-param T $object */ + public function add(object $object) : void{ + $this->objects[spl_object_id($object)] = $object; + } + + /** @phpstan-param T $object */ + public function remove(object $object) : void{ + unset($this->objects[spl_object_id($object)]); + } + + public function clear() : void{ + $this->objects = []; + } + + public function contains(object $object) : bool{ + return array_key_exists(spl_object_id($object), $this->objects); + } + + /** @phpstan-return \ArrayIterator */ + public function getIterator() : \ArrayIterator{ + return new \ArrayIterator($this->objects); + } + + /** + * @return object[] + * @phpstan-return array + */ + public function toArray() : array{ + return $this->objects; + } +} diff --git a/tests/phpstan/configs/phpstan-bugs.neon b/tests/phpstan/configs/phpstan-bugs.neon index 815c53ec0..1b42267f8 100644 --- a/tests/phpstan/configs/phpstan-bugs.neon +++ b/tests/phpstan/configs/phpstan-bugs.neon @@ -15,11 +15,71 @@ parameters: count: 3 path: ../../../src/command/CommandReader.php + - + message: "#^Property pocketmine\\\\crafting\\\\CraftingManager\\:\\:\\$recipeRegisteredCallbacks \\(pocketmine\\\\utils\\\\ObjectSet\\\\) does not accept pocketmine\\\\utils\\\\ObjectSet\\\\.$#" + count: 1 + path: ../../../src/crafting/CraftingManager.php + + - + message: "#^Method pocketmine\\\\crafting\\\\CraftingManager\\:\\:getDestructorCallbacks\\(\\) should return pocketmine\\\\utils\\\\ObjectSet\\ but returns pocketmine\\\\utils\\\\ObjectSet\\\\|pocketmine\\\\utils\\\\ObjectSet\\\\.$#" + count: 1 + path: ../../../src/crafting/CraftingManager.php + + - + message: "#^Property pocketmine\\\\crafting\\\\CraftingManager\\:\\:\\$destructorCallbacks \\(pocketmine\\\\utils\\\\ObjectSet\\\\|null\\) does not accept pocketmine\\\\utils\\\\ObjectSet\\\\.$#" + count: 1 + path: ../../../src/crafting/CraftingManager.php + + - + message: "#^Property pocketmine\\\\crafting\\\\FurnaceRecipeManager\\:\\:\\$recipeRegisteredCallbacks \\(pocketmine\\\\utils\\\\ObjectSet\\\\) does not accept pocketmine\\\\utils\\\\ObjectSet\\\\.$#" + count: 1 + path: ../../../src/crafting/FurnaceRecipeManager.php + + - + message: "#^Undefined variable\\: \\$blockstate$#" + count: 1 + path: ../../../src/data/bedrock/blockstate/BlockStateDeserializerR13.php + + - + message: "#^Property pocketmine\\\\entity\\\\effect\\\\EffectManager\\:\\:\\$effectAddHooks \\(pocketmine\\\\utils\\\\ObjectSet\\\\) does not accept pocketmine\\\\utils\\\\ObjectSet\\\\.$#" + count: 1 + path: ../../../src/entity/effect/EffectManager.php + + - + message: "#^Property pocketmine\\\\entity\\\\effect\\\\EffectManager\\:\\:\\$effectRemoveHooks \\(pocketmine\\\\utils\\\\ObjectSet\\\\) does not accept pocketmine\\\\utils\\\\ObjectSet\\\\.$#" + count: 1 + path: ../../../src/entity/effect/EffectManager.php + - message: "#^Call to function assert\\(\\) with false and 'unknown hit type' will always evaluate to false\\.$#" count: 1 path: ../../../src/entity/projectile/Projectile.php + - + message: "#^Property pocketmine\\\\inventory\\\\BaseInventory\\:\\:\\$listeners \\(pocketmine\\\\utils\\\\ObjectSet\\\\) does not accept pocketmine\\\\utils\\\\ObjectSet\\\\.$#" + count: 1 + path: ../../../src/inventory/BaseInventory.php + + - + message: "#^Property pocketmine\\\\inventory\\\\PlayerInventory\\:\\:\\$heldItemIndexChangeListeners \\(pocketmine\\\\utils\\\\ObjectSet\\\\) does not accept pocketmine\\\\utils\\\\ObjectSet\\\\.$#" + count: 1 + path: ../../../src/inventory/PlayerInventory.php + + - + message: "#^Property pocketmine\\\\network\\\\mcpe\\\\NetworkSession\\:\\:\\$disposeHooks \\(pocketmine\\\\utils\\\\ObjectSet\\\\) does not accept pocketmine\\\\utils\\\\ObjectSet\\\\.$#" + count: 1 + path: ../../../src/network/mcpe/NetworkSession.php + + - + message: "#^Property pocketmine\\\\permission\\\\PermissibleBase\\:\\:\\$permissionRecalculationCallbacks \\(pocketmine\\\\utils\\\\ObjectSet\\\\)\\: void\\>\\) does not accept pocketmine\\\\utils\\\\ObjectSet\\\\.$#" + count: 1 + path: ../../../src/permission/PermissibleBase.php + + - + message: "#^Property pocketmine\\\\scheduler\\\\TaskScheduler\\:\\:\\$tasks \\(pocketmine\\\\utils\\\\ObjectSet\\\\) does not accept pocketmine\\\\utils\\\\ObjectSet\\\\.$#" + count: 1 + path: ../../../src/scheduler/TaskScheduler.php + - message: "#^Strict comparison using \\=\\=\\= between string and false will always evaluate to false\\.$#" count: 1