[DeadCode] Make RemoveDefaultArgumentValueRector skip native fu… (#2145)

[DeadCode] Make RemoveDefaultArgumentValueRector skip native functions
This commit is contained in:
Tomáš Votruba 2019-10-12 15:38:20 +02:00 committed by GitHub
commit 8e46b7225b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 36 additions and 73 deletions

View File

@ -102,7 +102,7 @@ PHP
*/ */
public function refactor(Node $node): ?Node public function refactor(Node $node): ?Node
{ {
if ($node->args === []) { if ($this->shouldSkip($node)) {
return null; return null;
} }
@ -227,13 +227,26 @@ PHP
return $defaultValues; return $defaultValues;
} }
$coreFunctionReflection = $this->functionReflectionResolver->resolveCoreStubFunctionNode($nodeName); return [];
}
// unable to found /**
if ($coreFunctionReflection === null) { * @param MethodCall|StaticCall|FuncCall $node
return []; */
private function shouldSkip(Node $node): bool
{
if ($node->args === []) {
return true;
} }
return $this->resolveDefaultParamValuesFromFunctionLike($coreFunctionReflection); if (! $node instanceof FuncCall) {
return false;
}
// skip native functions, hard to analyze without stubs (stubs would make working with IDE non-practical)
/** @var string $functionName */
$functionName = $this->getName($node);
return $this->functionReflectionResolver->isPhpNativeFunction($functionName);
} }
} }

View File

@ -9,19 +9,3 @@ class SystemFunction
trigger_error('Error message', E_USER_NOTICE); trigger_error('Error message', E_USER_NOTICE);
} }
} }
?>
-----
<?php
namespace Rector\DeadCode\Tests\Rector\MethodCall\RemoveDefaultArgumentValueRector\Fixture;
class SystemFunction
{
public function run()
{
trigger_error('Error message');
}
}
?>

View File

@ -22,7 +22,7 @@ final class RemoveDefaultArgumentValueRectorTest extends AbstractRectorTestCase
yield [__DIR__ . '/Fixture/skip_previous_order.php.inc']; yield [__DIR__ . '/Fixture/skip_previous_order.php.inc'];
yield [__DIR__ . '/Fixture/function.php.inc']; yield [__DIR__ . '/Fixture/function.php.inc'];
yield [__DIR__ . '/Fixture/user_vendor_function.php.inc']; yield [__DIR__ . '/Fixture/user_vendor_function.php.inc'];
yield [__DIR__ . '/Fixture/system_function.php.inc']; yield [__DIR__ . '/Fixture/skip_system_function.php.inc'];
} }
protected function getRectorClass(): string protected function getRectorClass(): string

View File

@ -25,3 +25,6 @@ services:
PHPStan\Analyser\ScopeFactory: PHPStan\Analyser\ScopeFactory:
factory: ['@Rector\NodeTypeResolver\DependencyInjection\PHPStanServicesFactory', 'createScopeFactory'] factory: ['@Rector\NodeTypeResolver\DependencyInjection\PHPStanServicesFactory', 'createScopeFactory']
PHPStan\Reflection\SignatureMap\SignatureMapProvider:
factory: ['@Rector\NodeTypeResolver\DependencyInjection\PHPStanServicesFactory', 'createSignatureMapProvider']

View File

@ -8,6 +8,7 @@ use PHPStan\Analyser\ScopeFactory;
use PHPStan\Analyser\TypeSpecifier; use PHPStan\Analyser\TypeSpecifier;
use PHPStan\Broker\Broker; use PHPStan\Broker\Broker;
use PHPStan\DependencyInjection\ContainerFactory; use PHPStan\DependencyInjection\ContainerFactory;
use PHPStan\Reflection\SignatureMap\SignatureMapProvider;
final class PHPStanServicesFactory final class PHPStanServicesFactory
{ {
@ -47,6 +48,11 @@ final class PHPStanServicesFactory
return $this->container->getByType(TypeSpecifier::class); return $this->container->getByType(TypeSpecifier::class);
} }
public function createSignatureMapProvider(): SignatureMapProvider
{
return $this->container->getByType(SignatureMapProvider::class);
}
public function createScopeFactory(): ScopeFactory public function createScopeFactory(): ScopeFactory
{ {
return $this->container->getByType(ScopeFactory::class); return $this->container->getByType(ScopeFactory::class);

View File

@ -2,65 +2,22 @@
namespace Rector\Reflection; namespace Rector\Reflection;
use PhpParser\Node; use PHPStan\Reflection\SignatureMap\SignatureMapProvider;
use PhpParser\Node\Stmt\Function_;
use Rector\Exception\ShouldNotHappenException;
use Rector\PhpParser\Node\BetterNodeFinder;
use Rector\PhpParser\Parser\Parser;
final class FunctionReflectionResolver final class FunctionReflectionResolver
{ {
/** /**
* @var string[] * @var SignatureMapProvider
*/ */
private const POSSIBLE_CORE_STUB_LOCATIONS = [ private $signatureMapProvider;
__DIR__ . '/../../../../jetbrains/phpstorm-stubs/Core/Core.php',
__DIR__ . '/../../vendor/jetbrains/phpstorm-stubs/Core/Core.php',
];
/** public function __construct(SignatureMapProvider $signatureMapProvider)
* @var Parser
*/
private $parser;
/**
* @var BetterNodeFinder
*/
private $betterNodeFinder;
public function __construct(Parser $parser, BetterNodeFinder $betterNodeFinder)
{ {
$this->parser = $parser; $this->signatureMapProvider = $signatureMapProvider;
$this->betterNodeFinder = $betterNodeFinder;
} }
public function resolveCoreStubFunctionNode(string $nodeName): ?Function_ public function isPhpNativeFunction(string $functionName): bool
{ {
$stubFileLocation = $this->resolveCoreStubLocation(); return $this->signatureMapProvider->hasFunctionSignature($functionName);
$nodes = $this->parser->parseFile($stubFileLocation);
/** @var Function_|null $function */
$function = $this->betterNodeFinder->findFirst($nodes, function (Node $node) use ($nodeName): bool {
if (! $node instanceof Function_) {
return false;
}
return (string) $node->name === $nodeName;
});
return $function;
}
private function resolveCoreStubLocation(): string
{
foreach (self::POSSIBLE_CORE_STUB_LOCATIONS as $possibleCoreStubLocation) {
if (file_exists($possibleCoreStubLocation)) {
/** @var string $possibleCoreStubLocation */
return $possibleCoreStubLocation;
}
}
throw new ShouldNotHappenException();
} }
} }