diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 48bfd4a78..13f35c121 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -11,6 +11,7 @@ includes: rules: - pocketmine\phpstan\rules\DeprecatedLegacyEnumAccessRule + - pocketmine\phpstan\rules\DisallowDynamicNewRule - pocketmine\phpstan\rules\DisallowEnumComparisonRule - pocketmine\phpstan\rules\DisallowForeachByReferenceRule - pocketmine\phpstan\rules\ExplodeLimitRule diff --git a/tests/phpstan/configs/actual-problems.neon b/tests/phpstan/configs/actual-problems.neon index 73b7a65c1..e54bb166e 100644 --- a/tests/phpstan/configs/actual-problems.neon +++ b/tests/phpstan/configs/actual-problems.neon @@ -18,6 +18,12 @@ parameters: count: 1 path: ../../../src/Server.php + - + message: '#^Dynamic new is not allowed\.$#' + identifier: pocketmine.new.noDynamic + count: 1 + path: ../../../src/Server.php + - message: '#^Method pocketmine\\Server\:\:getCommandAliases\(\) should return array\\> but returns array\\>\.$#' identifier: return.type @@ -54,6 +60,12 @@ parameters: count: 1 path: ../../../src/VersionInfo.php + - + message: '#^Dynamic new is not allowed\.$#' + identifier: pocketmine.new.noDynamic + count: 1 + path: ../../../src/block/Block.php + - message: '#^Parameter \#1 \$x of method pocketmine\\world\\World\:\:getBlockAt\(\) expects int, float\|int given\.$#' identifier: argument.type @@ -510,6 +522,12 @@ parameters: count: 3 path: ../../../src/block/tile/Spawnable.php + - + message: '#^Dynamic new is not allowed\.$#' + identifier: pocketmine.new.noDynamic + count: 1 + path: ../../../src/block/tile/TileFactory.php + - message: '#^Parameter \#1 \$x of method pocketmine\\world\\World\:\:getPotentialLightAt\(\) expects int, float\|int given\.$#' identifier: argument.type @@ -936,6 +954,12 @@ parameters: count: 4 path: ../../../src/plugin/PluginManager.php + - + message: '#^Dynamic new is not allowed\.$#' + identifier: pocketmine.new.noDynamic + count: 1 + path: ../../../src/plugin/PluginManager.php + - message: '#^Method pocketmine\\resourcepacks\\ZippedResourcePack\:\:getPackSize\(\) should return int but returns int\<0, max\>\|false\.$#' identifier: return.type @@ -1248,6 +1272,12 @@ parameters: count: 1 path: ../../../src/world/format/io/region/RegionLoader.php + - + message: '#^Dynamic new is not allowed\.$#' + identifier: pocketmine.new.noDynamic + count: 1 + path: ../../../src/world/generator/GeneratorRegisterTask.php + - message: '#^Method pocketmine\\world\\generator\\biome\\BiomeSelector\:\:pickBiome\(\) should return pocketmine\\world\\biome\\Biome but returns pocketmine\\world\\biome\\Biome\|null\.$#' identifier: return.type diff --git a/tests/phpstan/rules/DisallowDynamicNewRule.php b/tests/phpstan/rules/DisallowDynamicNewRule.php new file mode 100644 index 000000000..c6c15a5aa --- /dev/null +++ b/tests/phpstan/rules/DisallowDynamicNewRule.php @@ -0,0 +1,55 @@ + + */ +final class DisallowDynamicNewRule implements Rule{ + + public function getNodeType() : string{ + return New_::class; + } + + public function processNode(Node $node, Scope $scope) : array{ + /** @var New_ $node */ + if($node->class instanceof Expr){ + return [ + RuleErrorBuilder::message("Dynamic new is not allowed.") + ->tip("For factories, use closures instead. Closures can implement custom logic, are statically analyzable, and don't restrict the constructor signature.") + ->identifier("pocketmine.new.noDynamic") + ->build() + ]; + } + + return []; + } +}