diff --git a/src/event/entity/EntityDeathEvent.php b/src/event/entity/EntityDeathEvent.php index 65aef71d0..c9114d0b7 100644 --- a/src/event/entity/EntityDeathEvent.php +++ b/src/event/entity/EntityDeathEvent.php @@ -25,6 +25,7 @@ namespace pocketmine\event\entity; use pocketmine\entity\Living; use pocketmine\item\Item; +use pocketmine\utils\Utils; /** * @phpstan-extends EntityEvent @@ -62,6 +63,7 @@ class EntityDeathEvent extends EntityEvent{ * @param Item[] $drops */ public function setDrops(array $drops) : void{ + Utils::validateArrayValueType($drops, function(Item $_) : void{}); $this->drops = $drops; } diff --git a/src/event/entity/EntityExplodeEvent.php b/src/event/entity/EntityExplodeEvent.php index e9b6bc3ad..6daf923cc 100644 --- a/src/event/entity/EntityExplodeEvent.php +++ b/src/event/entity/EntityExplodeEvent.php @@ -27,6 +27,7 @@ use pocketmine\block\Block; use pocketmine\entity\Entity; use pocketmine\event\Cancellable; use pocketmine\event\CancellableTrait; +use pocketmine\utils\Utils; use pocketmine\world\Position; /** @@ -70,6 +71,7 @@ class EntityExplodeEvent extends EntityEvent implements Cancellable{ * @param Block[] $blocks */ public function setBlockList(array $blocks) : void{ + Utils::validateArrayValueType($blocks, function(Block $_) : void{}); $this->blocks = $blocks; } diff --git a/src/event/player/PlayerChatEvent.php b/src/event/player/PlayerChatEvent.php index c385a360a..7e339d04b 100644 --- a/src/event/player/PlayerChatEvent.php +++ b/src/event/player/PlayerChatEvent.php @@ -29,6 +29,8 @@ use pocketmine\event\CancellableTrait; use pocketmine\permission\PermissionManager; use pocketmine\player\Player; use pocketmine\Server; +use pocketmine\utils\Utils; +use function array_values; use function spl_object_id; /** @@ -100,6 +102,7 @@ class PlayerChatEvent extends PlayerEvent implements Cancellable{ * @param CommandSender[] $recipients */ public function setRecipients(array $recipients) : void{ + Utils::validateArrayValueType($recipients, function(CommandSender $_) : void{}); $this->recipients = $recipients; } } diff --git a/src/network/query/QueryInfo.php b/src/network/query/QueryInfo.php index 0e3dbde9a..47e95eeda 100644 --- a/src/network/query/QueryInfo.php +++ b/src/network/query/QueryInfo.php @@ -27,6 +27,7 @@ use pocketmine\player\Player; use pocketmine\plugin\Plugin; use pocketmine\Server; use pocketmine\utils\Binary; +use pocketmine\utils\Utils; use function chr; use function count; use function str_replace; @@ -127,6 +128,7 @@ final class QueryInfo{ * @param Plugin[] $plugins */ public function setPlugins(array $plugins) : void{ + Utils::validateArrayValueType($plugins, function(Plugin $_) : void{}); $this->plugins = $plugins; $this->destroyCache(); } @@ -142,6 +144,7 @@ final class QueryInfo{ * @param Player[] $players */ public function setPlayerList(array $players) : void{ + Utils::validateArrayValueType($players, function(Player $_) : void{}); $this->players = $players; $this->destroyCache(); } diff --git a/src/utils/Utils.php b/src/utils/Utils.php index 565cb2abb..9e6da965e 100644 --- a/src/utils/Utils.php +++ b/src/utils/Utils.php @@ -501,6 +501,21 @@ class Utils{ } } + /** + * @phpstan-template TMemberType + * @phpstan-param array $array + * @phpstan-param \Closure(TMemberType) : void $validator + */ + public static function validateArrayValueType(array $array, \Closure $validator) : void{ + foreach($array as $k => $v){ + try{ + $validator($v); + }catch(\TypeError $e){ + throw new \TypeError("Incorrect type of element at \"$k\": " . $e->getMessage(), 0, $e); + } + } + } + public static function checkUTF8(string $string) : void{ if(!mb_check_encoding($string, 'UTF-8')){ throw new \InvalidArgumentException("Text must be valid UTF-8"); diff --git a/tests/phpstan/configs/phpstan-bugs.neon b/tests/phpstan/configs/phpstan-bugs.neon index a44533241..06748c384 100644 --- a/tests/phpstan/configs/phpstan-bugs.neon +++ b/tests/phpstan/configs/phpstan-bugs.neon @@ -30,6 +30,11 @@ parameters: count: 1 path: ../../../src/utils/Utils.php + - + message: "#^Parameter \\#1 \\$ of closure expects TMemberType, TMemberType given\\.$#" + count: 1 + path: ../../../src/utils/Utils.php + - message: "#^Call to function is_resource\\(\\) with resource will always evaluate to true\\.$#" count: 2