Merge pull request #565 from rectorphp/symfony-container-fixes

Fix interface suffix property naming, resolve to parent interface if not accessible
This commit is contained in:
Tomáš Votruba 2018-08-09 15:09:53 +02:00 committed by GitHub
commit 4fb91f72bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 57 additions and 15 deletions

View File

@ -4,9 +4,12 @@ namespace Rector\Symfony\Bridge;
use Rector\Bridge\Contract\AnalyzedApplicationContainerInterface;
use Rector\Configuration\Option;
use Rector\Exception\ShouldNotHappenException;
use Rector\Symfony\Bridge\DependencyInjection\ContainerFactory;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symplify\PackageBuilder\Parameter\ParameterProvider;
use Throwable;
final class DefaultAnalyzedSymfonyApplicationContainer implements AnalyzedApplicationContainerInterface
{
@ -39,13 +42,37 @@ final class DefaultAnalyzedSymfonyApplicationContainer implements AnalyzedApplic
{
$container = $this->getContainer();
if ($container->has($name)) {
$definition = $container->get($name);
return get_class($definition);
if (! $container->has($name)) {
return null;
}
return null;
try {
$service = $container->get($name);
} catch (Throwable $throwable) {
throw new ShouldNotHappenException(sprintf(
'Service type for "%s" name was not found in container of your Symfony application.',
$name
));
}
$serviceClass = get_class($service);
if ($container->has($serviceClass)) {
return $serviceClass;
}
// the type was not found in container → use it's interface or parent
// mimics: \Symfony\Component\DependencyInjection\Compiler\AutowirePass::getAliasesSuggestionForType()
foreach (class_implements($serviceClass) + class_parents($serviceClass) as $parent) {
if ($container->has($parent) && ! $container->findDefinition($parent)->isAbstract()) {
return $parent;
}
}
throw new ShouldNotHappenException(sprintf(
'Type "%s" was found for "%s" service name in container of your Symfony application, but it is not accessible.',
get_class($service),
$name
));
}
public function hasService(string $name): bool
@ -55,6 +82,9 @@ final class DefaultAnalyzedSymfonyApplicationContainer implements AnalyzedApplic
return $container->has($name);
}
/**
* @return ContainerBuilder
*/
private function getContainer(): Container
{
$kernelClass = $this->parameterProvider->provideParameter(Option::KERNEL_CLASS_PARAMETER);

View File

@ -19,6 +19,9 @@ final class GetToConstructorInjectionRector extends AbstractToConstructorInjecti
*/
private $traitClass;
/**
* @todo merge to $getMethodAwareTypes
*/
public function __construct(
string $controllerClass = 'Symfony\Bundle\FrameworkBundle\Controller\Controller',
string $traitClass = 'Symfony\Bundle\FrameworkBundle\Controller\ControllerTrait'

View File

@ -22,10 +22,10 @@ final class SomeKernelClass extends Kernel
protected function build(ContainerBuilder $containerBuilder): void
{
$containerBuilder->register('some_service', 'stdClass');
$containerBuilder->register('stdClass', 'stdClass');
$containerBuilder->setAlias('some_service', 'stdClass');
$containerBuilder->register('translator.data_collector', SomeTranslator::class);
$containerBuilder->setAlias('translator', 'translator.data_collector');
$containerBuilder->setAlias(SomeTranslatorInterface::class, 'translator.data_collector');
}

View File

@ -2,7 +2,7 @@
namespace Rector\Symfony\Tests\Rector\FrameworkBundle\AbstractToConstructorInjectionRectorSource;
final class SomeTranslator
final class SomeTranslator implements SomeTranslatorInterface
{
}

View File

@ -5,10 +5,10 @@ use Rector\Symfony\Tests\FrameworkBundle\ContainerGetToConstructorInjectionRecto
final class AnotherCommand extends ContainerAwareParentClass
{
/**
* @var \Rector\Symfony\Tests\Rector\FrameworkBundle\AbstractToConstructorInjectionRectorSource\SomeTranslator
* @var \Rector\Symfony\Tests\Rector\FrameworkBundle\AbstractToConstructorInjectionRectorSource\SomeTranslatorInterface
*/
private $someTranslator;
public function __construct(\Rector\Symfony\Tests\Rector\FrameworkBundle\AbstractToConstructorInjectionRectorSource\SomeTranslator $someTranslator)
public function __construct(\Rector\Symfony\Tests\Rector\FrameworkBundle\AbstractToConstructorInjectionRectorSource\SomeTranslatorInterface $someTranslator)
{
$this->someTranslator = $someTranslator;
}

View File

@ -6,10 +6,10 @@ class ClassWithNamedServiceAndTrait
{
use GetTrait;
/**
* @var \Rector\Symfony\Tests\Rector\FrameworkBundle\AbstractToConstructorInjectionRectorSource\SomeTranslator
* @var \Rector\Symfony\Tests\Rector\FrameworkBundle\AbstractToConstructorInjectionRectorSource\SomeTranslatorInterface
*/
private $someTranslator;
public function __construct(\Rector\Symfony\Tests\Rector\FrameworkBundle\AbstractToConstructorInjectionRectorSource\SomeTranslator $someTranslator)
public function __construct(\Rector\Symfony\Tests\Rector\FrameworkBundle\AbstractToConstructorInjectionRectorSource\SomeTranslatorInterface $someTranslator)
{
$this->someTranslator = $someTranslator;
}

View File

@ -5,10 +5,10 @@ use Rector\Symfony\Tests\Rector\FrameworkBundle\GetToConstructorInjectionRector\
class ClassWithNamedServiceAndParentTrait extends ParentClassWithGetTrait
{
/**
* @var \Rector\Symfony\Tests\Rector\FrameworkBundle\AbstractToConstructorInjectionRectorSource\SomeTranslator
* @var \Rector\Symfony\Tests\Rector\FrameworkBundle\AbstractToConstructorInjectionRectorSource\SomeTranslatorInterface
*/
private $someTranslator;
public function __construct(\Rector\Symfony\Tests\Rector\FrameworkBundle\AbstractToConstructorInjectionRectorSource\SomeTranslator $someTranslator)
public function __construct(\Rector\Symfony\Tests\Rector\FrameworkBundle\AbstractToConstructorInjectionRectorSource\SomeTranslatorInterface $someTranslator)
{
$this->someTranslator = $someTranslator;
}

View File

@ -4,6 +4,7 @@ parameters:
# missuse of interface and class
- '#Parameter \#1 (.*?) expects Symfony\\Component\\DependencyInjection\\ContainerBuilder, Symfony\\Component\\DependencyInjection\\ContainerInterface given#' # 2
- '#Method Rector\\Symfony\\Bridge\\DefaultAnalyzedSymfonyApplicationContainer::getContainer\(\) should return Symfony\\Component\\DependencyInjection\\ContainerBuilder but returns Symfony\\Component\\DependencyInjection\\Container#' # 1
# 0.10.2
# false positives & ->toString() methods

View File

@ -2,6 +2,8 @@
namespace Rector\Naming;
use Nette\Utils\Strings;
final class PropertyNaming
{
public function fqnToVariableName(string $fqn): string
@ -12,7 +14,13 @@ final class PropertyNaming
public function fqnToShortName(string $fqn): string
{
$nameSpaceParts = explode('\\', $fqn);
return end($nameSpaceParts);
$lastNamePart = end($nameSpaceParts);
if (Strings::endsWith($lastNamePart, 'Interface')) {
return Strings::substring($lastNamePart, 0, - strlen('Interface'));
}
return $lastNamePart;
}
/**