[DeprecationExtractor] provide more context to reported deprecations

This commit is contained in:
TomasVotruba 2017-10-11 20:10:28 +02:00
parent 1d5a01fcb0
commit 56840b0b51
7 changed files with 84 additions and 108 deletions

View File

@ -7,6 +7,7 @@ use Rector\DeprecationExtractor\DeprecationExtractor;
use Rector\DeprecationExtractor\Rector\RectorGuesser;
use Rector\DeprecationExtractor\RectorGuess\RectorGuess;
use Rector\Naming\CommandNaming;
use Rector\Node\Attribute;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
@ -94,12 +95,16 @@ final class ExtractDeprecationsCommand extends Command
$this->symfonyStyle->warning($guessedRector->getGuessedRectorClass());
}
$this->symfonyStyle->writeln(' ' . $guessedRector->getMessage());
$this->symfonyStyle->newLine();
$this->symfonyStyle->writeln($guessedRector->getMessage());
// @todo: add metadata like related class, method etc. - or maybe get from NODE like
// $node->getAttribute(Attributes::CLASS_NODE)
// $node->getAttribute(Attributes::METHOD_NODE)
$node = $guessedRector->getNode();
if ($guessedRector->getGuessedRectorClass() !== 'REMOVAL') {
$this->symfonyStyle->writeln(' Namespace: ' . $node->getAttribute(Attribute::NAMESPACE));
$this->symfonyStyle->writeln(' Class: ' . $node->getAttribute(Attribute::CLASS_NAME));
$this->symfonyStyle->writeln(' Scope: ' . $node->getAttribute(Attribute::SCOPE));
}
$this->symfonyStyle->newLine(2);
}

View File

@ -8,10 +8,10 @@ use PhpParser\Node;
use Rector\DeprecationExtractor\Deprecation\Deprecation;
use Rector\DeprecationExtractor\RectorGuess\RectorGuess;
use Rector\DeprecationExtractor\RectorGuess\RectorGuessFactory;
use Rector\DeprecationExtractor\Regex\ClassAndMethodMatcher;
use Rector\Exception\NotImplementedException;
use Rector\Node\Attribute;
use Rector\NodeValueResolver\Message\ClassPrepender;
use Rector\NodeValueResolver\NodeValueResolver;
/**
* This class tries to guess, which Rector could be used to create refactoring
@ -29,16 +29,21 @@ final class RectorGuesser
*/
private $unsupportedDeprecationFilter;
/**
* @var ClassAndMethodMatcher
*/
private $classAndMethodMatcher;
public function __construct(
// NodeValueResolver $nodeValueResolver,
ClassPrepender $classPrepender,
RectorGuessFactory $rectorGuessFactory,
UnsupportedDeprecationFilter $unsupportedDeprecationFilter
UnsupportedDeprecationFilter $unsupportedDeprecationFilter,
ClassAndMethodMatcher $classAndMethodMatcher
) {
// $this->nodeValueResolver = $nodeValueResolver;
$this->classPrepender = $classPrepender;
$this->rectorGuessFactory = $rectorGuessFactory;
$this->unsupportedDeprecationFilter = $unsupportedDeprecationFilter;
$this->classAndMethodMatcher = $classAndMethodMatcher;
}
public function guessForDeprecation(Deprecation $deprecation): ?RectorGuess
@ -69,7 +74,6 @@ final class RectorGuesser
if (count($result) === 2) {
if (Strings::contains($message, 'class is deprecated')) {
return $this->rectorGuessFactory->createClassReplacer(
'...',
$message,
$deprecation->getNode()
);
@ -99,55 +103,55 @@ final class RectorGuesser
return $guessedRectors;
}
// private function guess(string $message, Node $node): ?RectorGuess
// {
// // @todo: per node resolver...
// if ($node instanceof Class_) {
// return $this->rectorGuessFactory->createClassReplacer(
// $node->namespacedName->toString(),
// $message,
// $node
// );
// }
//
// if ($node instanceof Node\Stmt\ClassMethod) {
// $classWithMethod = $this->classAndMethodMatcher->matchClassWithMethod($message);
// $localMethod = $this->classAndMethodMatcher->matchLocalMethod($message);
//
// $className = $node->getAttribute(Attribute::CLASS_NODE)->namespacedName->toString();
// $methodName = (string) $node->name . '()';
// $fqnMethodName = $className . '::' . $methodName;
//
// if ($classWithMethod === '' && $localMethod === '') {
// return $this->rectorGuessFactory->createRemoval($message, $node);
// }
//
// if ($localMethod) {
// return $this->rectorGuessFactory->createRemoval(
// $fqnMethodName . ' => ' . $className . '::' . $localMethod . '()' . $message,
// $node
// );
// }
//
// $namespacedClassWithMethod = $this->classAndMethodMatcher->matchNamespacedClassWithMethod($message);
//
// /** @var string[] $useStatements */
// $useStatements = $node->getAttribute(Attribute::USE_STATEMENTS);
// $fqnClassWithMethod = $this->completeNamespace($useStatements, $namespacedClassWithMethod);
//
// return $this->rectorGuessFactory->createRemoval(
// $fqnMethodName . '=> ' . $fqnClassWithMethod,
// $node
// );
// }
//
// throw new NotImplementedException(sprintf(
// '%s() was unable to create a Deprecation based on "%s" string and "%s" Node. Create a new method there.',
// __METHOD__,
// $message,
// get_class($node)
// ));
// }
private function guess(string $message, Node $node): ?RectorGuess
{
// @todo: per node resolver...
if ($node instanceof Class_) {
return $this->rectorGuessFactory->createClassReplacer(
$node->namespacedName->toString(),
$message,
$node
);
}
if ($node instanceof Node\Stmt\ClassMethod) {
$classWithMethod = $this->classAndMethodMatcher->matchClassWithMethod($message);
$localMethod = $this->classAndMethodMatcher->matchLocalMethod($message);
$className = $node->getAttribute(Attribute::CLASS_NODE)->namespacedName->toString();
$methodName = (string) $node->name . '()';
$fqnMethodName = $className . '::' . $methodName;
if ($classWithMethod === '' && $localMethod === '') {
return $this->rectorGuessFactory->createRemoval($message, $node);
}
if ($localMethod) {
return $this->rectorGuessFactory->createRemoval(
$fqnMethodName . ' => ' . $className . '::' . $localMethod . '()' . $message,
$node
);
}
$namespacedClassWithMethod = $this->classAndMethodMatcher->matchNamespacedClassWithMethod($message);
/** @var string[] $useStatements */
$useStatements = $node->getAttribute(Attribute::USE_STATEMENTS);
$fqnClassWithMethod = $this->completeNamespace($useStatements, $namespacedClassWithMethod);
return $this->rectorGuessFactory->createRemoval(
$fqnMethodName . '=> ' . $fqnClassWithMethod,
$node
);
}
throw new NotImplementedException(sprintf(
'%s() was unable to create a Deprecation based on "%s" string and "%s" Node. Create a new method there.',
__METHOD__,
$message,
get_class($node)
));
}
/**
* @param string[] $useStatements

View File

@ -11,11 +11,11 @@ final class UnsupportedDeprecationFilter
* @var string[]
*/
private $yamlDeprecationMessages = [
'Autowiring-types are deprecated since',
'Autowiring-types are deprecated',
'The "=" suffix that used to disable strict references',
'The XmlFileLoader will raise an exception in Symfony 4.0, instead of silently ignoring unsupported',
'The "strict" attribute used when referencing the "" service is deprecated since version 3.3 and will be removed in 4.0.',
'Service names that start with an underscore are deprecated since Symfony 3.3 and will be reserved in 4.0',
'The "strict" attribute used when referencing the "" service is deprecated',
'Service names that start with an underscore are deprecated',
'configuration key',
];

View File

@ -35,7 +35,7 @@ final class RectorGuess
public function __construct(
string $guessedRectorClass,
Node $node,
string $message = ''
string $message
) {
$this->guessedRectorClass = $guessedRectorClass;
$this->node = $node;

View File

@ -9,48 +9,28 @@ use Rector\Rector\Dynamic\MethodNameReplacerRector;
final class RectorGuessFactory
{
public function createRemoval(string $message, Node $node): RectorGuess
public function createClassReplacer(string $message, Node $node): RectorGuess
{
return new RectorGuess(
RectorGuess::TYPE_REMOVAL,
$node,
$message
);
}
public function createClassReplacer(string $className, string $message, Node $node): RectorGuess
{
return new RectorGuess(
ClassReplacerRector::class,
$node,
$className . ' - ' . $message
);
return new RectorGuess(ClassReplacerRector::class, $node, $message);
}
public function createMethodNameReplacerGuess(string $message, Node $node): RectorGuess
{
return new RectorGuess(
MethodNameReplacerRector::class,
$node,
$message
);
return new RectorGuess(MethodNameReplacerRector::class, $node, $message);
}
public function createNewArgument(string $message, Node $node): RectorGuess
{
return new RectorGuess(
MethodArgumentChangerRector::class,
$node,
$message
);
return new RectorGuess(MethodArgumentChangerRector::class, $node, $message);
}
public function createRemoval(string $message, Node $node): RectorGuess
{
return new RectorGuess(RectorGuess::TYPE_REMOVAL, $node, $message);
}
public function createUnsupported(string $message, Node $node): RectorGuess
{
return new RectorGuess(
RectorGuess::TYPE_UNSUPPORTED,
$node,
$message
);
return new RectorGuess(RectorGuess::TYPE_UNSUPPORTED, $node, $message);
}
}

View File

@ -30,9 +30,6 @@ final class DeprecationCollectorTest extends AbstractContainerAwareTestCase
__DIR__ . '/../../../../vendor/symfony/dependency-injection',
]);
$deprecations = $this->deprecationCollector->getDeprecationTriggerErrors()
+ $this->deprecationCollector->getDeprecationAnnotations();
$this->assertGreaterThanOrEqual(35, $deprecations);
$this->assertGreaterThanOrEqual(35, $this->deprecationCollector->getDeprecations());
}
}

View File

@ -2,7 +2,6 @@
namespace Rector\DeprecationExtractor\Tests;
use PhpParser\Node\Arg;
use Rector\DeprecationExtractor\Deprecation\DeprecationCollector;
use Rector\DeprecationExtractor\DeprecationExtractor;
use Rector\Tests\AbstractContainerAwareTestCase;
@ -25,16 +24,7 @@ final class DeprecationExtractorTest extends AbstractContainerAwareTestCase
public function testDeprectaionMessages(): void
{
$deprecationMessages = $this->deprecationCollector->getDeprecationAnnotations();
$this->assertCount(0, $deprecationMessages);
}
public function testDeprecationNodes(): void
{
$deprecationArgNodes = $this->deprecationCollector->getDeprecationTriggerErrors();
$this->assertCount(2, $deprecationArgNodes);
$deprecationArgNode = $deprecationArgNodes[0];
$this->assertInstanceOf(Arg::class, $deprecationArgNode);
$deprecationMessages = $this->deprecationCollector->getDeprecations();
$this->assertCount(2, $deprecationMessages);
}
}