From b306f65185372b6f5f140bb463db5d5f1f549d0a Mon Sep 17 00:00:00 2001 From: Opeyemi Ibrahim Date: Fri, 22 Nov 2024 10:53:53 +0100 Subject: [PATCH 1/7] Add rule to check for wpm_apply_filters function --- composer.json | 1 + phpstan.neon.dist | 3 + ...ypedDynamicFunctionReturnTypeExtension.php | 201 ++++++++++++++++++ 3 files changed, 205 insertions(+) create mode 100644 tests/phpstan/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php diff --git a/composer.json b/composer.json index 5c474f3135..717f3c93a7 100644 --- a/composer.json +++ b/composer.json @@ -234,6 +234,7 @@ "@test-integration-pressidium" ], "run-stan": "vendor/bin/phpstan analyze --memory-limit=2G --no-progress", + "run-stan-reset-baseline": "vendor/bin/phpstan analyze --memory-limit=2G --no-progress --generate-baseline", "install-codestandards": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin::run", "phpcs": "phpcs --basepath=.", "phpcs-changed": "./bin/phpcs-changed.sh", diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 02e47b7399..0062b2abe3 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -10,6 +10,7 @@ parameters: - %currentWorkingDirectory%/inc/ThirdParty/ - %currentWorkingDirectory%/tests/Integration/ - %currentWorkingDirectory%/tests/Unit/ + - %currentWorkingDirectory%/tests/phpstan/Rules/ bootstrapFiles: # Must be first - %currentWorkingDirectory%/inc/functions/options.php @@ -51,3 +52,5 @@ parameters: # These need plugin stubs! - %currentWorkingDirectory%/inc/classes/subscriber/third-party/ - %currentWorkingDirectory%/inc/3rd-party/ +rules: + - WP_Rocket\Tests\phpstan\Rules\ApplyFiltersTypedDynamicFunctionReturnTypeExtension diff --git a/tests/phpstan/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php b/tests/phpstan/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php new file mode 100644 index 0000000000..05abe614ce --- /dev/null +++ b/tests/phpstan/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php @@ -0,0 +1,201 @@ + */ + private $errors; + + public function getNodeType(): string + { + return FuncCall::class; + } + + public function processNode(Node $node, Scope $scope): array + { + $this->currentNode = $node; + $this->currentScope = $scope; + $this->errors = []; + + if (! ($node->name instanceof Name)) { + return []; + } + + if (! in_array($node->name->toString(), self::SUPPORTED_FUNCTIONS, true)) { + return []; + } + + $resolvedPhpDoc = $this->hookDocBlock->getNullableHookDocBlock($node, $scope); + + if ($resolvedPhpDoc === null) { + return []; + } + + $this->validateDocBlock($resolvedPhpDoc); + + return $this->errors; + } + + /** + * Validates the `@param` tags documented in the given docblock. + */ + public function validateDocBlock(ResolvedPhpDocBlock $resolvedPhpDoc): void + { + // Count all documented `@param` tag strings in the docblock. + $numberOfParamTagStrings = substr_count($resolvedPhpDoc->getPhpDocString(), '* @param '); + + // A docblock with no param tags is allowed and gets skipped. + if ($numberOfParamTagStrings === 0) { + return; + } + + $this->validateParamCount($numberOfParamTagStrings); + + // If the number of param tags doesn't match the number of + // parameters, bail out early. There's no point trying to + // reconcile param tags in this situation. + if ($this->errors !== []) { + return; + } + + // Fetch the parsed `@param` tags from the docblock. + $paramTags = $resolvedPhpDoc->getParamTags(); + + $this->validateParamDocumentation(count($paramTags), $resolvedPhpDoc); + if ($this->errors !== []) { + return; + } + + $nodeArgs = $this->currentNode->getArgs(); + $paramIndex = 2; + + foreach ($paramTags as $paramName => $paramTag) { + $this->validateSingleParamTag($paramName, $paramTag, $nodeArgs[$paramIndex]); + $paramIndex += 1; + } + } + + /** + * Validates the number of documented `@param` tags in the docblock. + */ + public function validateParamCount(int $numberOfParamTagStrings): void + { + // The first parameter is the type, the second parameter is the hook name, so we subtract 2. + $numberOfParams = count($this->currentNode->getArgs()) - 2; + + // Correct number of `@param` tags. + if ($numberOfParams === $numberOfParamTagStrings) { + return; + } + + $this->errors[] = RuleErrorBuilder::message( + sprintf( + 'Expected %1$d @param tags, found %2$d.', + $numberOfParams, + $numberOfParamTagStrings + ) + )->identifier('paramTag.count')->build(); + } + + /** + * Validates the number of parsed and valid `@param` tags in the docblock. + */ + public function validateParamDocumentation( + int $numberOfParamTags, + ResolvedPhpDocBlock $resolvedPhpDoc + ): void { + $nodeArgs = $this->currentNode->getArgs(); + $numberOfParams = count($nodeArgs) - 2; + + // No invalid `@param` tags. + if ($numberOfParams === $numberOfParamTags) { + return; + } + + // We might have an invalid `@param` tag because it's named `$this`. + // PHPStan does not detect param tags named `$this`, it skips the tag. + // We can indirectly detect this by checking the actual parameter name, + // and if one of them is `$this` assume that's the problem. + $namedThis = false; + if (strpos($resolvedPhpDoc->getPhpDocString(), ' $this') !== false) { + foreach ($nodeArgs as $param) { + if (($param->value instanceof Variable) && $param->value->name === 'this') { + $namedThis = true; + break; + } + } + } + + $this->errors[] = RuleErrorBuilder::message( + $namedThis === true + ? '@param tag must not be named $this. Choose a descriptive alias, for example $instance.' + : 'One or more @param tags has an invalid name or invalid syntax.' + )->identifier('phpDoc.parseError')->build(); + } + + /** + * Validates a `@param` tag against its actual parameter. + * + * @param string $paramName The param tag name. + * @param ParamTag $paramTag The param tag instance. + * @param Arg $arg The actual parameter instance. + */ + protected function validateSingleParamTag(string $paramName, ParamTag $paramTag, Arg $arg): void + { + $paramTagType = $paramTag->getType(); + $paramType = $this->currentScope->getType($arg->value); + $accepted = $this->ruleLevelHelper->accepts( + $paramTagType, + $paramType, + $this->currentScope->isDeclareStrictTypes() + ); + + if ($accepted) { + return; + } + + $paramTagVerbosityLevel = VerbosityLevel::getRecommendedLevelByType($paramTagType); + $paramVerbosityLevel = VerbosityLevel::getRecommendedLevelByType($paramType); + + $this->errors[] = RuleErrorBuilder::message( + sprintf( + '@param %1$s $%2$s does not accept actual type of parameter: %3$s.', + $paramTagType->describe($paramTagVerbosityLevel), + $paramName, + $paramType->describe($paramVerbosityLevel) + ) + )->identifier('parameter.phpDocType')->build(); + } +} From a7bfc41040850a7f8b31b9feecf865188849f979 Mon Sep 17 00:00:00 2001 From: Opeyemi Ibrahim Date: Fri, 22 Nov 2024 11:30:20 +0100 Subject: [PATCH 2/7] Add constructor :closes: #7119 --- phpstan-baseline.neon | 16 ++++++++++++++++ ...rsTypedDynamicFunctionReturnTypeExtension.php | 9 +++++++++ 2 files changed, 25 insertions(+) create mode 100644 phpstan-baseline.neon diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 0000000000..167512f2ed --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,16 @@ +parameters: + ignoreErrors: + - + message: "#^One or more @param tags has an invalid name or invalid syntax\\.$#" + count: 1 + path: inc/Engine/Common/PerformanceHints/Frontend/Subscriber.php + + - + message: "#^Access to an undefined property PhpParser\\\\Node\\:\\:\\$name\\.$#" + count: 1 + path: tests/phpstan/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php + + - + message: "#^Property WP_Rocket\\\\Tests\\\\phpstan\\\\Rules\\\\ApplyFiltersTypedDynamicFunctionReturnTypeExtension\\:\\:\\$currentNode \\(PhpParser\\\\Node\\\\Expr\\\\FuncCall\\) does not accept PhpParser\\\\Node\\.$#" + count: 1 + path: tests/phpstan/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php diff --git a/tests/phpstan/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php b/tests/phpstan/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php index 05abe614ce..7723553bee 100644 --- a/tests/phpstan/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php +++ b/tests/phpstan/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php @@ -12,6 +12,7 @@ use PHPStan\Rules\Rule; use PHPStan\Rules\RuleErrorBuilder; use PHPStan\Rules\RuleLevelHelper; +use PHPStan\Type\FileTypeMapper; use PHPStan\Type\VerbosityLevel; use SzepeViktor\PHPStan\WordPress\HookDocBlock; use PHPStan\PhpDoc\Tag\ParamTag; @@ -38,6 +39,14 @@ class ApplyFiltersTypedDynamicFunctionReturnTypeExtension implements Rule /** @var list */ private $errors; + public function __construct( + FileTypeMapper $fileTypeMapper, + RuleLevelHelper $ruleLevelHelper + ) { + $this->hookDocBlock = new HookDocBlock($fileTypeMapper); + $this->ruleLevelHelper = $ruleLevelHelper; + } + public function getNodeType(): string { return FuncCall::class; From 3ac6b68f443043b12bfd9cf784461db31c6b52b9 Mon Sep 17 00:00:00 2001 From: Opeyemi Ibrahim Date: Fri, 22 Nov 2024 15:29:10 +0100 Subject: [PATCH 3/7] Add error message for missing docblock --- ...iltersTypedDynamicFunctionReturnTypeExtension.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/phpstan/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php b/tests/phpstan/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php index 7723553bee..c4bd14eaff 100644 --- a/tests/phpstan/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php +++ b/tests/phpstan/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php @@ -58,17 +58,19 @@ public function processNode(Node $node, Scope $scope): array $this->currentScope = $scope; $this->errors = []; - if (! ($node->name instanceof Name)) { - return []; - } - - if (! in_array($node->name->toString(), self::SUPPORTED_FUNCTIONS, true)) { + if (! ($node->name instanceof Name) + || ! in_array($node->name->toString(), self::SUPPORTED_FUNCTIONS, true) + ) { return []; } $resolvedPhpDoc = $this->hookDocBlock->getNullableHookDocBlock($node, $scope); if ($resolvedPhpDoc === null) { + $this->errors[] = RuleErrorBuilder::message( + 'Missing docblock for wpm_apply_filters_typed call.' + )->identifier('docblock.missing')->build(); + return []; } From a508059a057b30c915bd0ff1edd481d9230e901d Mon Sep 17 00:00:00 2001 From: Gael Robin Date: Fri, 22 Nov 2024 19:39:25 +0100 Subject: [PATCH 4/7] Add a check to make sure $node is a FuncCall. --- .../ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/phpstan/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php b/tests/phpstan/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php index c4bd14eaff..b6d09feded 100644 --- a/tests/phpstan/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php +++ b/tests/phpstan/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php @@ -54,6 +54,11 @@ public function getNodeType(): string public function processNode(Node $node, Scope $scope): array { + // Ensure the node is a FuncCall instance. + if (! ($node instanceof FuncCall)) { + return []; + } + $this->currentNode = $node; $this->currentScope = $scope; $this->errors = []; From c29054a45b6d8edbd375777a730660ae1b6f9877 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20Robin?= Date: Tue, 26 Nov 2024 03:49:05 +0100 Subject: [PATCH 5/7] Update baseline --- phpstan-baseline.neon | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index eaf8957317..a03dd4f913 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -135,6 +135,11 @@ parameters: count: 1 path: inc/Engine/Common/JobManager/APIHandler/APIClient.php + - + message: "#^One or more @param tags has an invalid name or invalid syntax\\.$#" + count: 1 + path: inc/Engine/Common/PerformanceHints/Frontend/Subscriber.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 2 From 97c1c8d348732a3757be180a4abf87a4e7a9e4cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20Robin?= Date: Fri, 29 Nov 2024 01:18:03 +0700 Subject: [PATCH 6/7] Update baseline --- phpstan-baseline.neon | 240 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 240 insertions(+) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index a03dd4f913..517c55ad6d 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -40,6 +40,11 @@ parameters: count: 1 path: inc/Engine/Admin/Deactivation/DeactivationIntent.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 2 + path: inc/Engine/Admin/DomainChange/Subscriber.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 @@ -50,6 +55,11 @@ parameters: count: 12 path: inc/Engine/Admin/Settings/Page.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 2 + path: inc/Engine/Admin/Settings/Page.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 2 @@ -80,6 +90,11 @@ parameters: count: 1 path: inc/Engine/CDN/RocketCDN/DataManagerSubscriber.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 3 + path: inc/Engine/CDN/RocketCDN/DataManagerSubscriber.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 2 @@ -110,6 +125,11 @@ parameters: count: 1 path: inc/Engine/Cache/PurgeExpired/PurgeExpiredCache.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: inc/Engine/Cache/PurgeExpired/PurgeExpiredCache.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 6 @@ -135,6 +155,11 @@ parameters: count: 1 path: inc/Engine/Common/JobManager/APIHandler/APIClient.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: inc/Engine/Common/JobManager/APIHandler/APIClient.php + - message: "#^One or more @param tags has an invalid name or invalid syntax\\.$#" count: 1 @@ -160,6 +185,11 @@ parameters: count: 1 path: inc/Engine/CriticalPath/Admin/Admin.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 2 + path: inc/Engine/CriticalPath/Admin/Settings.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 5 @@ -190,6 +220,11 @@ parameters: count: 3 path: inc/Engine/Media/AboveTheFold/AJAX/Controller.php + - + message: "#^Hooks should not be used in ORM classes\\: WP_Rocket\\\\Engine\\\\Media\\\\AboveTheFold\\\\Database\\\\Queries\\\\AboveTheFold\\:\\:apply_filters$#" + count: 1 + path: inc/Engine/Media/AboveTheFold/Database/Queries/AboveTheFold.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 @@ -255,11 +290,21 @@ parameters: count: 3 path: inc/Engine/Optimization/DeferJS/DeferJS.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: inc/Engine/Optimization/DeferJS/DeferJS.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 path: inc/Engine/Optimization/DelayJS/Admin/SiteList.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: inc/Engine/Optimization/DelayJS/Admin/SiteList.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 @@ -270,11 +315,21 @@ parameters: count: 1 path: inc/Engine/Optimization/GoogleFonts/Admin/Settings.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: inc/Engine/Optimization/GoogleFonts/Admin/Settings.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 path: inc/Engine/Optimization/LazyRenderContent/AJAX/Controller.php + - + message: "#^Hooks should not be used in ORM classes\\: WP_Rocket\\\\Engine\\\\Optimization\\\\LazyRenderContent\\\\Database\\\\Queries\\\\LazyRenderContent\\:\\:apply_filters$#" + count: 1 + path: inc/Engine/Optimization/LazyRenderContent/Database/Queries/LazyRenderContent.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 @@ -315,6 +370,11 @@ parameters: count: 1 path: inc/Engine/Optimization/Minify/JS/Subscriber.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 2 + path: inc/Engine/Optimization/RUCSS/Admin/Settings.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 2 @@ -325,6 +385,11 @@ parameters: count: 13 path: inc/Engine/Optimization/RUCSS/Controller/UsedCSS.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 2 + path: inc/Engine/Optimization/RUCSS/Frontend/Subscriber.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 7 @@ -360,6 +425,11 @@ parameters: count: 5 path: inc/Engine/Preload/Cron/Subscriber.php + - + message: "#^Hooks should not be used in ORM classes\\: WP_Rocket\\\\Engine\\\\Preload\\\\Database\\\\Queries\\\\Cache\\:\\:apply_filters$#" + count: 4 + path: inc/Engine/Preload/Database/Queries/Cache.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 4 @@ -380,6 +450,16 @@ parameters: count: 2 path: inc/Engine/Preload/Subscriber.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: inc/ThirdParty/Hostings/Godaddy.php + + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: inc/ThirdParty/Plugins/Ads/Adthrive.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 @@ -395,6 +475,11 @@ parameters: count: 1 path: inc/ThirdParty/Plugins/ModPagespeed.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: inc/ThirdParty/Plugins/Optimization/WPMeteor.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 2 @@ -415,6 +500,11 @@ parameters: count: 1 path: inc/ThirdParty/Plugins/WPGeotargeting.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: inc/ThirdParty/Plugins/WPGeotargeting.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 @@ -450,6 +540,11 @@ parameters: count: 1 path: tests/Integration/bootstrap.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 5 + path: tests/Integration/bootstrap.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 @@ -570,6 +665,21 @@ parameters: count: 1 path: tests/Integration/inc/Engine/Admin/Settings/Subscriber/asyncWistiaScript.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: tests/Integration/inc/Engine/Admin/Settings/Subscriber/enableMobileCache.php + + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: tests/Integration/inc/Engine/Admin/Settings/Subscriber/enableSeparateCacheFilesMobile.php + + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: tests/Integration/inc/Engine/CDN/RocketCDN/AdminPageSubscriber/displayRocketcdnStatus.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 @@ -580,6 +690,21 @@ parameters: count: 1 path: tests/Integration/inc/Engine/CDN/RocketCDN/AdminPageSubscriber/rocketcdnField.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: tests/Integration/inc/Engine/CDN/RocketCDN/CDNOptionsManager/TestCase.php + + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: tests/Integration/inc/Engine/CDN/RocketCDN/NoticesSubscriber/displayRocketcdnCta.php + + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: tests/Integration/inc/Engine/CDN/RocketCDN/RESTSubscriber/disable.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 @@ -640,6 +765,21 @@ parameters: count: 1 path: tests/Integration/inc/Engine/Cache/Config/ConfigSubscriber/changeCacheRejectUriWithPermalink.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 2 + path: tests/Integration/inc/Engine/Cache/PurgeActionsSubscriber/purgeCacheOnPublicSettingChange.php + + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 3 + path: tests/Integration/inc/Engine/Cache/PurgeExpired/Subscriber/getCacheLifespan.php + + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 2 + path: tests/Integration/inc/Engine/Cache/PurgeExpired/Subscriber/scheduleEvent.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 @@ -710,11 +850,21 @@ parameters: count: 1 path: tests/Integration/inc/Engine/CriticalPath/CriticalCSS/getCriticalCssContent.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: tests/Integration/inc/Engine/CriticalPath/CriticalCSS/getCriticalCssContent.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 path: tests/Integration/inc/Engine/CriticalPath/CriticalCSS/getCurrentPageCriticalCss.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: tests/Integration/inc/Engine/CriticalPath/CriticalCSSSubscriber/deleteCpcss.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 @@ -730,6 +880,11 @@ parameters: count: 1 path: tests/Integration/inc/Engine/CriticalPath/CriticalCSSSubscriber/insertCriticalCssBuffer.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 2 + path: tests/Integration/inc/Engine/CriticalPath/CriticalCSSSubscriber/insertCriticalCssBuffer.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 @@ -740,6 +895,11 @@ parameters: count: 1 path: tests/Integration/inc/Engine/CriticalPath/CriticalCSSSubscriber/stopCpcssProcess.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: tests/Integration/inc/Engine/CriticalPath/CriticalCSSSubscriber/stopCpcssProcess.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 @@ -890,21 +1050,41 @@ parameters: count: 1 path: tests/Integration/inc/Engine/Optimization/DeferJS/AdminSubscriber/addDeferJsOption.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: tests/Integration/inc/Engine/Optimization/DeferJS/AdminSubscriber/excludeJqueryDefer.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 path: tests/Integration/inc/Engine/Optimization/DeferJS/Subscriber/deferInlineJs.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: tests/Integration/inc/Engine/Optimization/DeferJS/Subscriber/deferInlineJs.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 path: tests/Integration/inc/Engine/Optimization/DeferJS/Subscriber/deferJs.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: tests/Integration/inc/Engine/Optimization/DeferJS/Subscriber/deferJs.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 path: tests/Integration/inc/Engine/Optimization/DeferJS/Subscriber/excludeJqueryCombine.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: tests/Integration/inc/Engine/Optimization/DeferJS/Subscriber/excludeJqueryCombine.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 @@ -930,6 +1110,11 @@ parameters: count: 1 path: tests/Integration/inc/Engine/Optimization/DelayJS/Subscriber/delayJs.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: tests/Integration/inc/Engine/Optimization/DelayJS/Subscriber/delayJs.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 @@ -980,6 +1165,11 @@ parameters: count: 1 path: tests/Integration/inc/Engine/Optimization/DynamicLists/Subscriber/updateLists.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: tests/Integration/inc/Engine/Optimization/GoogleFonts/Admin/Subscriber/enableGoogleFonts.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 @@ -1070,6 +1260,11 @@ parameters: count: 1 path: tests/Integration/inc/Engine/Optimization/RUCSS/Frontend/Subscriber/maybeDisablePreloadFonts.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: tests/Integration/inc/Engine/Optimization/RUCSS/Frontend/Subscriber/maybeDisablePreloadFonts.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 @@ -1100,6 +1295,11 @@ parameters: count: 1 path: tests/Integration/inc/Engine/WPRocketUninstall/uninstall.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: tests/Integration/inc/Engine/WPRocketUninstall/uninstall.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 @@ -1280,6 +1480,16 @@ parameters: count: 1 path: tests/Integration/inc/ThirdParty/Plugins/Optimization/AMP/isAmpCompatibleCallback.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 3 + path: tests/Integration/inc/ThirdParty/Plugins/Optimization/Autoptimize/warnWhenAggregateInlineCssAndCPCSSActive.php + + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 2 + path: tests/Integration/inc/ThirdParty/Plugins/Optimization/Autoptimize/warnWhenJsAggregationAndDelayJsActive.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 @@ -1290,6 +1500,11 @@ parameters: count: 1 path: tests/Integration/inc/ThirdParty/Plugins/Optimization/Ezoic/addExplanations.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: tests/Integration/inc/ThirdParty/Plugins/Optimization/Hummingbird/warningNotice.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 @@ -1365,11 +1580,21 @@ parameters: count: 1 path: tests/Integration/inc/ThirdParty/Plugins/SEO/TheSEOFramework/addTsfSitemapToPreload.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: tests/Integration/inc/ThirdParty/Plugins/SimpleCustomCss/updateCacheFile.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 path: tests/Integration/inc/ThirdParty/Plugins/Smush/SmushSubscriberTestCase.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: tests/Integration/inc/ThirdParty/Plugins/Smush/maybeDeactivateRocketLazyload.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 1 @@ -1475,6 +1700,21 @@ parameters: count: 2 path: tests/Integration/inc/ThirdParty/Themes/Xstore/excludeInlineContent.php + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: tests/Integration/inc/admin/rocketAfterSaveOptions.php + + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 2 + path: tests/Integration/inc/admin/rocketFirstInstall.php + + - + message: "#^Usage of update_option\\(\\) is discouraged\\. Use the Option object instead\\.$#" + count: 1 + path: tests/Integration/inc/functions/rocketIsPluginActive.php + - message: "#^Usage of apply_filters\\(\\) is discouraged\\. Use wpm_apply_filters_typed\\(\\) instead\\.$#" count: 5 From bb82f34c644588fcf2baf45925f9ea368fc4c4d3 Mon Sep 17 00:00:00 2001 From: COQUARD Cyrille Date: Fri, 10 Jan 2025 14:59:12 +0100 Subject: [PATCH 7/7] Added tests but they are failing --- ...ypedDynamicFunctionReturnTypeExtension.php | 2 +- ...DynamicFunctionReturnTypeExtensionTest.php | 43 +++++++++++++++++++ .../extension.neon | 2 + .../not-valid.php | 13 ++++++ .../valid.php | 6 +++ 5 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 tests/phpstan/tests/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtensionTest.php create mode 100644 tests/phpstan/tests/data/ApplyFiltersTypedDynamicFunctionReturnTypeExtension/extension.neon create mode 100644 tests/phpstan/tests/data/ApplyFiltersTypedDynamicFunctionReturnTypeExtension/not-valid.php create mode 100644 tests/phpstan/tests/data/ApplyFiltersTypedDynamicFunctionReturnTypeExtension/valid.php diff --git a/tests/phpstan/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php b/tests/phpstan/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php index b6d09feded..4ff3f23435 100644 --- a/tests/phpstan/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php +++ b/tests/phpstan/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtension.php @@ -76,7 +76,7 @@ public function processNode(Node $node, Scope $scope): array 'Missing docblock for wpm_apply_filters_typed call.' )->identifier('docblock.missing')->build(); - return []; + return $this->errors; } $this->validateDocBlock($resolvedPhpDoc); diff --git a/tests/phpstan/tests/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtensionTest.php b/tests/phpstan/tests/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtensionTest.php new file mode 100644 index 0000000000..82719fa26c --- /dev/null +++ b/tests/phpstan/tests/Rules/ApplyFiltersTypedDynamicFunctionReturnTypeExtensionTest.php @@ -0,0 +1,43 @@ +getContainer()->getByType(FileTypeMapper::class), $this->getContainer()->getByType(RuleLevelHelper::class)); + } + + public function testShouldRaiseError() { + $this->analyse([__DIR__ . '/../data/ApplyFiltersTypedDynamicFunctionReturnTypeExtension/not-valid.php'], [ + [ + 'Missing docblock for wpm_apply_filters_typed call.', + 3, + ], + [ + 'Expected 2 @param tags, found 0.', + 8, + ], + [ + 'Expected 2 @param tags, found 1.', + 13, + ], + ]); + } + + public function testShouldNotRaiseError() { + $this->analyse([__DIR__ . '/../data/ApplyFiltersTypedDynamicFunctionReturnTypeExtension/valid.php'], []); + } + + public static function getAdditionalConfigFiles(): array + { + // path to your project's phpstan.neon, or extension.neon in case of custom extension packages + // this is only necessary if your custom rule relies on some extra configuration and other extensions + return [__DIR__ . '/../data/ApplyFiltersTypedDynamicFunctionReturnTypeExtension/extension.neon']; + } +} diff --git a/tests/phpstan/tests/data/ApplyFiltersTypedDynamicFunctionReturnTypeExtension/extension.neon b/tests/phpstan/tests/data/ApplyFiltersTypedDynamicFunctionReturnTypeExtension/extension.neon new file mode 100644 index 0000000000..383a8a393d --- /dev/null +++ b/tests/phpstan/tests/data/ApplyFiltersTypedDynamicFunctionReturnTypeExtension/extension.neon @@ -0,0 +1,2 @@ +includes: + - ../../../../../vendor/szepeviktor/phpstan-wordpress/extension.neon diff --git a/tests/phpstan/tests/data/ApplyFiltersTypedDynamicFunctionReturnTypeExtension/not-valid.php b/tests/phpstan/tests/data/ApplyFiltersTypedDynamicFunctionReturnTypeExtension/not-valid.php new file mode 100644 index 0000000000..63e59508bf --- /dev/null +++ b/tests/phpstan/tests/data/ApplyFiltersTypedDynamicFunctionReturnTypeExtension/not-valid.php @@ -0,0 +1,13 @@ +