-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
TE-10831 Added rule: any extension of non spryker code must have retu…
…rrn types (#112) * TE-1083 Added rule: any extension of non spryker code must have return types
- Loading branch information
Dmytro Dymarchuk
authored
Mar 10, 2022
1 parent
b4bbef1
commit 6edac6a
Showing
12 changed files
with
438 additions
and
1 deletion.
There are no files selected for viewing
111 changes: 111 additions & 0 deletions
111
src/Common/Method/ExternalMethodExtensionReturnTypeRule.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
<?php | ||
|
||
/** | ||
* Copyright © 2016-present Spryker Systems GmbH. All rights reserved. | ||
* Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file. | ||
*/ | ||
|
||
namespace ArchitectureSniffer\Common\Method; | ||
|
||
use ArchitectureSniffer\Common\DeprecationTrait; | ||
use ArchitectureSniffer\Common\PhpDocTrait; | ||
use ArchitectureSniffer\Common\PhpTypesTrait; | ||
use PHPMD\AbstractNode; | ||
use PHPMD\AbstractRule; | ||
use PHPMD\Node\ClassNode; | ||
use PHPMD\Rule\ClassAware; | ||
use ReflectionException; | ||
use ReflectionMethod; | ||
|
||
class ExternalMethodExtensionReturnTypeRule extends AbstractRule implements ClassAware | ||
{ | ||
use DeprecationTrait; | ||
use PhpDocTrait; | ||
use PhpTypesTrait; | ||
|
||
/** | ||
* @param \PHPMD\AbstractNode $node | ||
* | ||
* @return void | ||
*/ | ||
public function apply(AbstractNode $node): void | ||
{ | ||
if ( | ||
!$node instanceof ClassNode | ||
|| $this->isClassDeprecated($node) | ||
|| !class_exists($node->getFullQualifiedName()) | ||
) { | ||
return; | ||
} | ||
|
||
foreach ($node->getMethods() as $methodNode) { | ||
if ($this->isMethodDeprecated($methodNode)) { | ||
continue; | ||
} | ||
|
||
$className = $node->getFullQualifiedName(); | ||
|
||
$reflectionMethod = new ReflectionMethod( | ||
$className, | ||
$methodNode->getName(), | ||
); | ||
|
||
if ($reflectionMethod->hasReturnType()) { | ||
continue; | ||
} | ||
|
||
$initialMethod = $this->getInitialMethod($reflectionMethod); | ||
|
||
if ( | ||
$initialMethod === null | ||
|| $initialMethod->getDeclaringClass() === $className | ||
|| $this->isInternalClass($initialMethod->getDeclaringClass()->getName()) | ||
) { | ||
continue; | ||
} | ||
|
||
$returnType = $this->getReturnTypeByPhpDoc($initialMethod->getDocComment()); | ||
|
||
if ( | ||
$returnType == null | ||
|| $this->isTypeInPhp7NotAllowed($returnType) | ||
) { | ||
continue; | ||
} | ||
|
||
$message = sprintf( | ||
'Method `%s` must have return type.', | ||
$methodNode->getFullQualifiedName(), | ||
); | ||
|
||
$this->addViolation($methodNode, [$message]); | ||
} | ||
} | ||
|
||
/** | ||
* @param string $className | ||
* | ||
* @return bool | ||
*/ | ||
protected function isInternalClass(string $className): bool | ||
{ | ||
return strpos($className, 'Spryker') === 0; | ||
} | ||
|
||
/** | ||
* @param \ReflectionMethod $reflectionMethod | ||
* @param \ReflectionMethod|null $initialReflectionMethod | ||
* | ||
* @return \ReflectionMethod|null | ||
*/ | ||
protected function getInitialMethod(ReflectionMethod $reflectionMethod, ?ReflectionMethod $initialReflectionMethod = null): ?ReflectionMethod | ||
{ | ||
try { | ||
$prototypeMethod = $reflectionMethod->getPrototype(); | ||
} catch (ReflectionException $exception) { | ||
return $initialReflectionMethod ?? null; | ||
} | ||
|
||
return $this->getInitialMethod($prototypeMethod, $prototypeMethod); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
84 changes: 84 additions & 0 deletions
84
tests/Common/Method/ExternalMethodExtensionReturnTypeRuleTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
<?php | ||
|
||
/** | ||
* Copyright © 2016-present Spryker Systems GmbH. All rights reserved. | ||
* Use of this software requires acceptance of the Evaluation License Agreement. See LICENSE file. | ||
*/ | ||
|
||
namespace ArchitectureSnifferTest\Common\Method; | ||
|
||
use ArchitectureSniffer\Common\Method\ExternalMethodExtensionReturnTypeRule; | ||
use ArchitectureSnifferTest\AbstractArchitectureSnifferRuleTest; | ||
|
||
class ExternalMethodExtensionReturnTypeRuleTest extends AbstractArchitectureSnifferRuleTest | ||
{ | ||
/** | ||
* @return void | ||
*/ | ||
public function testRuleDoesNotApplyWhenClassExtendInternalAndDoesNotHaveReturnType(): void | ||
{ | ||
$bridgePathRule = new ExternalMethodExtensionReturnTypeRule(); | ||
$bridgePathRule->setReport($this->getReportMock(0)); | ||
$bridgePathRule->apply($this->getClassNode()); | ||
} | ||
|
||
/** | ||
* @return void | ||
*/ | ||
public function testRuleDoesNotApplyWhenClassDoesNotExtendOrImplementExternal(): void | ||
{ | ||
$bridgePathRule = new ExternalMethodExtensionReturnTypeRule(); | ||
$bridgePathRule->setReport($this->getReportMock(0)); | ||
$bridgePathRule->apply($this->getClassNode()); | ||
} | ||
|
||
/** | ||
* @return void | ||
*/ | ||
public function testRuleDoesNotApplyWhenClassExtendsExternalAndHasReturnType(): void | ||
{ | ||
$bridgePathRule = new ExternalMethodExtensionReturnTypeRule(); | ||
$bridgePathRule->setReport($this->getReportMock(0)); | ||
$bridgePathRule->apply($this->getClassNode()); | ||
} | ||
|
||
/** | ||
* @return void | ||
*/ | ||
public function testRuleDoesNotApplyWhenClassImplementsExternalAndHasReturnType(): void | ||
{ | ||
$bridgePathRule = new ExternalMethodExtensionReturnTypeRule(); | ||
$bridgePathRule->setReport($this->getReportMock(0)); | ||
$bridgePathRule->apply($this->getClassNode()); | ||
} | ||
|
||
/** | ||
* @return void | ||
*/ | ||
public function testRuleDoesNotApplyWhenClassExtendsExternalAndDoesNotHaveUnsupportedReturnType(): void | ||
{ | ||
$bridgePathRule = new ExternalMethodExtensionReturnTypeRule(); | ||
$bridgePathRule->setReport($this->getReportMock(0)); | ||
$bridgePathRule->apply($this->getClassNode()); | ||
} | ||
|
||
/** | ||
* @return void | ||
*/ | ||
public function testRuleAppliesWhenClassExtendsExternalAndDoesNotHaveReturnType(): void | ||
{ | ||
$bridgePathRule = new ExternalMethodExtensionReturnTypeRule(); | ||
$bridgePathRule->setReport($this->getReportMock(1)); | ||
$bridgePathRule->apply($this->getClassNode()); | ||
} | ||
|
||
/** | ||
* @return void | ||
*/ | ||
public function testRuleAppliesWhenClassImplementsExternalAndDoesNotHaveReturnType(): void | ||
{ | ||
$bridgePathRule = new ExternalMethodExtensionReturnTypeRule(); | ||
$bridgePathRule->setReport($this->getReportMock(1)); | ||
$bridgePathRule->apply($this->getClassNode()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 35 additions & 0 deletions
35
...ionReturnTypeRuleTest/testRuleAppliesWhenClassExtendsExternalAndDoesNotHaveReturnType.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<?php | ||
|
||
/** | ||
* MIT License | ||
* For full license information, please view the LICENSE file that was distributed with this source code. | ||
*/ | ||
|
||
namespace ArchitectureSnifferTest\Common\Method\ExternalMethodExtensionReturnTypeRuleTest\TestRuleAppliesWhenClassExtendsExternalAndDoesNotHaveReturnType; | ||
|
||
use Spryker\Zed\Module\Business\ModuleFacadeInterface; | ||
use Spryker\Zed\Module\Business; | ||
use TestRuleAppliesWhenClassExtendsExternalAndDoesNotHaveReturnType\Bar; | ||
|
||
class Foo extends Bar | ||
{ | ||
/** | ||
* @return \TestRuleAppliesWhenClassExtendsExternalAndDoesNotHaveReturnType\Bar | ||
*/ | ||
public function foo() | ||
{ | ||
return new Bar(); | ||
} | ||
} | ||
|
||
namespace TestRuleAppliesWhenClassExtendsExternalAndDoesNotHaveReturnType; | ||
|
||
class Bar | ||
{ | ||
/** | ||
* @return \TestRuleAppliesWhenClassExtendsExternalAndDoesNotHaveReturnType\Bar | ||
*/ | ||
public function foo() | ||
{ | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
...ReturnTypeRuleTest/testRuleAppliesWhenClassImplementsExternalAndDoesNotHaveReturnType.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
<?php | ||
|
||
/** | ||
* MIT License | ||
* For full license information, please view the LICENSE file that was distributed with this source code. | ||
*/ | ||
|
||
namespace ArchitectureSnifferTest\Common\Method\ExternalMethodExtensionReturnTypeRuleTest\TestRuleAppliesWhenClassImplementsExternalAndDoesNotHaveReturnType; | ||
|
||
use Spryker\Zed\Module\Business\ModuleFacadeInterface; | ||
use Spryker\Zed\Module\Business; | ||
use TestRuleAppliesWhenClassImplementsExternalAndDoesNotHaveReturnType\Bar; | ||
|
||
class Foo implements Bar | ||
{ | ||
/** | ||
* @return \TestRuleAppliesWhenClassImplementsExternalAndDoesNotHaveReturnType\Bar | ||
*/ | ||
public function foo() | ||
{ | ||
} | ||
} | ||
|
||
namespace TestRuleAppliesWhenClassImplementsExternalAndDoesNotHaveReturnType; | ||
|
||
interface Bar | ||
{ | ||
/** | ||
* @return \TestRuleAppliesWhenClassImplementsExternalAndDoesNotHaveReturnType\Bar | ||
*/ | ||
public function foo(); | ||
} |
33 changes: 33 additions & 0 deletions
33
...nsionReturnTypeRuleTest/testRuleDoesNotApplyWhenClassDoesNotExtendOrImplementExternal.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
<?php | ||
|
||
/** | ||
* MIT License | ||
* For full license information, please view the LICENSE file that was distributed with this source code. | ||
*/ | ||
|
||
namespace ArchitectureSnifferTest\Common\Method\ExternalMethodExtensionReturnTypeRuleTest\TestRuleDoesNotApplyWhenClassDoesNotExtendOrImplementExternal; | ||
|
||
use Spryker\Zed\Module\Business\ModuleFacadeInterface; | ||
use TestRuleDoesNotApplyWhenClassDoesNotExtendOrImplementExternal\Bar; | ||
use TestRuleDoesNotApplyWhenClassDoesNotExtendOrImplementExternal\Baz; | ||
|
||
class Foo extends Bar implements Baz | ||
{ | ||
/** | ||
* @return \TestRuleDoesNotApplyWhenClassDoesNotExtendOrImplementExternal\Bar | ||
*/ | ||
public function foo() | ||
{ | ||
return new Bar(); | ||
} | ||
} | ||
|
||
namespace TestRuleDoesNotApplyWhenClassDoesNotExtendOrImplementExternal; | ||
|
||
class Bar | ||
{ | ||
} | ||
|
||
interface Baz | ||
{ | ||
} |
34 changes: 34 additions & 0 deletions
34
...eturnTypeRuleTest/testRuleDoesNotApplyWhenClassExtendInternalAndDoesNotHaveReturnType.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<?php | ||
|
||
/** | ||
* MIT License | ||
* For full license information, please view the LICENSE file that was distributed with this source code. | ||
*/ | ||
|
||
namespace ArchitectureSnifferTest\Common\Method\ExternalMethodExtensionReturnTypeRuleTest\TestRuleDoesNotApplyWhenClassExtendInternalAndDoesNotHaveReturnType; | ||
|
||
use Spryker\TestRuleDoesNotApplyWhenClassExtendInternalAndDoesNotHaveReturnType\Bar; | ||
use Spryker\Zed\Module\Business\ModuleFacadeInterface; | ||
use Spryker\Zed\Module\Business; | ||
|
||
class Foo extends Bar | ||
{ | ||
/** | ||
* @return bool | ||
*/ | ||
public function foo() | ||
{ | ||
} | ||
} | ||
|
||
namespace Spryker\TestRuleDoesNotApplyWhenClassExtendInternalAndDoesNotHaveReturnType; | ||
|
||
class Bar | ||
{ | ||
/** | ||
* @return bool | ||
*/ | ||
public function foo() | ||
{ | ||
} | ||
} |
Oops, something went wrong.