From 15eade91e82d70fa6cdbcea0dddaa9ca0f17c2e4 Mon Sep 17 00:00:00 2001 From: Dave Liddament Date: Mon, 12 Aug 2024 16:43:21 +0100 Subject: [PATCH 1/2] ADD rule to find rules that are not in extension.neon --- .../PHPStan/Rules/CheckRuleIsInExtension.php | 74 +++++++++++++++++++ composer.json | 6 +- composer.lock | 70 +++++++++++++++++- phpstan.neon | 10 ++- 4 files changed, 156 insertions(+), 4 deletions(-) create mode 100644 build/PHPStan/Rules/CheckRuleIsInExtension.php diff --git a/build/PHPStan/Rules/CheckRuleIsInExtension.php b/build/PHPStan/Rules/CheckRuleIsInExtension.php new file mode 100644 index 0000000..66e64c4 --- /dev/null +++ b/build/PHPStan/Rules/CheckRuleIsInExtension.php @@ -0,0 +1,74 @@ + */ +final class CheckRuleIsInExtension implements Rule +{ + /** @var list */ + private array $classes; + + public function __construct() + { + $file = Neon::decodeFile(__DIR__.'/../../../extension.neon'); + + if (!is_array($file)) { + throw new \Exception('Expecting neon file to be parseable'); + } + + $services = $file['services'] ?? []; + + $classes = []; + foreach ($services as $service) { + $class = $service['class'] ?? null; + if (null === $class) { + continue; + } + $classes[] = $class; + } + + $this->classes = $classes; + } + + public function getNodeType(): string + { + return InClassNode::class; + } + + public function processNode(Node $node, Scope $scope): array + { + $classReflection = $scope->getClassReflection(); + if (null === $classReflection) { + return []; + } + + if (!$classReflection->isSubclassOf(Rule::class)) { + return []; + } + + if ($classReflection->isAbstract()) { + return []; + } + + $className = $classReflection->getName(); + + if (str_starts_with(haystack: $className, needle: 'DaveLiddament\PhpstanPhpLanguageExtensions\Build')) { + return []; + } + + if (in_array($className, $this->classes)) { + return []; + } + + return [ + RuleErrorBuilder::message("Rule [$className] not in extension.neon.")->build(), + ]; + } +} diff --git a/composer.json b/composer.json index be147c7..ed04904 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,8 @@ "phpunit/phpunit": "^9.6.12", "friendsofphp/php-cs-fixer": "^3.26.1", "php-parallel-lint/php-parallel-lint": "^1.3.2", - "dave-liddament/phpstan-rule-test-helper": "^0.3.0" + "dave-liddament/phpstan-rule-test-helper": "^0.3.0", + "nette/neon": "^3.4" }, "license": "MIT", "autoload": { @@ -22,7 +23,8 @@ }, "autoload-dev": { "psr-4": { - "DaveLiddament\\PhpstanPhpLanguageExtensions\\Tests\\": "tests/" + "DaveLiddament\\PhpstanPhpLanguageExtensions\\Tests\\": "tests/", + "DaveLiddament\\PhpstanPhpLanguageExtensions\\Build\\": "build/" }, "classmap": [ "tests/Rules/data" diff --git a/composer.lock b/composer.lock index 1922d98..2ae6f03 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": "44a0a3837d85fb45c81ff033206e3b22", + "content-hash": "65b372eb17b17e5642eb1d52e725ac94", "packages": [ { "name": "dave-liddament/php-language-extensions", @@ -606,6 +606,74 @@ ], "time": "2020-06-29T13:22:24+00:00" }, + { + "name": "nette/neon", + "version": "v3.4.3", + "source": { + "type": "git", + "url": "https://github.com/nette/neon.git", + "reference": "c8481c104431c8d94cc88424a1e21f47f8c93280" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nette/neon/zipball/c8481c104431c8d94cc88424a1e21f47f8c93280", + "reference": "c8481c104431c8d94cc88424a1e21f47f8c93280", + "shasum": "" + }, + "require": { + "ext-json": "*", + "php": "8.0 - 8.3" + }, + "require-dev": { + "nette/tester": "^2.4", + "phpstan/phpstan": "^1.0", + "tracy/tracy": "^2.7" + }, + "bin": [ + "bin/neon-lint" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause", + "GPL-2.0-only", + "GPL-3.0-only" + ], + "authors": [ + { + "name": "David Grudl", + "homepage": "https://davidgrudl.com" + }, + { + "name": "Nette Community", + "homepage": "https://nette.org/contributors" + } + ], + "description": "🍸 Nette NEON: encodes and decodes NEON file format.", + "homepage": "https://ne-on.org", + "keywords": [ + "export", + "import", + "neon", + "nette", + "yaml" + ], + "support": { + "issues": "https://github.com/nette/neon/issues", + "source": "https://github.com/nette/neon/tree/v3.4.3" + }, + "time": "2024-06-26T14:53:59+00:00" + }, { "name": "nikic/php-parser", "version": "v4.15.0", diff --git a/phpstan.neon b/phpstan.neon index 679d2ad..f7b1f3d 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -3,5 +3,13 @@ parameters: paths: - src - tests + - build excludePaths: - - tests/Rules/data \ No newline at end of file + - tests/Rules/data + +services: + +- + class: DaveLiddament\PhpstanPhpLanguageExtensions\Build\PHPStan\Rules\CheckRuleIsInExtension + tags: + - phpstan.rules.rule \ No newline at end of file From ce418040a808bbc81a860d6ecf6f8a16169430f3 Mon Sep 17 00:00:00 2001 From: Dave Liddament Date: Mon, 12 Aug 2024 15:35:31 +0100 Subject: [PATCH 2/2] ADD missing entries to the extensions.neon file --- extension.neon | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/extension.neon b/extension.neon index 2264121..2b55719 100644 --- a/extension.neon +++ b/extension.neon @@ -81,6 +81,17 @@ services: tags: - phpstan.rules.rule + - + class: DaveLiddament\PhpstanPhpLanguageExtensions\Rules\MustUseResultRule + tags: + - phpstan.rules.rule + + - + class: DaveLiddament\PhpstanPhpLanguageExtensions\Rules\RestrictTraitToRule + tags: + - phpstan.rules.rule + + parametersSchema: phpLanguageExtensions: structure([