Update to PHPStan 2.x

This commit is contained in:
Dylan K. Taylor 2025-01-07 22:34:43 +00:00
parent d25ec58a6f
commit 9633b7d8a7
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
18 changed files with 876 additions and 344 deletions

View File

@ -52,9 +52,9 @@
"symfony/filesystem": "~6.4.0"
},
"require-dev": {
"phpstan/phpstan": "1.11.11",
"phpstan/phpstan-phpunit": "^1.1.0",
"phpstan/phpstan-strict-rules": "^1.2.0",
"phpstan/phpstan": "2.1.1",
"phpstan/phpstan-phpunit": "^2.0.0",
"phpstan/phpstan-strict-rules": "^2.0.0",
"phpunit/phpunit": "^10.5.24"
},
"autoload": {

58
composer.lock generated
View File

@ -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": "732102eca72dc1d29e7b67dfbce07653",
"content-hash": "994ccffe45f066768542019f6f9d237b",
"packages": [
{
"name": "adhocore/json-comment",
@ -1386,20 +1386,20 @@
},
{
"name": "phpstan/phpstan",
"version": "1.11.11",
"version": "2.1.1",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
"reference": "707c2aed5d8d0075666e673a5e71440c1d01a5a3"
"reference": "cd6e973e04b4c2b94c86e8612b5a65f0da0e08e7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/707c2aed5d8d0075666e673a5e71440c1d01a5a3",
"reference": "707c2aed5d8d0075666e673a5e71440c1d01a5a3",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/cd6e973e04b4c2b94c86e8612b5a65f0da0e08e7",
"reference": "cd6e973e04b4c2b94c86e8612b5a65f0da0e08e7",
"shasum": ""
},
"require": {
"php": "^7.2|^8.0"
"php": "^7.4|^8.0"
},
"conflict": {
"phpstan/phpstan-shim": "*"
@ -1440,34 +1440,33 @@
"type": "github"
}
],
"time": "2024-08-19T14:37:29+00:00"
"time": "2025-01-05T16:43:48+00:00"
},
{
"name": "phpstan/phpstan-phpunit",
"version": "1.4.0",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-phpunit.git",
"reference": "f3ea021866f4263f07ca3636bf22c64be9610c11"
"reference": "e32ac656788a5bf3dedda89e6a2cad5643bf1a18"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/f3ea021866f4263f07ca3636bf22c64be9610c11",
"reference": "f3ea021866f4263f07ca3636bf22c64be9610c11",
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/e32ac656788a5bf3dedda89e6a2cad5643bf1a18",
"reference": "e32ac656788a5bf3dedda89e6a2cad5643bf1a18",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0",
"phpstan/phpstan": "^1.11"
"php": "^7.4 || ^8.0",
"phpstan/phpstan": "^2.0.4"
},
"conflict": {
"phpunit/phpunit": "<7.0"
},
"require-dev": {
"nikic/php-parser": "^4.13.0",
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/phpstan-strict-rules": "^1.5.1",
"phpunit/phpunit": "^9.5"
"phpstan/phpstan-strict-rules": "^2.0",
"phpunit/phpunit": "^9.6"
},
"type": "phpstan-extension",
"extra": {
@ -1490,34 +1489,33 @@
"description": "PHPUnit extensions and rules for PHPStan",
"support": {
"issues": "https://github.com/phpstan/phpstan-phpunit/issues",
"source": "https://github.com/phpstan/phpstan-phpunit/tree/1.4.0"
"source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.3"
},
"time": "2024-04-20T06:39:00+00:00"
"time": "2024-12-19T09:14:43+00:00"
},
{
"name": "phpstan/phpstan-strict-rules",
"version": "1.6.0",
"version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-strict-rules.git",
"reference": "363f921dd8441777d4fc137deb99beb486c77df1"
"reference": "ed6fea0ad4ad9c7e25f3ad2e7c4d420cf1e67fe3"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/363f921dd8441777d4fc137deb99beb486c77df1",
"reference": "363f921dd8441777d4fc137deb99beb486c77df1",
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/ed6fea0ad4ad9c7e25f3ad2e7c4d420cf1e67fe3",
"reference": "ed6fea0ad4ad9c7e25f3ad2e7c4d420cf1e67fe3",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0",
"phpstan/phpstan": "^1.11"
"php": "^7.4 || ^8.0",
"phpstan/phpstan": "^2.0.4"
},
"require-dev": {
"nikic/php-parser": "^4.13.0",
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/phpstan-deprecation-rules": "^1.1",
"phpstan/phpstan-phpunit": "^1.0",
"phpunit/phpunit": "^9.5"
"phpstan/phpstan-deprecation-rules": "^2.0",
"phpstan/phpstan-phpunit": "^2.0",
"phpunit/phpunit": "^9.6"
},
"type": "phpstan-extension",
"extra": {
@ -1539,9 +1537,9 @@
"description": "Extra strict and opinionated rules for PHPStan",
"support": {
"issues": "https://github.com/phpstan/phpstan-strict-rules/issues",
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.6.0"
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.1"
},
"time": "2024-04-20T06:37:51+00:00"
"time": "2024-12-12T20:21:10+00:00"
},
{
"name": "phpunit/php-code-coverage",

View File

@ -1,6 +1,7 @@
includes:
- tests/phpstan/analyse-for-current-php-version.neon.php
- tests/phpstan/configs/actual-problems.neon
- tests/phpstan/configs/dependency-problems.neon
- tests/phpstan/configs/impossible-generics.neon
- tests/phpstan/configs/php-bugs.neon
- tests/phpstan/configs/phpstan-bugs.neon
@ -31,6 +32,7 @@ parameters:
paths:
- build
- src
- tests/phpstan/DummyPluginOwned.php
- tests/phpstan/rules
- tests/phpunit
- tests/plugins/TesterPlugin

View File

@ -51,9 +51,8 @@ final class CommandStringHelper{
foreach($matches[0] as $k => $_){
for($i = 1; $i <= 2; ++$i){
if($matches[$i][$k] !== ""){
/** @var string $match */ //phpstan can't understand preg_match and friends by itself :(
$match = $matches[$i][$k];
$args[(int) $k] = preg_replace('/\\\\([\\\\"])/u', '$1', $match) ?? throw new AssumptionFailedError(preg_last_error_msg());
$args[] = preg_replace('/\\\\([\\\\"])/u', '$1', $match) ?? throw new AssumptionFailedError(preg_last_error_msg());
break;
}
}

View File

@ -167,6 +167,7 @@ final class Utils{
/**
* @phpstan-return \Closure(object) : object
* @deprecated
*/
public static function cloneCallback() : \Closure{
return static function(object $o){
@ -179,15 +180,13 @@ final class Utils{
* @phpstan-template TValue of object
*
* @param object[] $array
* @phpstan-param array<TKey, TValue> $array
* @phpstan-param array<TKey, TValue>|list<TValue> $array
*
* @return object[]
* @phpstan-return array<TKey, TValue>
* @phpstan-return ($array is list<TValue> ? list<TValue> : array<TKey, TValue>)
*/
public static function cloneObjectArray(array $array) : array{
/** @phpstan-var \Closure(TValue) : TValue $callback */
$callback = self::cloneCallback();
return array_map($callback, $array);
return array_map(fn(object $o) => clone $o, $array);
}
/**

View File

@ -215,6 +215,9 @@ abstract class RegionWorldProvider extends BaseWorldProvider{
return null;
}
/**
* @phpstan-return \RegexIterator<mixed, string, \FilesystemIterator>
*/
private function createRegionIterator() : \RegexIterator{
return new \RegexIterator(
new \FilesystemIterator(

View File

@ -117,7 +117,7 @@ final class FlatGeneratorOptions{
}
}
}
$options[(string) $option] = $params;
$options[$option] = $params;
}
return new self($structure, $biomeId, $options);
}

View File

@ -0,0 +1,28 @@
<?php
/*
*
* ____ _ _ __ __ _ __ __ ____
* | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
* | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
* | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
* |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* @author PocketMine Team
* @link http://www.pocketmine.net/
*
*
*/
declare(strict_types=1);
namespace pocketmine\plugin;
class DummyPluginOwned{
use PluginOwnedTrait;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,73 @@
parameters:
ignoreErrors:
-
message: '#^Method pocketmine\\network\\mcpe\\convert\\BlockStateDictionary\:\:loadPaletteFromString\(\) should return list\<pocketmine\\data\\bedrock\\block\\BlockStateData\> but returns array\<pocketmine\\data\\bedrock\\block\\BlockStateData\>\.$#'
identifier: return.type
count: 1
path: ../../../src/network/mcpe/convert/BlockStateDictionary.php
-
message: '#^Parameter \#3 \$entityNBT of class pocketmine\\world\\format\\io\\ChunkData constructor expects list\<pocketmine\\nbt\\tag\\CompoundTag\>, array\<pocketmine\\nbt\\tag\\CompoundTag\> given\.$#'
identifier: argument.type
count: 1
path: ../../../src/world/format/io/leveldb/LevelDB.php
-
message: '#^Parameter \#4 \$tileNBT of class pocketmine\\world\\format\\io\\ChunkData constructor expects list\<pocketmine\\nbt\\tag\\CompoundTag\>, array\<pocketmine\\nbt\\tag\\CompoundTag\> given\.$#'
identifier: argument.type
count: 1
path: ../../../src/world/format/io/leveldb/LevelDB.php
-
message: '#^Parameter \#1 \$array of static method pocketmine\\world\\format\\io\\ChunkUtils\:\:convertBiomeColors\(\) expects list\<int\>, array\<int\> given\.$#'
identifier: argument.type
count: 1
path: ../../../src/world/format/io/region/Anvil.php
-
message: '#^Parameter \#1 \$array of static method pocketmine\\world\\format\\io\\ChunkUtils\:\:convertBiomeColors\(\) expects list\<int\>, array\<int\> given\.$#'
identifier: argument.type
count: 1
path: ../../../src/world/format/io/region/McRegion.php
-
message: '#^Parameter \#1 \$array of static method pocketmine\\world\\format\\io\\ChunkUtils\:\:convertBiomeColors\(\) expects list\<int\>, array\<int\> given\.$#'
identifier: argument.type
count: 1
path: ../../../src/world/format/io/region/PMAnvil.php
-
message: '#^Parameter \#1 \$oldNewStateList of function pocketmine\\tools\\blockstate_upgrade_schema_utils\\buildUpgradeTableFromData expects list\<pocketmine\\nbt\\TreeRoot\>, array\<pocketmine\\nbt\\TreeRoot\> given\.$#'
identifier: argument.type
count: 1
path: ../../../tools/blockstate-upgrade-schema-utils.php
-
message: '#^Parameter \#1 \$input of class pocketmine\\crafting\\json\\ShapelessRecipeData constructor expects list\<pocketmine\\crafting\\json\\RecipeIngredientData\>, array\<pocketmine\\crafting\\json\\RecipeIngredientData\> given\.$#'
identifier: argument.type
count: 1
path: ../../../tools/generate-bedrock-data-from-packets.php
-
message: '#^Parameter \#2 \$output of class pocketmine\\crafting\\json\\ShapelessRecipeData constructor expects list\<pocketmine\\crafting\\json\\ItemStackData\>, array\<pocketmine\\crafting\\json\\ItemStackData\> given\.$#'
identifier: argument.type
count: 1
path: ../../../tools/generate-bedrock-data-from-packets.php
-
message: '#^Parameter \#3 \$output of class pocketmine\\crafting\\json\\ShapedRecipeData constructor expects list\<pocketmine\\crafting\\json\\ItemStackData\>, array\<pocketmine\\crafting\\json\\ItemStackData\> given\.$#'
identifier: argument.type
count: 1
path: ../../../tools/generate-bedrock-data-from-packets.php
-
message: '#^Parameter \#5 \$unlockingIngredients of class pocketmine\\crafting\\json\\ShapelessRecipeData constructor expects list\<pocketmine\\crafting\\json\\RecipeIngredientData\>, array\<pocketmine\\crafting\\json\\RecipeIngredientData\> given\.$#'
identifier: argument.type
count: 1
path: ../../../tools/generate-bedrock-data-from-packets.php
-
message: '#^Parameter \#6 \$unlockingIngredients of class pocketmine\\crafting\\json\\ShapedRecipeData constructor expects list\<pocketmine\\crafting\\json\\RecipeIngredientData\>, array\<pocketmine\\crafting\\json\\RecipeIngredientData\> given\.$#'
identifier: argument.type
count: 1
path: ../../../tools/generate-bedrock-data-from-packets.php

View File

@ -1,12 +1,14 @@
parameters:
ignoreErrors:
-
message: "#^Method pocketmine\\\\event\\\\RegisteredListener\\:\\:__construct\\(\\) has parameter \\$handler with no signature specified for Closure\\.$#"
message: '#^Method pocketmine\\event\\RegisteredListener\:\:__construct\(\) has parameter \$handler with no signature specified for Closure\.$#'
identifier: missingType.callable
count: 1
path: ../../../src/event/RegisteredListener.php
-
message: "#^Method pocketmine\\\\event\\\\RegisteredListener\\:\\:getHandler\\(\\) return type has no signature specified for Closure\\.$#"
message: '#^Method pocketmine\\event\\RegisteredListener\:\:getHandler\(\) return type has no signature specified for Closure\.$#'
identifier: missingType.callable
count: 1
path: ../../../src/event/RegisteredListener.php

View File

@ -1,112 +1,260 @@
parameters:
ignoreErrors:
-
message: "#^Method pocketmine\\\\block\\\\DoubleTallGrass\\:\\:traitGetDropsForIncompatibleTool\\(\\) return type has no value type specified in iterable type array\\.$#"
message: '#^Access to an undefined property object\:\:\$crashId\.$#'
identifier: property.notFound
count: 1
path: ../../../src/Server.php
-
message: '#^Access to an undefined property object\:\:\$crashUrl\.$#'
identifier: property.notFound
count: 1
path: ../../../src/Server.php
-
message: '#^Access to an undefined property object\:\:\$error\.$#'
identifier: property.notFound
count: 1
path: ../../../src/Server.php
-
message: '#^Method pocketmine\\block\\Block\:\:readStateFromWorld\(\) is marked as impure but does not have any side effects\.$#'
identifier: impureMethod.pure
count: 1
path: ../../../src/block/Block.php
-
message: '#^Method pocketmine\\block\\DoubleTallGrass\:\:traitGetDropsForIncompatibleTool\(\) return type has no value type specified in iterable type array\.$#'
identifier: missingType.iterableValue
count: 1
path: ../../../src/block/DoubleTallGrass.php
-
message: "#^Creating callable from a non\\-native static method pocketmine\\\\item\\\\VanillaItems\\:\\:ACACIA_SIGN\\(\\)\\.$#"
message: '#^Creating callable from a non\-native static method pocketmine\\item\\VanillaItems\:\:ACACIA_SIGN\(\)\.$#'
identifier: callable.nonNativeMethod
count: 1
path: ../../../src/block/VanillaBlocks.php
-
message: "#^Creating callable from a non\\-native static method pocketmine\\\\item\\\\VanillaItems\\:\\:BIRCH_SIGN\\(\\)\\.$#"
message: '#^Creating callable from a non\-native static method pocketmine\\item\\VanillaItems\:\:BIRCH_SIGN\(\)\.$#'
identifier: callable.nonNativeMethod
count: 1
path: ../../../src/block/VanillaBlocks.php
-
message: "#^Creating callable from a non\\-native static method pocketmine\\\\item\\\\VanillaItems\\:\\:CHERRY_SIGN\\(\\)\\.$#"
message: '#^Creating callable from a non\-native static method pocketmine\\item\\VanillaItems\:\:CHERRY_SIGN\(\)\.$#'
identifier: callable.nonNativeMethod
count: 1
path: ../../../src/block/VanillaBlocks.php
-
message: "#^Creating callable from a non\\-native static method pocketmine\\\\item\\\\VanillaItems\\:\\:CRIMSON_SIGN\\(\\)\\.$#"
message: '#^Creating callable from a non\-native static method pocketmine\\item\\VanillaItems\:\:CRIMSON_SIGN\(\)\.$#'
identifier: callable.nonNativeMethod
count: 1
path: ../../../src/block/VanillaBlocks.php
-
message: "#^Creating callable from a non\\-native static method pocketmine\\\\item\\\\VanillaItems\\:\\:DARK_OAK_SIGN\\(\\)\\.$#"
message: '#^Creating callable from a non\-native static method pocketmine\\item\\VanillaItems\:\:DARK_OAK_SIGN\(\)\.$#'
identifier: callable.nonNativeMethod
count: 1
path: ../../../src/block/VanillaBlocks.php
-
message: "#^Creating callable from a non\\-native static method pocketmine\\\\item\\\\VanillaItems\\:\\:JUNGLE_SIGN\\(\\)\\.$#"
message: '#^Creating callable from a non\-native static method pocketmine\\item\\VanillaItems\:\:JUNGLE_SIGN\(\)\.$#'
identifier: callable.nonNativeMethod
count: 1
path: ../../../src/block/VanillaBlocks.php
-
message: "#^Creating callable from a non\\-native static method pocketmine\\\\item\\\\VanillaItems\\:\\:MANGROVE_SIGN\\(\\)\\.$#"
message: '#^Creating callable from a non\-native static method pocketmine\\item\\VanillaItems\:\:MANGROVE_SIGN\(\)\.$#'
identifier: callable.nonNativeMethod
count: 1
path: ../../../src/block/VanillaBlocks.php
-
message: "#^Creating callable from a non\\-native static method pocketmine\\\\item\\\\VanillaItems\\:\\:OAK_SIGN\\(\\)\\.$#"
message: '#^Creating callable from a non\-native static method pocketmine\\item\\VanillaItems\:\:OAK_SIGN\(\)\.$#'
identifier: callable.nonNativeMethod
count: 1
path: ../../../src/block/VanillaBlocks.php
-
message: "#^Creating callable from a non\\-native static method pocketmine\\\\item\\\\VanillaItems\\:\\:PALE_OAK_SIGN\\(\\)\\.$#"
message: '#^Creating callable from a non\-native static method pocketmine\\item\\VanillaItems\:\:PALE_OAK_SIGN\(\)\.$#'
identifier: callable.nonNativeMethod
count: 1
path: ../../../src/block/VanillaBlocks.php
-
message: "#^Creating callable from a non\\-native static method pocketmine\\\\item\\\\VanillaItems\\:\\:SPRUCE_SIGN\\(\\)\\.$#"
message: '#^Creating callable from a non\-native static method pocketmine\\item\\VanillaItems\:\:SPRUCE_SIGN\(\)\.$#'
identifier: callable.nonNativeMethod
count: 1
path: ../../../src/block/VanillaBlocks.php
-
message: "#^Creating callable from a non\\-native static method pocketmine\\\\item\\\\VanillaItems\\:\\:WARPED_SIGN\\(\\)\\.$#"
message: '#^Creating callable from a non\-native static method pocketmine\\item\\VanillaItems\:\:WARPED_SIGN\(\)\.$#'
identifier: callable.nonNativeMethod
count: 1
path: ../../../src/block/VanillaBlocks.php
-
message: "#^Call to function assert\\(\\) with false and 'unknown hit type' will always evaluate to false\\.$#"
message: '#^Strict comparison using \=\=\= between \*NEVER\* and 5 will always evaluate to false\.$#'
identifier: identical.alwaysFalse
count: 1
path: ../../../src/command/defaults/TeleportCommand.php
-
message: '#^Method pocketmine\\crafting\\ShapedRecipe\:\:getIngredientMap\(\) should return list\<list\<pocketmine\\crafting\\RecipeIngredient\|null\>\> but returns array\<int\<0, max\>, non\-empty\-array\<int\<0, max\>, pocketmine\\crafting\\RecipeIngredient\|null\>\>\.$#'
identifier: return.type
count: 1
path: ../../../src/crafting/ShapedRecipe.php
-
message: '#^Property pocketmine\\crash\\CrashDumpData\:\:\$parameters \(list\<string\>\) does not accept array\.$#'
identifier: assign.propertyType
count: 1
path: ../../../src/crash/CrashDump.php
-
message: '#^Call to function assert\(\) with false and ''unknown hit type'' will always evaluate to false\.$#'
identifier: function.impossibleType
count: 1
path: ../../../src/entity/projectile/Projectile.php
-
message: "#^Property pocketmine\\\\network\\\\mcpe\\\\raklib\\\\PthreadsChannelWriter\\:\\:\\$buffer is never read, only written\\.$#"
message: '#^Property pocketmine\\item\\WritableBookBase\:\:\$pages \(list\<pocketmine\\item\\WritableBookPage\>\) does not accept non\-empty\-array\<int, pocketmine\\item\\WritableBookPage\>\.$#'
identifier: assign.propertyType
count: 1
path: ../../../src/item/WritableBookBase.php
-
message: '#^Method pocketmine\\network\\mcpe\\compression\\ZlibCompressor\:\:getNetworkId\(\) never returns 1 so it can be removed from the return type\.$#'
identifier: return.unusedType
count: 1
path: ../../../src/network/mcpe/compression/ZlibCompressor.php
-
message: '#^Method pocketmine\\network\\mcpe\\compression\\ZlibCompressor\:\:getNetworkId\(\) never returns 255 so it can be removed from the return type\.$#'
identifier: return.unusedType
count: 1
path: ../../../src/network/mcpe/compression/ZlibCompressor.php
-
message: '#^Parameter \#1 \$states of class pocketmine\\network\\mcpe\\convert\\BlockStateDictionary constructor expects list\<pocketmine\\network\\mcpe\\convert\\BlockStateDictionaryEntry\>, array\<int\<0, max\>, pocketmine\\network\\mcpe\\convert\\BlockStateDictionaryEntry\> given\.$#'
identifier: argument.type
count: 1
path: ../../../src/network/mcpe/convert/BlockStateDictionary.php
-
message: '#^Cannot access offset ''default'' on mixed\.$#'
identifier: offsetAccess.nonOffsetAccessible
count: 1
path: ../../../src/network/mcpe/convert/LegacySkinAdapter.php
-
message: '#^Property pocketmine\\network\\mcpe\\raklib\\PthreadsChannelWriter\:\:\$buffer is never read, only written\.$#'
identifier: property.onlyWritten
count: 1
path: ../../../src/network/mcpe/raklib/PthreadsChannelWriter.php
-
message: "#^Property pocketmine\\\\network\\\\mcpe\\\\raklib\\\\SnoozeAwarePthreadsChannelWriter\\:\\:\\$buffer is never read, only written\\.$#"
message: '#^Property pocketmine\\network\\mcpe\\raklib\\SnoozeAwarePthreadsChannelWriter\:\:\$buffer is never read, only written\.$#'
identifier: property.onlyWritten
count: 1
path: ../../../src/network/mcpe/raklib/SnoozeAwarePthreadsChannelWriter.php
-
message: "#^Dead catch \\- RuntimeException is never thrown in the try block\\.$#"
message: '#^Dead catch \- RuntimeException is never thrown in the try block\.$#'
identifier: catch.neverThrown
count: 1
path: ../../../src/plugin/PluginManager.php
-
message: "#^Method pocketmine\\\\timings\\\\TimingsHandler\\:\\:lazyGetSet\\(\\) should return pocketmine\\\\utils\\\\ObjectSet\\<T of object\\> but returns pocketmine\\\\utils\\\\ObjectSet\\<object\\>\\.$#"
message: '#^Binary operation "\." between mixed and ''/''\|''\\\\'' results in an error\.$#'
identifier: binaryOp.invalid
count: 1
path: ../../../src/thread/ThreadSafeClassLoader.php
-
message: '#^Binary operation "\." between mixed and non\-falsy\-string results in an error\.$#'
identifier: binaryOp.invalid
count: 1
path: ../../../src/thread/ThreadSafeClassLoader.php
-
message: '#^Method pocketmine\\timings\\TimingsHandler\:\:lazyGetSet\(\) should return pocketmine\\utils\\ObjectSet\<T of object\> but returns pocketmine\\utils\\ObjectSet\<object\>\.$#'
identifier: return.type
count: 1
path: ../../../src/timings/TimingsHandler.php
-
message: "#^Casting to int something that's already int\\.$#"
message: '#^Parameter &\$where @param\-out type of method pocketmine\\timings\\TimingsHandler\:\:lazyGetSet\(\) expects pocketmine\\utils\\ObjectSet\<T of object\>, pocketmine\\utils\\ObjectSet\<object\> given\.$#'
identifier: paramOut.type
count: 1
path: ../../../src/timings/TimingsHandler.php
-
message: '#^Binary operation "\*" between mixed and 3600 results in an error\.$#'
identifier: binaryOp.invalid
count: 1
path: ../../../src/utils/Timezone.php
-
message: '#^Binary operation "\*" between mixed and 60 results in an error\.$#'
identifier: binaryOp.invalid
count: 1
path: ../../../src/utils/Timezone.php
-
message: '#^Binary operation "\+" between \(float\|int\) and mixed results in an error\.$#'
identifier: binaryOp.invalid
count: 1
path: ../../../src/utils/Timezone.php
-
message: '#^Property pocketmine\\world\\format\\io\\region\\RegionLoader\:\:\$locationTable \(list\<pocketmine\\world\\format\\io\\region\\RegionLocationTableEntry\|null\>\) does not accept non\-empty\-array\<int, pocketmine\\world\\format\\io\\region\\RegionLocationTableEntry\|null\>\.$#'
identifier: assign.propertyType
count: 2
path: ../../../src/world/format/io/region/RegionLoader.php
-
message: '#^Property pocketmine\\world\\format\\io\\region\\RegionLoader\:\:\$locationTable \(list\<pocketmine\\world\\format\\io\\region\\RegionLocationTableEntry\|null\>\) does not accept non\-empty\-array\<int\<0, max\>, pocketmine\\world\\format\\io\\region\\RegionLocationTableEntry\|null\>\.$#'
identifier: assign.propertyType
count: 3
path: ../../../src/world/format/io/region/RegionLoader.php
-
message: '#^Method pocketmine\\world\\format\\io\\region\\RegionWorldProvider\:\:createRegionIterator\(\) should return RegexIterator\<mixed, string, FilesystemIterator\> but returns RegexIterator\<mixed, mixed, Traversable\<TKey, TValue\>\>\.$#'
identifier: return.type
count: 1
path: ../../../src/world/format/io/region/RegionWorldProvider.php
-
message: '#^Casting to int something that''s already int\.$#'
identifier: cast.useless
count: 1
path: ../../../src/world/generator/normal/Normal.php
-
message: "#^Call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertFalse\\(\\) with false will always evaluate to true\\.$#"
message: '#^Call to static method PHPUnit\\Framework\\Assert\:\:assertFalse\(\) with false will always evaluate to true\.$#'
identifier: staticMethod.alreadyNarrowedType
count: 1
path: ../../phpunit/promise/PromiseTest.php
-
message: "#^Call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertTrue\\(\\) with false and 'All promise should…' will always evaluate to false\\.$#"
message: '#^Call to static method PHPUnit\\Framework\\Assert\:\:assertTrue\(\) with false and ''All promise should…'' will always evaluate to false\.$#'
identifier: staticMethod.impossibleType
count: 1
path: ../../phpunit/promise/PromiseTest.php
-
message: "#^Call to static method PHPUnit\\\\Framework\\\\Assert\\:\\:assertTrue\\(\\) with false will always evaluate to false\\.$#"
message: '#^Call to static method PHPUnit\\Framework\\Assert\:\:assertTrue\(\) with false will always evaluate to false\.$#'
identifier: staticMethod.impossibleType
count: 2
path: ../../phpunit/promise/PromiseTest.php
-
message: "#^Strict comparison using \\=\\=\\= between 0 and 0 will always evaluate to true\\.$#"
message: '#^Strict comparison using \=\=\= between 0 and 0 will always evaluate to true\.$#'
identifier: identical.alwaysTrue
count: 1
path: ../rules/UnsafeForeachArrayOfStringRule.php

View File

@ -1,22 +1,32 @@
parameters:
ignoreErrors:
-
message: "#^Cannot call method collectGarbage\\(\\) on pocketmine\\\\world\\\\format\\\\SubChunk\\|null\\.$#"
message: '#^Cannot call method collectGarbage\(\) on pocketmine\\world\\format\\SubChunk\|null\.$#'
identifier: method.nonObject
count: 1
path: ../../../src/world/format/Chunk.php
-
message: "#^Method pocketmine\\\\world\\\\format\\\\Chunk\\:\\:getSubChunks\\(\\) should return array\\<int, pocketmine\\\\world\\\\format\\\\SubChunk\\> but returns array\\<int, pocketmine\\\\world\\\\format\\\\SubChunk\\|null\\>\\.$#"
message: '#^Method pocketmine\\world\\format\\Chunk\:\:getSubChunks\(\) should return array\<int, pocketmine\\world\\format\\SubChunk\> but returns array\<int, pocketmine\\world\\format\\SubChunk\|null\>\.$#'
identifier: return.type
count: 1
path: ../../../src/world/format/Chunk.php
-
message: "#^Parameter \\#1 \\$callback of function array_map expects \\(callable\\(pocketmine\\\\world\\\\format\\\\SubChunk\\|null\\)\\: mixed\\)\\|null, Closure\\(pocketmine\\\\world\\\\format\\\\SubChunk\\)\\: pocketmine\\\\world\\\\format\\\\SubChunk given\\.$#"
message: '#^Parameter \#1 \$callback of function array_map expects \(callable\(pocketmine\\world\\format\\SubChunk\|null\)\: mixed\)\|null, Closure\(pocketmine\\world\\format\\SubChunk\)\: pocketmine\\world\\format\\SubChunk given\.$#'
identifier: argument.type
count: 1
path: ../../../src/world/format/Chunk.php
-
message: "#^Method pocketmine\\\\world\\\\format\\\\HeightArray\\:\\:getValues\\(\\) should return non\\-empty\\-array\\<int, int\\> but returns array\\<int, int\\|null\\>\\.$#"
message: '#^Method pocketmine\\world\\format\\HeightArray\:\:getValues\(\) should return non\-empty\-list\<int\> but returns array\<int, int\|null\>\.$#'
identifier: return.type
count: 1
path: ../../../src/world/format/HeightArray.php
-
message: '#^Offset int might not exist on SplFixedArray\<float\>\|null\.$#'
identifier: offsetAccess.notFound
count: 4
path: ../../../src/world/generator/noise/Noise.php

View File

@ -28,7 +28,6 @@ use PhpParser\Node\Expr\StaticCall;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\Type\TypeWithClassName;
use pocketmine\utils\LegacyEnumShimTrait;
use function sprintf;
@ -51,18 +50,15 @@ final class DeprecatedLegacyEnumAccessRule implements Rule{
$scope->resolveTypeByName($node->class) :
$scope->getType($node->class);
if(!$classType instanceof TypeWithClassName){
return [];
}
$errors = [];
$reflections = $classType->getObjectClassReflections();
foreach($reflections as $reflection){
if(!$reflection->hasTraitUse(LegacyEnumShimTrait::class) || !$reflection->implementsInterface(\UnitEnum::class)){
continue;
}
$reflection = $classType->getClassReflection();
if($reflection === null || !$reflection->hasTraitUse(LegacyEnumShimTrait::class) || !$reflection->implementsInterface(\UnitEnum::class)){
return [];
}
if(!$reflection->hasNativeMethod($caseName)){
return [
RuleErrorBuilder::message(sprintf(
if(!$reflection->hasNativeMethod($caseName)){
$errors[] = RuleErrorBuilder::message(sprintf(
'Use of legacy enum case accessor %s::%s().',
$reflection->getName(),
$caseName
@ -70,10 +66,11 @@ final class DeprecatedLegacyEnumAccessRule implements Rule{
'Access the enum constant directly instead (remove the brackets), e.g. %s::%s',
$reflection->getName(),
$caseName
))->build()
];
))->identifier('pocketmine.enum.deprecatedAccessor')
->build();
}
}
return [];
return $errors;
}
}

View File

@ -30,7 +30,6 @@ use PhpParser\Node\Expr\BinaryOp\NotIdentical;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;
use PHPStan\Type\ObjectType;
use PHPStan\Type\Type;
use PHPStan\Type\UnionType;
use PHPStan\Type\VerbosityLevel;
@ -61,7 +60,7 @@ class DisallowEnumComparisonRule implements Rule{
$node instanceof Identical ? '===' : '!==',
$leftType->describe(VerbosityLevel::value()),
$rightType->describe(VerbosityLevel::value())
))->build()];
))->identifier('pocketmine.enum.badComparison')->build()];
}
return [];
}
@ -69,7 +68,7 @@ class DisallowEnumComparisonRule implements Rule{
private function checkForEnumTypes(Type $comparedType) : bool{
//TODO: what we really want to do here is iterate over the contained types, but there's no universal way to
//do that. This might break with other circumstances.
if($comparedType instanceof ObjectType){
if($comparedType->isObject()->yes()){
$types = [$comparedType];
}elseif($comparedType instanceof UnionType){
$types = $comparedType->getTypes();
@ -77,12 +76,14 @@ class DisallowEnumComparisonRule implements Rule{
return false;
}
foreach($types as $containedType){
if(!($containedType instanceof ObjectType)){
if(!($containedType->isObject()->yes())){
continue;
}
$class = $containedType->getClassReflection();
if($class !== null && $class->hasTraitUse(EnumTrait::class)){
return true;
$classes = $containedType->getObjectClassReflections();
foreach($classes as $class){
if($class->hasTraitUse(EnumTrait::class)){
return true;
}
}
}
return false;

View File

@ -44,6 +44,7 @@ final class DisallowForeachByReferenceRule implements Rule{
return [
RuleErrorBuilder::message("Foreach by-reference is not allowed, because it has surprising behaviour.")
->tip("If the value variable is used outside of the foreach construct (e.g. in a second foreach), the iterable's contents will be unexpectedly altered.")
->identifier('pocketmine.foreach.byRef')
->build()
];
}

View File

@ -101,7 +101,7 @@ final class UnsafeForeachArrayOfStringRule implements Rule{
RuleErrorBuilder::message(sprintf(
"Unsafe foreach on array with key type %s (they might be casted to int).",
$iterableType->getIterableKeyType()->describe(VerbosityLevel::value())
))->tip($tip)->build()
))->tip($tip)->identifier('pocketmine.foreach.stringKeys')->build()
];
}
return [];

View File

@ -23,6 +23,6 @@ declare(strict_types=1);
namespace pocketmine\utils\fixtures;
trait TestTrait{
trait TestTrait{ // @phpstan-ignore trait.unused
}