[DeprecationExtractor] Deprecation class added, UnsupportedDeprecationFilter extracted

This commit is contained in:
TomasVotruba 2017-10-11 19:20:48 +02:00
parent 0bdc6aa6e8
commit fd45756be2
7 changed files with 199 additions and 86 deletions

View File

@ -81,16 +81,7 @@ final class ExtractDeprecationsCommand extends Command
count($this->deprecationCollector->getDeprecations())
));
/** @var RectorGuess[] $guessedRectors */
$guessedRectors = [];
$deprecations = $this->deprecationCollector->getDeprecations();
foreach ($deprecations as $deprecation) {
$guessedRectors[] = $this->rectorGuesser->guessFromMessageAndNode(
$deprecation['message'],
$deprecation['node']
);
}
$guessedRectors = $this->rectorGuesser->guessForDeprecations($this->deprecationCollector->getDeprecations());
foreach ($guessedRectors as $guessedRector) {
if ($this->shouldSkipGuessedRector($guessedRector)) {
@ -122,7 +113,7 @@ final class ExtractDeprecationsCommand extends Command
return true;
}
$typesToHide = [RectorGuess::YAML_CONFIGURATION, RectorGuess::SERVICE];
$typesToHide = [RectorGuess::TYPE_YAML_CONFIGURATION, RectorGuess::TYPE_SERVICE];
if (in_array($guessedRector->getGuessedRectorClass(), $typesToHide, true)) {
return true;
}

View File

@ -0,0 +1,39 @@
<?php declare(strict_types=1);
namespace Rector\DeprecationExtractor\Deprecation;
use PhpParser\Node;
final class Deprecation
{
/**
* @var string
*/
private $message;
/**
* @var Node
*/
private $node;
private function __construct(string $message, Node $node)
{
$this->message = $message;
$this->node = $node;
}
public static function createFromMessageAndNode(string $message, Node $node): self
{
return new self($message, $node);
}
public function getMessage(): string
{
return $this->message;
}
public function getNode(): Node
{
return $this->node;
}
}

View File

@ -11,20 +11,17 @@ use PhpParser\Node;
final class DeprecationCollector
{
/**
* @var string[]|Node[]
* @var Deprecation[]
*/
private $deprecations = [];
public function addDeprecation(string $message, Node $node): void
{
$this->deprecations[] = [
'message' => $message,
'node' => $node,
];
$this->deprecations[] = Deprecation::createFromMessageAndNode($message, $node);
}
/**
* @return mixed[]
* @return Deprecation[]
*/
public function getDeprecations(): array
{

View File

@ -5,6 +5,7 @@ namespace Rector\DeprecationExtractor\Rector;
use Nette\Utils\Strings;
use PhpParser\Builder\Class_;
use PhpParser\Node;
use Rector\DeprecationExtractor\Deprecation\Deprecation;
use Rector\DeprecationExtractor\RectorGuess\RectorGuess;
use Rector\DeprecationExtractor\RectorGuess\RectorGuessFactory;
use Rector\Exception\NotImplementedException;
@ -54,48 +55,49 @@ final class RectorGuesser
'Relying on its factory\'s return-type to define the class of service',
];
/**
* @var UnsupportedDeprecationFilter
*/
private $unsupportedDeprecationFilter;
public function __construct(
NodeValueResolver $nodeValueResolver,
ClassPrepender $classPrepender,
RectorGuessFactory $rectorGuessFactory
RectorGuessFactory $rectorGuessFactory,
UnsupportedDeprecationFilter $unsupportedDeprecationFilter
) {
$this->nodeValueResolver = $nodeValueResolver;
$this->classPrepender = $classPrepender;
$this->rectorGuessFactory = $rectorGuessFactory;
$this->unsupportedDeprecationFilter = $unsupportedDeprecationFilter;
}
public function guessFromMessageAndNode(string $message, Node $node): ?RectorGuess
public function guessForDeprecation(Deprecation $deprecation): ?RectorGuess
{
// @todo: group to early filter method
foreach ($this->yamlDeprecationMessages as $yamlDeprecationMessage) {
if (Strings::contains($message, $yamlDeprecationMessage)) {
return $this->rectorGuessFactory->createYamlConfiguration($message, $node);
}
if ($this->unsupportedDeprecationFilter->matches($deprecation)) {
return $this->rectorGuessFactory->
}
foreach ($this->serviceDeprecationMessages as $serviceDeprecationMessage) {
if (Strings::contains($message, $serviceDeprecationMessage)) {
return $this->rectorGuessFactory->createService($message, $node);
}
$rectorGuess = $this->processWithEarlyFilter($deprecation);
if ($rectorGuess !== null) {
return $rectorGuess;
}
$message = $this->classPrepender->completeClassToLocalMethods(
$message,
(string) $node->getAttribute(Attribute::CLASS_NAME)
$deprecation->getMessage(),
(string) $deprecation->getNode()->getAttribute(Attribute::CLASS_NAME)
);
if ($message === '') {
throw new NotImplementedException(sprintf(
'Not implemented yet. Go to "%s()" and add check for "%s" node.',
__METHOD__,
get_class($node)
get_class($deprecation->getNode())
));
}
if (Strings::contains($message, 'It will be made mandatory in') || Strings::contains($message, 'Not defining it is deprecated since')) {
return $this->rectorGuessFactory->createNewArgument($message, $node);
return $this->rectorGuessFactory->createNewArgument($message, $deprecation->getNode());
}
$result = Strings::split($message, '#use |Use#');
@ -105,69 +107,101 @@ final class RectorGuesser
return $this->rectorGuessFactory->createClassReplacer(
'...',
$message,
$node
$deprecation->getNode()
);
}
return $this->rectorGuessFactory->createMethodNameReplacerGuess(
$message,
$node
$deprecation->getNode()
);
}
return $this->rectorGuessFactory->createRemoval($message, $node);
return $this->rectorGuessFactory->createRemoval($message, $deprecation->getNode());
}
public function guess(string $message, Node $node): ?RectorGuess
/**
* @param Deprecation[] $deprecations
* @return RectorGuess[]
*/
public function guessForDeprecations(array $deprecations): array
{
// @todo: per node resolver...
if ($node instanceof Class_) {
return $this->rectorGuessFactory->createClassReplacer(
$node->namespacedName->toString(),
$message,
$node
);
$guessedRectors = [];
foreach ($deprecations as $deprecation) {
$guessedRectors[] = $this->guessForDeprecation($deprecation);
}
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)
));
return $guessedRectors;
}
private function processWithEarlyFilter(Deprecation $deprecation): ?RectorGuess
{
foreach ($this->yamlDeprecationMessages as $yamlDeprecationMessage) {
if (Strings::contains($deprecation->getMessage(), $yamlDeprecationMessage)) {
return $this->rectorGuessFactory->createYamlConfiguration($deprecation->getMessage(), $deprecation->getNode());
}
}
foreach ($this->serviceDeprecationMessages as $serviceDeprecationMessage) {
if (Strings::contains($deprecation->getMessage(), $serviceDeprecationMessage)) {
return $this->rectorGuessFactory->createService($deprecation->getMessage(), $deprecation->getNode());
}
}
return null;
}
// 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

@ -0,0 +1,52 @@
<?php declare(strict_types=1);
namespace Rector\DeprecationExtractor\Rector;
use Nette\Utils\Strings;
use Rector\DeprecationExtractor\Deprecation\Deprecation;
final class UnsupportedDeprecationFilter
{
/**
* @var string[]
*/
private $yamlDeprecationMessages = [
'Autowiring-types are deprecated since',
'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',
'configuration key',
];
/**
* @var string[]
*/
private $serviceDeprecationMessages = [
'It should either be deprecated or its implementation upgraded.',
'It should either be deprecated or its factory upgraded.',
'Service identifiers will be made case sensitive',
'Generating a dumped container without populating the method map is deprecated',
'Dumping an uncompiled ContainerBuilder is deprecated',
'service is private, ',
'service is already initialized, ',
'Relying on its factory\'s return-type to define the class of service',
];
public function matches(Deprecation $deprecation): bool
{
foreach ($this->yamlDeprecationMessages as $yamlDeprecationMessage) {
if (Strings::contains($deprecation->getMessage(), $yamlDeprecationMessage)) {
return true;
}
}
foreach ($this->serviceDeprecationMessages as $serviceDeprecationMessage) {
if (Strings::contains($deprecation->getMessage(), $serviceDeprecationMessage)) {
return true;
}
}
return false;
}
}

View File

@ -15,12 +15,12 @@ final class RectorGuess
/**
* @var string
*/
public const YAML_CONFIGURATION = 'YAML_CONFIGURATION';
public const TYPE_YAML_CONFIGURATION = 'YAML_CONFIGURATION';
/**
* @var string
*/
public const SERVICE = 'SERVICE';
public const TYPE_SERVICE = 'SERVICE';
/**
* @var string

View File

@ -39,7 +39,7 @@ final class RectorGuessFactory
public function createYamlConfiguration(string $message, Node $node): RectorGuess
{
return new RectorGuess(
RectorGuess::YAML_CONFIGURATION,
RectorGuess::TYPE_YAML_CONFIGURATION,
$node,
$message
);
@ -48,7 +48,7 @@ final class RectorGuessFactory
public function createService(string $message, Node $node): RectorGuess
{
return new RectorGuess(
RectorGuess::SERVICE,
RectorGuess::TYPE_SERVICE,
$node,
$message
);