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/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 new file mode 100644 index 0000000..526702b --- /dev/null +++ b/src/Common/Method/DeprecatedObjectUsageJsonDecodeRule.php @@ -0,0 +1,119 @@ +isClassDeprecated($node) + || $this->isBridgeClass($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); + } +}