add PHPUnitEnvironment

This commit is contained in:
Tomas Votruba 2019-08-10 12:05:18 +02:00
parent 4b584b9507
commit 1f9f5c7e0d
7 changed files with 91 additions and 24 deletions

View File

@ -95,6 +95,7 @@ parameters:
Symplify\CodingStandard\Sniffs\CleanCode\ForbiddenStaticFunctionSniff:
- 'src/Util/*.php'
- 'packages/BetterPhpDocParser/src/Annotation/AnnotationNaming.php'
- 'src/Testing/PHPUnit/PHPUnitEnvironment.php'
Symplify\CodingStandard\Fixer\Naming\PropertyNameMatchingTypeFixer:
- 'packages/NodeTypeResolver/src/PHPStan/Scope/NodeScopeResolver.php'

View File

@ -12,6 +12,7 @@ use Rector\NodeContainer\ParsedNodesByType;
use Rector\PhpParser\Node\Manipulator\ClassManipulator;
use Rector\PhpParser\Node\Resolver\NameResolver;
use Rector\PhpParser\NodeTraverser\CallableNodeTraverser;
use Rector\Testing\PHPUnit\PHPUnitEnvironment;
final class SetterOnlyMethodAnalyzer
{
@ -58,7 +59,7 @@ final class SetterOnlyMethodAnalyzer
*/
public function provideSetterOnlyPropertiesAndMethodsByType(): array
{
if ($this->propertiesAndMethodsToRemoveByType !== []) {
if ($this->propertiesAndMethodsToRemoveByType !== [] && ! PHPUnitEnvironment::isPHPUnitRun()) {
return $this->propertiesAndMethodsToRemoveByType;
}

View File

@ -3,7 +3,10 @@
namespace Rector\DeadCode\Rector\Class_;
use PhpParser\Node;
use PhpParser\Node\Expr\Assign;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Stmt\ClassMethod;
use PhpParser\Node\Stmt\Property;
use Rector\DeadCode\Analyzer\SetterOnlyMethodAnalyzer;
@ -75,11 +78,11 @@ CODE_SAMPLE
*/
public function getNodeTypes(): array
{
return [Property::class, MethodCall::class, ClassMethod::class];
return [Property::class, MethodCall::class, ClassMethod::class, Assign::class];
}
/**
* @param Property|MethodCall|ClassMethod $node
* @param Property|MethodCall|ClassMethod|Assign $node
*/
public function refactor(Node $node): ?Node
{
@ -88,47 +91,92 @@ CODE_SAMPLE
return null;
}
// 1. remove class properties
if ($node instanceof Property) {
if ($this->isNames($node, $setterOnlyPropertiesAndMethods['properties'] ?? [])) {
$this->removeNode($node);
}
}
// 2. remove class methods
if ($node instanceof ClassMethod) {
if ($this->isNames($node, $setterOnlyPropertiesAndMethods['methods'] ?? [])) {
$this->removeNode($node);
}
}
// 3. remove method calls
// remove method calls
if ($node instanceof MethodCall) {
if ($this->isNames($node->name, $setterOnlyPropertiesAndMethods['methods'] ?? [])) {
$this->removeNode($node);
}
return null;
}
$this->processClassStmts($node, $setterOnlyPropertiesAndMethods);
return null;
}
/**
* @param Property|ClassMethod|MethodCall $node
* @param Property|ClassMethod|MethodCall|Assign $node
* @return string[][]][]|null
*/
private function resolveSetterOnlyPropertiesAndMethodsForClass(Node $node): ?array
{
if ($node instanceof Property || $node instanceof ClassMethod) {
$className = $node->getAttribute(AttributeKey::CLASS_NAME);
} elseif ($node instanceof MethodCall) {
if ($node instanceof MethodCall) {
$className = $this->getTypes($node->var)[0] ?? null;
if ($className === null) {
return null;
}
} else {
$className = $node->getAttribute(AttributeKey::CLASS_NAME);
}
$setterOnlyPropertiesAndMethodsByType = $this->setterOnlyMethodAnalyzer->provideSetterOnlyPropertiesAndMethodsByType();
return $setterOnlyPropertiesAndMethodsByType[$className] ?? null;
}
/**
* @param Property|Assign|ClassMethod $node
* @param string[][] $setterOnlyPropertiesAndMethods
*/
private function processClassStmts(Node $node, array $setterOnlyPropertiesAndMethods): void
{
$propertyNames = $setterOnlyPropertiesAndMethods['properties'] ?? [];
$methodNames = $setterOnlyPropertiesAndMethods['methods'] ?? [];
// 1. remove class properties
if ($node instanceof Property) {
if ($this->isNames($node, $propertyNames)) {
$this->removeNode($node);
}
}
// 2. remove class inner assigns
if ($this->isThisVariableAssign($node)) {
/** @var Assign $node */
$propertyFetch = $node->var;
/** @var PropertyFetch $propertyFetch */
if ($this->isNames($propertyFetch->name, $propertyNames)) {
$this->removeNode($node);
}
}
// 3. remove class methods
if ($node instanceof ClassMethod) {
if ($this->isNames($node, $methodNames)) {
$this->removeNode($node);
}
}
}
/**
* Checks:
* $this->x = y;
*/
private function isThisVariableAssign(Node $node): bool
{
if (! $node instanceof Assign) {
return false;
}
if (! $node->var instanceof PropertyFetch) {
return false;
}
if (! $node->var->var instanceof Variable) {
return false;
}
return $this->isName($node->var->var, 'this');
}
}

View File

@ -4,6 +4,7 @@ namespace Rector\PhpSpecToPHPUnit;
use PhpParser\Node\Identifier;
use PhpParser\Node\Stmt\ClassMethod;
use Rector\Testing\PHPUnit\PHPUnitEnvironment;
use ReflectionMethod;
/**
@ -18,7 +19,7 @@ final class PHPUnitTypeDeclarationDecorator
}
// skip test run
if (defined('PHPUNIT_COMPOSER_INSTALL')) {
if (PHPUnitEnvironment::isPHPUnitRun()) {
return;
}

View File

@ -189,3 +189,4 @@ parameters:
- '#In method "Rector\\Rector\\AbstractRector\:\:traverseNodesWithCallable", parameter \$nodes has no type\-hint and no @param annotation\. More info\: http\://bit\.ly/usetypehint#'
- '#In method "Rector\\FileSystemRector\\Rector\\AbstractFileSystemRector\:\:traverseNodesWithCallable", parameter \$nodes has no type\-hint and no @param annotation\. More info\: http\://bit\.ly/usetypehint#'
- '#Ternary operator condition is always true#'
- '#Access to an undefined property PhpParser\\Node\\Expr\\Assign\|PhpParser\\Node\\Stmt\\ClassMethod\|PhpParser\\Node\\Stmt\\Property\:\:\$var#'

View File

@ -3,6 +3,7 @@
namespace Rector\Php;
use Rector\Configuration\Option;
use Rector\Testing\PHPUnit\PHPUnitEnvironment;
use Symplify\PackageBuilder\Parameter\ParameterProvider;
final class PhpVersionProvider
@ -26,7 +27,7 @@ final class PhpVersionProvider
}
// for tests
if (defined('PHPUNIT_COMPOSER_INSTALL') || defined('__PHPUNIT_PHAR__')) {
if (PHPUnitEnvironment::isPHPUnitRun()) {
return '7.5';
}

View File

@ -0,0 +1,14 @@
<?php declare(strict_types=1);
namespace Rector\Testing\PHPUnit;
final class PHPUnitEnvironment
{
/**
* Never ever used static methods if possible, this is just handy for tests + src to prevent duplication.
*/
public static function isPHPUnitRun(): bool
{
return defined('PHPUNIT_COMPOSER_INSTALL') || defined('__PHPUNIT_PHAR__');
}
}