From ae5f67b029e3d216a39984b868df99854928d1f6 Mon Sep 17 00:00:00 2001 From: Yaroslav Krutikov Date: Tue, 5 Apr 2022 11:29:57 +0200 Subject: [PATCH 1/4] TE-10562 Add rule ro check deprecated usage of decodeJson --- .../DeprecatedObjectUsageJsonDecodeRule.php | 117 ++++++++++++++++++ src/Common/ruleset.xml | 8 ++ ...eprecatedObjectUsageJsonDecodeRuleTest.php | 34 +++++ tests/_bootstrap.php | 2 + .../testRuleApplyWhenUsageIncorrect.php | 29 +++++ .../testRuleDoesNotApplyWhenUsageCorrect.php | 21 ++++ 6 files changed, 211 insertions(+) create mode 100644 src/Common/Method/DeprecatedObjectUsageJsonDecodeRule.php create mode 100644 tests/Common/Method/DeprecatedObjectUsageJsonDecodeRuleTest.php create mode 100644 tests/_data/Common/Method/DeprecatedObjectUsageJsonDecodeRuleTest/testRuleApplyWhenUsageIncorrect.php create mode 100644 tests/_data/Common/Method/DeprecatedObjectUsageJsonDecodeRuleTest/testRuleDoesNotApplyWhenUsageCorrect.php diff --git a/src/Common/Method/DeprecatedObjectUsageJsonDecodeRule.php b/src/Common/Method/DeprecatedObjectUsageJsonDecodeRule.php new file mode 100644 index 0000000..8769ac8 --- /dev/null +++ b/src/Common/Method/DeprecatedObjectUsageJsonDecodeRule.php @@ -0,0 +1,117 @@ +isClassDeprecated($node) + ) { + return; + } + + foreach ($node->getMethods() as $methodNode) { + $this->verifyMethod($methodNode); + } + } + + /** + * @param \PHPMD\Node\MethodNode $methodNode + * + * @return void + */ + protected function verifyMethod(MethodNode $methodNode): void + { + if ($this->isMethodDeprecated($methodNode)) { + return; + } + + $childNodes = $methodNode->findChildrenOfType('MethodPostfix'); + + foreach ($childNodes as $childNode) { + if ($childNode->getName() !== static::METHOD_NAME) { + continue; + } + + $this->verifyUsages($childNode, $methodNode); + } + } + + /** + * @param \PHPMD\Node\ASTNode $node + * @param \PHPMD\Node\MethodNode $methodNode + * + * @return void + */ + protected function verifyUsages(ASTNode $node, MethodNode $methodNode): void + { + $arguments = $node->getFirstChildOfType('Arguments')->findChildrenOfType('Literal'); + if ($arguments === []) { + $this->addRuleViolation($methodNode); + + return; + } + + foreach ($arguments as $argument) { + if ($argument->getName() == static::CORRECT_VALUE) { + continue; + } + + $this->addRuleViolation($methodNode); + } + } + + /** + * @param \PHPMD\Node\MethodNode $methodNode + * + * @return void + */ + protected function addRuleViolation(MethodNode $methodNode): void + { + $message = sprintf( + static::RULE_DEPRECATED_USAGE_FOUND, + $methodNode->getFullQualifiedName(), + ); + + $this->addViolation($methodNode, [$message]); + } +} diff --git a/src/Common/ruleset.xml b/src/Common/ruleset.xml index c9eae0a..e21b68d 100644 --- a/src/Common/ruleset.xml +++ b/src/Common/ruleset.xml @@ -50,6 +50,14 @@ 1 + + + 1 + + setReport($this->getReportMock(0)); + $bridgePathRule->apply($this->getClassNode()); + } + + /** + * @return void + */ + public function testRuleApplyWhenUsageIncorrect(): void + { + $bridgePathRule = new DeprecatedObjectUsageJsonDecodeRule(); + $bridgePathRule->setReport($this->getReportMock(2)); + $bridgePathRule->apply($this->getClassNode()); + } +} diff --git a/tests/_bootstrap.php b/tests/_bootstrap.php index e7c6535..50a61f1 100644 --- a/tests/_bootstrap.php +++ b/tests/_bootstrap.php @@ -14,6 +14,8 @@ require_once '_data/Common/Bridge/BridgeMethodsInterfaceTest/testRuleAppliesWhenBridgeInterfaceMethodsAreNotCorrect.php'; require_once '_data/Common/Bridge/BridgeMethodsInterfaceTest/testRuleDoesNotApplyWhenBridgeInterfaceMethodsAreCorrect.php'; require_once '_data/Common/Factory/FactoryCreateContainOneNewRuleTest/testRuleAppliesWhenCreateContainsWrongWayOfQueryCreation.php'; +require_once '_data/Common/Method/DeprecatedObjectUsageJsonDecodeRuleTest/testRuleApplyWhenUsageIncorrect.php'; +require_once '_data/Common/Method/DeprecatedObjectUsageJsonDecodeRuleTest/testRuleDoesNotApplyWhenUsageCorrect.php'; require_once '_data/Common/Method/ExternalMethodExtensionReturnTypeRuleTest/testRuleAppliesWhenClassExtendsExternalAndDoesNotHaveReturnType.php'; require_once '_data/Common/Method/ExternalMethodExtensionReturnTypeRuleTest/testRuleAppliesWhenClassImplementsExternalAndDoesNotHaveReturnType.php'; require_once '_data/Common/Method/ExternalMethodExtensionReturnTypeRuleTest/testRuleDoesNotApplyWhenClassExtendInternalAndDoesNotHaveReturnType.php'; diff --git a/tests/_data/Common/Method/DeprecatedObjectUsageJsonDecodeRuleTest/testRuleApplyWhenUsageIncorrect.php b/tests/_data/Common/Method/DeprecatedObjectUsageJsonDecodeRuleTest/testRuleApplyWhenUsageIncorrect.php new file mode 100644 index 0000000..e7bf43e --- /dev/null +++ b/tests/_data/Common/Method/DeprecatedObjectUsageJsonDecodeRuleTest/testRuleApplyWhenUsageIncorrect.php @@ -0,0 +1,29 @@ +utilEncodingService->decodeJson($value); + } + + /** + * @return bool + */ + public function testTwo(): bool + { + return $this->utilEncodingService->decodeJson($value, false); + } +} diff --git a/tests/_data/Common/Method/DeprecatedObjectUsageJsonDecodeRuleTest/testRuleDoesNotApplyWhenUsageCorrect.php b/tests/_data/Common/Method/DeprecatedObjectUsageJsonDecodeRuleTest/testRuleDoesNotApplyWhenUsageCorrect.php new file mode 100644 index 0000000..e81d07f --- /dev/null +++ b/tests/_data/Common/Method/DeprecatedObjectUsageJsonDecodeRuleTest/testRuleDoesNotApplyWhenUsageCorrect.php @@ -0,0 +1,21 @@ +utilEncodingService->decodeJson($value, true); + } +} From 098f343e8e850d054e24191e9d861ec0c7015112 Mon Sep 17 00:00:00 2001 From: Yaroslav Krutikov Date: Tue, 5 Apr 2022 11:37:46 +0200 Subject: [PATCH 2/4] TE-10562 Fix codestyle --- .gitignore | 1 + src/Common/Method/DeprecatedObjectUsageJsonDecodeRule.php | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c051b32..78b2ab1 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ composer.phar composer.lock phpunit.phar +.phpunit.result.cache tests/Common/_support/ tests/Zed/_support/ diff --git a/src/Common/Method/DeprecatedObjectUsageJsonDecodeRule.php b/src/Common/Method/DeprecatedObjectUsageJsonDecodeRule.php index 8769ac8..423d987 100644 --- a/src/Common/Method/DeprecatedObjectUsageJsonDecodeRule.php +++ b/src/Common/Method/DeprecatedObjectUsageJsonDecodeRule.php @@ -8,7 +8,6 @@ namespace ArchitectureSniffer\Common\Method; use ArchitectureSniffer\Common\DeprecationTrait; -use PDepend\Source\AST\ASTParameter; use PHPMD\AbstractNode; use PHPMD\AbstractRule; use PHPMD\Node\ASTNode; From 6546321db2c4144c20852bed2e2a8f08d3624406 Mon Sep 17 00:00:00 2001 From: Yaroslav Krutikov Date: Wed, 13 Apr 2022 11:14:08 +0200 Subject: [PATCH 3/4] Skip bridges during decodeJson rule check --- .../Bridge/BridgeMethodsInterfaceRule.php | 7 +++-- src/Common/Bridge/BridgeMethodsRule.php | 7 +++-- src/Common/Bridge/BridgeNameRule.php | 8 ++--- src/Common/ClassNameTrait.php | 30 +++++++++++++++++++ .../DeprecatedObjectUsageJsonDecodeRule.php | 3 ++ 5 files changed, 45 insertions(+), 10 deletions(-) create mode 100644 src/Common/ClassNameTrait.php diff --git a/src/Common/Bridge/BridgeMethodsInterfaceRule.php b/src/Common/Bridge/BridgeMethodsInterfaceRule.php index 246c720..6e6123f 100644 --- a/src/Common/Bridge/BridgeMethodsInterfaceRule.php +++ b/src/Common/Bridge/BridgeMethodsInterfaceRule.php @@ -7,6 +7,7 @@ namespace ArchitectureSniffer\Common\Bridge; +use ArchitectureSniffer\Common\ClassNameTrait; use ArchitectureSniffer\Common\PhpDocTrait; use ArchitectureSniffer\Common\PhpTypesTrait; use ArchitectureSniffer\SprykerAbstractRule; @@ -20,6 +21,7 @@ class BridgeMethodsInterfaceRule extends SprykerAbstractRule implements ClassAware { + use ClassNameTrait; use PhpDocTrait; use PhpTypesTrait; @@ -44,9 +46,8 @@ public function getDescription() public function apply(AbstractNode $node): void { if ( - preg_match('([A-Za-z0-9]+Bridge$)', $node->getName()) === 0 || - preg_match('#.*\\\\Dependency\\\\.*#', $node->getNamespaceName()) === 0 || - !$node instanceof ClassNode + !$node instanceof ClassNode || + !$this->isBridgeClass($node) ) { return; } diff --git a/src/Common/Bridge/BridgeMethodsRule.php b/src/Common/Bridge/BridgeMethodsRule.php index bef30c3..d2b96b8 100644 --- a/src/Common/Bridge/BridgeMethodsRule.php +++ b/src/Common/Bridge/BridgeMethodsRule.php @@ -7,6 +7,7 @@ namespace ArchitectureSniffer\Common\Bridge; +use ArchitectureSniffer\Common\ClassNameTrait; use ArchitectureSniffer\Common\PhpDocTrait; use ArchitectureSniffer\Common\PhpTypesTrait; use ArchitectureSniffer\SprykerAbstractRule; @@ -19,6 +20,7 @@ class BridgeMethodsRule extends SprykerAbstractRule implements ClassAware { + use ClassNameTrait; use PhpDocTrait; use PhpTypesTrait; @@ -43,9 +45,8 @@ public function getDescription() public function apply(AbstractNode $node) { if ( - preg_match('([A-Za-z0-9]+Bridge$)', $node->getName()) === 0 || - preg_match('#.*\\\\Dependency\\\\.*#', $node->getNamespaceName()) === 0 || - !$node instanceof ClassNode + !$node instanceof ClassNode || + !$this->isBridgeClass($node) ) { return; } diff --git a/src/Common/Bridge/BridgeNameRule.php b/src/Common/Bridge/BridgeNameRule.php index 592d5ec..c96c6f1 100644 --- a/src/Common/Bridge/BridgeNameRule.php +++ b/src/Common/Bridge/BridgeNameRule.php @@ -7,6 +7,7 @@ namespace ArchitectureSniffer\Common\Bridge; +use ArchitectureSniffer\Common\ClassNameTrait; use PHPMD\AbstractNode; use PHPMD\AbstractRule; use PHPMD\Node\InterfaceNode; @@ -14,6 +15,8 @@ class BridgeNameRule extends AbstractRule implements ClassAware { + use ClassNameTrait; + /** * @var string */ @@ -39,10 +42,7 @@ public function getDescription() */ public function apply(AbstractNode $node) { - if ( - preg_match('([A-Za-z0-9]+Bridge$)', $node->getName()) === 0 || - preg_match('#.*\\\\Dependency\\\\.*#', $node->getNamespaceName()) === 0 - ) { + if (!$this->isBridgeClass($node)) { return; } diff --git a/src/Common/ClassNameTrait.php b/src/Common/ClassNameTrait.php new file mode 100644 index 0000000..aa60c99 --- /dev/null +++ b/src/Common/ClassNameTrait.php @@ -0,0 +1,30 @@ +getName()) === 0 || + preg_match('#.*\\\\Dependency\\\\.*#', $node->getNamespaceName()) === 0 + ) { + return false; + } + + return true; + } +} diff --git a/src/Common/Method/DeprecatedObjectUsageJsonDecodeRule.php b/src/Common/Method/DeprecatedObjectUsageJsonDecodeRule.php index 423d987..b185679 100644 --- a/src/Common/Method/DeprecatedObjectUsageJsonDecodeRule.php +++ b/src/Common/Method/DeprecatedObjectUsageJsonDecodeRule.php @@ -7,6 +7,7 @@ namespace ArchitectureSniffer\Common\Method; +use ArchitectureSniffer\Common\ClassNameTrait; use ArchitectureSniffer\Common\DeprecationTrait; use PHPMD\AbstractNode; use PHPMD\AbstractRule; @@ -17,6 +18,7 @@ class DeprecatedObjectUsageJsonDecodeRule extends AbstractRule implements ClassAware { + use ClassNameTrait; use DeprecationTrait; /** @@ -44,6 +46,7 @@ public function apply(AbstractNode $node) if ( !$node instanceof ClassNode || $this->isClassDeprecated($node) + || $this->isBridgeClass($node) ) { return; } From feb08cad531f21186428e316a1962fbcc99ba46f Mon Sep 17 00:00:00 2001 From: Yaroslav Krutikov Date: Wed, 13 Apr 2022 11:16:35 +0200 Subject: [PATCH 4/4] Fix rule violation message --- src/Common/Method/DeprecatedObjectUsageJsonDecodeRule.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Common/Method/DeprecatedObjectUsageJsonDecodeRule.php b/src/Common/Method/DeprecatedObjectUsageJsonDecodeRule.php index b185679..526702b 100644 --- a/src/Common/Method/DeprecatedObjectUsageJsonDecodeRule.php +++ b/src/Common/Method/DeprecatedObjectUsageJsonDecodeRule.php @@ -34,7 +34,7 @@ class DeprecatedObjectUsageJsonDecodeRule extends AbstractRule implements ClassA /** * @var string */ - protected const RULE_DEPRECATED_USAGE_FOUND = 'Param #2 `$assoc` of `decodeJson` must be `true` as return of type `object` is not accepted. Method: %s.'; + protected const RULE_DEPRECATED_USAGE_FOUND = 'Param #2 `$assoc` of `decodeJson` must be `true` as return value of type `object` is deprecetaed. Method: %s.'; /** * @param \PHPMD\AbstractNode $node