Fix comments, improve the feature
This commit is contained in:
parent
a6292b917b
commit
4b3e9d4c96
@ -4,6 +4,7 @@ CHANGELOG
|
|||||||
4.4.0
|
4.4.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
* Added `lint:container` to check that services wiring matches type declarations
|
||||||
* Added `MailerAssertionsTrait`
|
* Added `MailerAssertionsTrait`
|
||||||
* Deprecated support for `templating` engine in `TemplateController`, use Twig instead
|
* Deprecated support for `templating` engine in `TemplateController`, use Twig instead
|
||||||
* Deprecated the `$parser` argument of `ControllerResolver::__construct()` and `DelegatingLoader::__construct()`
|
* Deprecated the `$parser` argument of `ControllerResolver::__construct()` and `DelegatingLoader::__construct()`
|
||||||
|
@ -11,19 +11,21 @@
|
|||||||
|
|
||||||
namespace Symfony\Bundle\FrameworkBundle\Command;
|
namespace Symfony\Bundle\FrameworkBundle\Command;
|
||||||
|
|
||||||
|
use Symfony\Component\Config\ConfigCache;
|
||||||
|
use Symfony\Component\Config\FileLocator;
|
||||||
use Symfony\Component\Console\Command\Command;
|
use Symfony\Component\Console\Command\Command;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
use Symfony\Component\Config\ConfigCache;
|
use Symfony\Component\DependencyInjection\Compiler\CheckTypeDeclarationsPass;
|
||||||
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
|
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
|
||||||
use Symfony\Component\DependencyInjection\Compiler\CheckTypeHintsPass;
|
|
||||||
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
|
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
|
||||||
use Symfony\Component\Config\FileLocator;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
|
||||||
|
|
||||||
class ContainerLintCommand extends Command
|
final class ContainerLintCommand extends Command
|
||||||
{
|
{
|
||||||
|
protected static $defaultName = 'lint:container';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var ContainerBuilder
|
* @var ContainerBuilder
|
||||||
*/
|
*/
|
||||||
@ -35,37 +37,33 @@ class ContainerLintCommand extends Command
|
|||||||
protected function configure()
|
protected function configure()
|
||||||
{
|
{
|
||||||
$this
|
$this
|
||||||
->setDescription('Lints container for services arguments type hints')
|
->setDescription('Ensures that arguments injected into services match type declarations')
|
||||||
->setHelp('This command will parse all your defined services and check that you are injecting service without type error based on type hints.')
|
->setHelp('This command parses service definitions and ensures that injected values match the type declarations of each services\' class.')
|
||||||
->addOption('only-used-services', 'o', InputOption::VALUE_NONE, 'Check only services that are used in your application')
|
->addOption('ignore-unused-services', 'o', InputOption::VALUE_NONE, 'Ignore unused services')
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
protected function execute(InputInterface $input, OutputInterface $output)
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
{
|
{
|
||||||
$container = $this->getContainerBuilder();
|
$container = $this->getContainerBuilder();
|
||||||
|
|
||||||
$container->setParameter('container.build_id', 'lint_container');
|
$container->setParameter('container.build_id', 'lint_container');
|
||||||
|
|
||||||
$container->addCompilerPass(
|
$container->addCompilerPass(
|
||||||
new CheckTypeHintsPass(),
|
new CheckTypeDeclarationsPass(true),
|
||||||
$input->getOption('only-used-services') ? PassConfig::TYPE_AFTER_REMOVING : PassConfig::TYPE_BEFORE_OPTIMIZATION
|
$input->getOption('ignore-unused-services') ? PassConfig::TYPE_AFTER_REMOVING : PassConfig::TYPE_OPTIMIZE,
|
||||||
|
-5
|
||||||
);
|
);
|
||||||
|
|
||||||
$container->compile();
|
$container->compile();
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private function getContainerBuilder(): ContainerBuilder
|
||||||
* Loads the ContainerBuilder from the cache.
|
|
||||||
*
|
|
||||||
* @return ContainerBuilder
|
|
||||||
*
|
|
||||||
* @throws \LogicException
|
|
||||||
*/
|
|
||||||
protected function getContainerBuilder()
|
|
||||||
{
|
{
|
||||||
if ($this->containerBuilder) {
|
if ($this->containerBuilder) {
|
||||||
return $this->containerBuilder;
|
return $this->containerBuilder;
|
||||||
@ -74,10 +72,9 @@ class ContainerLintCommand extends Command
|
|||||||
$kernel = $this->getApplication()->getKernel();
|
$kernel = $this->getApplication()->getKernel();
|
||||||
|
|
||||||
if (!$kernel->isDebug() || !(new ConfigCache($kernel->getContainer()->getParameter('debug.container.dump'), true))->isFresh()) {
|
if (!$kernel->isDebug() || !(new ConfigCache($kernel->getContainer()->getParameter('debug.container.dump'), true))->isFresh()) {
|
||||||
$buildContainer = \Closure::bind(function () { return $this->buildContainer(); }, $kernel, get_class($kernel));
|
$buildContainer = \Closure::bind(function () { return $this->buildContainer(); }, $kernel, \get_class($kernel));
|
||||||
$container = $buildContainer();
|
$container = $buildContainer();
|
||||||
$container->getCompilerPassConfig()->setRemovingPasses(array());
|
$container->getCompilerPassConfig()->setRemovingPasses([]);
|
||||||
$container->compile();
|
|
||||||
} else {
|
} else {
|
||||||
(new XmlFileLoader($container = new ContainerBuilder(), new FileLocator()))->load($kernel->getContainer()->getParameter('debug.container.dump'));
|
(new XmlFileLoader($container = new ContainerBuilder(), new FileLocator()))->load($kernel->getContainer()->getParameter('debug.container.dump'));
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ CHANGELOG
|
|||||||
4.4.0
|
4.4.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
* added `CheckTypeHintsPass` to check injected parameters type during compilation
|
* added `CheckTypeDeclarationsPass` to check injected parameters type during compilation
|
||||||
* added support for opcache.preload by generating a preloading script in the cache folder
|
* added support for opcache.preload by generating a preloading script in the cache folder
|
||||||
* added support for dumping the container in one file instead of many files
|
* added support for dumping the container in one file instead of many files
|
||||||
* deprecated support for short factories and short configurators in Yaml
|
* deprecated support for short factories and short configurators in Yaml
|
||||||
|
@ -0,0 +1,172 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\DependencyInjection\Compiler;
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
||||||
|
use Symfony\Component\DependencyInjection\Definition;
|
||||||
|
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||||
|
use Symfony\Component\DependencyInjection\Exception\InvalidParameterTypeException;
|
||||||
|
use Symfony\Component\DependencyInjection\Parameter;
|
||||||
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
|
use Symfony\Component\DependencyInjection\ServiceLocator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether injected parameters are compatible with type declarations.
|
||||||
|
*
|
||||||
|
* This pass should be run after all optimization passes.
|
||||||
|
*
|
||||||
|
* It can be added either:
|
||||||
|
* * before removing passes to check all services even if they are not currently used,
|
||||||
|
* * after removing passes to check only services are used in the app.
|
||||||
|
*
|
||||||
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
|
* @author Julien Maulny <jmaulny@darkmira.fr>
|
||||||
|
*/
|
||||||
|
final class CheckTypeDeclarationsPass extends AbstractRecursivePass
|
||||||
|
{
|
||||||
|
private const SCALAR_TYPES = ['int', 'float', 'bool', 'string'];
|
||||||
|
|
||||||
|
private $autoload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $autoload Whether services who's class in not loaded should be checked or not.
|
||||||
|
* Defaults to false to save loading code during compilation.
|
||||||
|
*/
|
||||||
|
public function __construct(bool $autoload = false)
|
||||||
|
{
|
||||||
|
$this->autoload = $autoload;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function processValue($value, $isRoot = false)
|
||||||
|
{
|
||||||
|
if (!$value instanceof Definition) {
|
||||||
|
return parent::processValue($value, $isRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$this->autoload && !class_exists($class = $value->getClass(), false) && !interface_exists($class, false)) {
|
||||||
|
return parent::processValue($value, $isRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ServiceLocator::class === $value->getClass()) {
|
||||||
|
return parent::processValue($value, $isRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($constructor = $this->getConstructor($value, false)) {
|
||||||
|
$this->checkTypeDeclarations($value, $constructor, $value->getArguments());
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($value->getMethodCalls() as $methodCall) {
|
||||||
|
$reflectionMethod = $this->getReflectionMethod($value, $methodCall[0]);
|
||||||
|
|
||||||
|
$this->checkTypeDeclarations($value, $reflectionMethod, $methodCall[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::processValue($value, $isRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws InvalidArgumentException When not enough parameters are defined for the method
|
||||||
|
*/
|
||||||
|
private function checkTypeDeclarations(Definition $checkedDefinition, \ReflectionFunctionAbstract $reflectionFunction, array $configurationArguments): void
|
||||||
|
{
|
||||||
|
$numberOfRequiredParameters = $reflectionFunction->getNumberOfRequiredParameters();
|
||||||
|
|
||||||
|
if (\count($configurationArguments) < $numberOfRequiredParameters) {
|
||||||
|
throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": "%s::%s()" requires %d arguments, %d passed.', $this->currentId, $reflectionFunction->class, $reflectionFunction->name, $numberOfRequiredParameters, \count($configurationArguments)));
|
||||||
|
}
|
||||||
|
|
||||||
|
$reflectionParameters = $reflectionFunction->getParameters();
|
||||||
|
$checksCount = min($reflectionFunction->getNumberOfParameters(), \count($configurationArguments));
|
||||||
|
|
||||||
|
for ($i = 0; $i < $checksCount; ++$i) {
|
||||||
|
if (!$reflectionParameters[$i]->hasType() || $reflectionParameters[$i]->isVariadic()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->checkType($checkedDefinition, $configurationArguments[$i], $reflectionParameters[$i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($reflectionFunction->isVariadic() && ($lastParameter = end($reflectionParameters))->hasType()) {
|
||||||
|
$variadicParameters = \array_slice($configurationArguments, $lastParameter->getPosition());
|
||||||
|
|
||||||
|
foreach ($variadicParameters as $variadicParameter) {
|
||||||
|
$this->checkType($checkedDefinition, $variadicParameter, $lastParameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws InvalidParameterTypeException When a parameter is not compatible with the declared type
|
||||||
|
*/
|
||||||
|
private function checkType(Definition $checkedDefinition, $configurationArgument, \ReflectionParameter $parameter): void
|
||||||
|
{
|
||||||
|
$parameterTypeName = $parameter->getType()->getName();
|
||||||
|
|
||||||
|
$referencedDefinition = $configurationArgument;
|
||||||
|
|
||||||
|
if ($referencedDefinition instanceof Reference) {
|
||||||
|
if (!$this->container->has($referencedDefinition)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$referencedDefinition = $this->container->findDefinition((string) $referencedDefinition);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('self' === $parameterTypeName) {
|
||||||
|
$parameterTypeName = $parameter->getDeclaringClass()->getName();
|
||||||
|
}
|
||||||
|
if ('static' === $parameterTypeName) {
|
||||||
|
$parameterTypeName = $checkedDefinition->getClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($referencedDefinition instanceof Definition) {
|
||||||
|
$class = $referencedDefinition->getClass();
|
||||||
|
|
||||||
|
if (!$class || (!$this->autoload && !class_exists($class, false) && !interface_exists($class, false))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_a($class, $parameterTypeName, true)) {
|
||||||
|
throw new InvalidParameterTypeException($this->currentId, $class, $parameter);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (null === $configurationArgument && $parameter->allowsNull()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (\in_array($parameterTypeName, self::SCALAR_TYPES, true) && is_scalar($configurationArgument)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('iterable' === $parameterTypeName && $configurationArgument instanceof IteratorArgument) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('Traversable' === $parameterTypeName && $configurationArgument instanceof IteratorArgument) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($configurationArgument instanceof Parameter) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$checkFunction = sprintf('is_%s', $parameter->getType()->getName());
|
||||||
|
|
||||||
|
if (!$parameter->getType()->isBuiltin() || !$checkFunction($configurationArgument)) {
|
||||||
|
throw new InvalidParameterTypeException($this->currentId, \gettype($configurationArgument), $parameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,184 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the Symfony package.
|
|
||||||
*
|
|
||||||
* (c) Fabien Potencier <fabien@symfony.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Symfony\Component\DependencyInjection\Compiler;
|
|
||||||
|
|
||||||
use Symfony\Component\DependencyInjection\Definition;
|
|
||||||
use Symfony\Component\DependencyInjection\Reference;
|
|
||||||
use Symfony\Component\DependencyInjection\ServiceLocator;
|
|
||||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
|
||||||
use Symfony\Component\DependencyInjection\Exception\InvalidParameterTypeHintException;
|
|
||||||
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether injected parameters types are compatible with type hints.
|
|
||||||
* This pass should be run after all optimization passes.
|
|
||||||
* So it can be added either:
|
|
||||||
* * before removing (PassConfig::TYPE_BEFORE_REMOVING) so that it will check
|
|
||||||
* all services, even if they are not currently used,
|
|
||||||
* * after removing (PassConfig::TYPE_AFTER_REMOVING) so that it will check
|
|
||||||
* only services you are using.
|
|
||||||
*
|
|
||||||
* @author Nicolas Grekas <p@tchwork.com>
|
|
||||||
* @author Julien Maulny <jmaulny@darkmira.fr>
|
|
||||||
*/
|
|
||||||
class CheckTypeHintsPass extends AbstractRecursivePass
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* If set to true, allows to autoload classes during compilation
|
|
||||||
* in order to check type hints on parameters that are not yet loaded.
|
|
||||||
* Defaults to false to prevent code loading during compilation.
|
|
||||||
*
|
|
||||||
* @param bool
|
|
||||||
*/
|
|
||||||
private $autoload;
|
|
||||||
|
|
||||||
public function __construct(bool $autoload = false)
|
|
||||||
{
|
|
||||||
$this->autoload = $autoload;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
protected function processValue($value, $isRoot = false)
|
|
||||||
{
|
|
||||||
if (!$value instanceof Definition) {
|
|
||||||
return parent::processValue($value, $isRoot);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$this->autoload && !class_exists($className = $this->getClassName($value), false) && !interface_exists($className, false)) {
|
|
||||||
return parent::processValue($value, $isRoot);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ServiceLocator::class === $value->getClass()) {
|
|
||||||
return parent::processValue($value, $isRoot);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null !== $constructor = $this->getConstructor($value, false)) {
|
|
||||||
$this->checkArgumentsTypeHints($constructor, $value->getArguments());
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach ($value->getMethodCalls() as $methodCall) {
|
|
||||||
$reflectionMethod = $this->getReflectionMethod($value, $methodCall[0]);
|
|
||||||
|
|
||||||
$this->checkArgumentsTypeHints($reflectionMethod, $methodCall[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return parent::processValue($value, $isRoot);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check type hints for every parameter of a method/constructor.
|
|
||||||
*
|
|
||||||
* @throws InvalidArgumentException on type hint incompatibility
|
|
||||||
*/
|
|
||||||
private function checkArgumentsTypeHints(\ReflectionFunctionAbstract $reflectionFunction, array $configurationArguments): void
|
|
||||||
{
|
|
||||||
$numberOfRequiredParameters = $reflectionFunction->getNumberOfRequiredParameters();
|
|
||||||
|
|
||||||
if (count($configurationArguments) < $numberOfRequiredParameters) {
|
|
||||||
throw new InvalidArgumentException(sprintf(
|
|
||||||
'Invalid definition for service "%s": "%s::%s()" requires %d arguments, %d passed.', $this->currentId, $reflectionFunction->class, $reflectionFunction->name, $numberOfRequiredParameters, count($configurationArguments)));
|
|
||||||
}
|
|
||||||
|
|
||||||
$reflectionParameters = $reflectionFunction->getParameters();
|
|
||||||
$checksCount = min($reflectionFunction->getNumberOfParameters(), count($configurationArguments));
|
|
||||||
|
|
||||||
for ($i = 0; $i < $checksCount; ++$i) {
|
|
||||||
if (!$reflectionParameters[$i]->hasType() || $reflectionParameters[$i]->isVariadic()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->checkTypeHint($configurationArguments[$i], $reflectionParameters[$i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($reflectionFunction->isVariadic() && ($lastParameter = end($reflectionParameters))->hasType()) {
|
|
||||||
$variadicParameters = array_slice($configurationArguments, $lastParameter->getPosition());
|
|
||||||
|
|
||||||
foreach ($variadicParameters as $variadicParameter) {
|
|
||||||
$this->checkTypeHint($variadicParameter, $lastParameter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check type hints compatibility between
|
|
||||||
* a definition argument and a reflection parameter.
|
|
||||||
*
|
|
||||||
* @throws InvalidArgumentException on type hint incompatibility
|
|
||||||
*/
|
|
||||||
private function checkTypeHint($configurationArgument, \ReflectionParameter $parameter): void
|
|
||||||
{
|
|
||||||
$referencedDefinition = $configurationArgument;
|
|
||||||
|
|
||||||
if ($referencedDefinition instanceof Reference) {
|
|
||||||
$referencedDefinition = $this->container->findDefinition((string) $referencedDefinition);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($referencedDefinition instanceof Definition) {
|
|
||||||
$class = $this->getClassName($referencedDefinition);
|
|
||||||
|
|
||||||
if (!$this->autoload && !class_exists($class, false)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_a($class, $parameter->getType()->getName(), true)) {
|
|
||||||
throw new InvalidParameterTypeHintException($this->currentId, null === $class ? 'null' : $class, $parameter);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (null === $configurationArgument && $parameter->allowsNull()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($parameter->getType()->isBuiltin() && is_scalar($configurationArgument)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('iterable' === $parameter->getType()->getName() && $configurationArgument instanceof IteratorArgument) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ('Traversable' === $parameter->getType()->getName() && $configurationArgument instanceof IteratorArgument) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$checkFunction = 'is_'.$parameter->getType()->getName();
|
|
||||||
|
|
||||||
if (!$parameter->getType()->isBuiltin() || !$checkFunction($configurationArgument)) {
|
|
||||||
throw new InvalidParameterTypeHintException($this->currentId, gettype($configurationArgument), $parameter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get class name from value that can have a factory.
|
|
||||||
*
|
|
||||||
* @return string|null
|
|
||||||
*/
|
|
||||||
private function getClassName($value)
|
|
||||||
{
|
|
||||||
if (is_array($factory = $value->getFactory())) {
|
|
||||||
list($class, $method) = $factory;
|
|
||||||
if ($class instanceof Reference) {
|
|
||||||
$class = $this->container->findDefinition((string) $class)->getClass();
|
|
||||||
} elseif (null === $class) {
|
|
||||||
$class = $value->getClass();
|
|
||||||
} elseif ($class instanceof Definition) {
|
|
||||||
$class = $this->getClassName($class);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$class = $value->getClass();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $class;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\DependencyInjection\Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown when trying to inject a parameter into a constructor/method with an incompatible type.
|
||||||
|
*
|
||||||
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
|
* @author Julien Maulny <jmaulny@darkmira.fr>
|
||||||
|
*/
|
||||||
|
class InvalidParameterTypeException extends InvalidArgumentException
|
||||||
|
{
|
||||||
|
public function __construct(string $serviceId, string $type, \ReflectionParameter $parameter)
|
||||||
|
{
|
||||||
|
parent::__construct(sprintf('Invalid definition for service "%s": argument %d of "%s::%s" accepts "%s", "%s" passed.', $serviceId, 1 + $parameter->getPosition(), $parameter->getDeclaringClass()->getName(), $parameter->getDeclaringFunction()->getName(), $parameter->getType()->getName(), $type));
|
||||||
|
}
|
||||||
|
}
|
@ -1,28 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of the Symfony package.
|
|
||||||
*
|
|
||||||
* (c) Fabien Potencier <fabien@symfony.com>
|
|
||||||
*
|
|
||||||
* For the full copyright and license information, please view the LICENSE
|
|
||||||
* file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Symfony\Component\DependencyInjection\Exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Thrown when trying to inject a parameter into a constructor/method
|
|
||||||
* with a type that does not match type hint.
|
|
||||||
*
|
|
||||||
* @author Nicolas Grekas <p@tchwork.com>
|
|
||||||
* @author Julien Maulny <jmaulny@darkmira.fr>
|
|
||||||
*/
|
|
||||||
class InvalidParameterTypeHintException extends InvalidArgumentException
|
|
||||||
{
|
|
||||||
public function __construct(string $serviceId, string $typeHint, \ReflectionParameter $parameter)
|
|
||||||
{
|
|
||||||
parent::__construct(sprintf(
|
|
||||||
'Invalid definition for service "%s": argument %d of "%s::%s" requires a "%s", "%s" passed.', $serviceId, $parameter->getPosition(), $parameter->getDeclaringClass()->getName(), $parameter->getDeclaringFunction()->getName(), $parameter->getType()->getName(), $typeHint));
|
|
||||||
}
|
|
||||||
}
|
|
@ -12,77 +12,73 @@
|
|||||||
namespace Symfony\Component\DependencyInjection\Tests\Compiler;
|
namespace Symfony\Component\DependencyInjection\Tests\Compiler;
|
||||||
|
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
||||||
|
use Symfony\Component\DependencyInjection\Compiler\CheckTypeDeclarationsPass;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
use Symfony\Component\DependencyInjection\Reference;
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeDeclarationsPass\Bar;
|
||||||
use Symfony\Component\DependencyInjection\Compiler\CheckTypeHintsPass;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeDeclarationsPass\BarMethodCall;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\Bar;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeDeclarationsPass\BarOptionalArgument;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\BarOptionalArgument;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeDeclarationsPass\BarOptionalArgumentNotNull;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\BarOptionalArgumentNotNull;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeDeclarationsPass\Foo;
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\BarMethodCall;
|
|
||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\Foo;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Nicolas Grekas <p@tchwork.com>
|
* @author Nicolas Grekas <p@tchwork.com>
|
||||||
* @author Julien Maulny <jmaulny@darkmira.fr>
|
* @author Julien Maulny <jmaulny@darkmira.fr>
|
||||||
*/
|
*/
|
||||||
class CheckTypeHintsPassTest extends TestCase
|
class CheckTypeDeclarationsPassTest extends TestCase
|
||||||
{
|
{
|
||||||
/**
|
public function testProcessThrowsExceptionOnInvalidTypesConstructorArguments()
|
||||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
|
||||||
* @expectedExceptionMessage Invalid definition for service "bar": argument 0 of "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\Bar::__construct" requires a "stdClass", "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\Foo" passed
|
|
||||||
*/
|
|
||||||
public function testProcessThrowsExceptionOnInvalidTypeHintsConstructorArguments()
|
|
||||||
{
|
{
|
||||||
|
$this->expectException(\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException::class);
|
||||||
|
$this->expectExceptionMessage('Invalid definition for service "bar": argument 1 of "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\Bar::__construct" accepts "stdClass", "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\Foo" passed.');
|
||||||
|
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
$container->register('foo', Foo::class);
|
$container->register('foo', Foo::class);
|
||||||
$container->register('bar', Bar::class)
|
$container->register('bar', Bar::class)
|
||||||
->addArgument(new Reference('foo'));
|
->addArgument(new Reference('foo'));
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function testProcessThrowsExceptionOnInvalidTypesMethodCallArguments()
|
||||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
|
||||||
* @expectedExceptionMessage Invalid definition for service "bar": argument 0 of "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\BarMethodCall::setFoo" requires a "stdClass", "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\Foo" passed
|
|
||||||
*/
|
|
||||||
public function testProcessThrowsExceptionOnInvalidTypeHintsMethodCallArguments()
|
|
||||||
{
|
{
|
||||||
|
$this->expectException(\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException::class);
|
||||||
|
$this->expectExceptionMessage('Invalid definition for service "bar": argument 1 of "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\BarMethodCall::setFoo" accepts "stdClass", "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\Foo" passed.');
|
||||||
|
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
$container->register('foo', Foo::class);
|
$container->register('foo', Foo::class);
|
||||||
$container->register('bar', BarMethodCall::class)
|
$container->register('bar', BarMethodCall::class)
|
||||||
->addMethodCall('setFoo', array(new Reference('foo')));
|
->addMethodCall('setFoo', [new Reference('foo')]);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
|
||||||
* @expectedExceptionMessage Invalid definition for service "bar": argument 0 of "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\Bar::__construct" requires a "stdClass", "NULL" passed
|
|
||||||
*/
|
|
||||||
public function testProcessFailsWhenPassingNullToRequiredArgument()
|
public function testProcessFailsWhenPassingNullToRequiredArgument()
|
||||||
{
|
{
|
||||||
|
$this->expectException(\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException::class);
|
||||||
|
$this->expectExceptionMessage('Invalid definition for service "bar": argument 1 of "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\Bar::__construct" accepts "stdClass", "NULL" passed.');
|
||||||
|
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
$container->register('bar', Bar::class)
|
$container->register('bar', Bar::class)
|
||||||
->addArgument(null);
|
->addArgument(null);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
|
||||||
* @expectedExceptionMessage Invalid definition for service "bar": "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\Bar::__construct()" requires 1 arguments, 0 passed
|
|
||||||
*/
|
|
||||||
public function testProcessThrowsExceptionWhenMissingArgumentsInConstructor()
|
public function testProcessThrowsExceptionWhenMissingArgumentsInConstructor()
|
||||||
{
|
{
|
||||||
|
$this->expectException(\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException::class);
|
||||||
|
$this->expectExceptionMessage('Invalid definition for service "bar": "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\Bar::__construct()" requires 1 arguments, 0 passed.');
|
||||||
|
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
$container->register('bar', Bar::class);
|
$container->register('bar', Bar::class);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testProcessSuccessWhenPassingTooManyArgumentInConstructor()
|
public function testProcessSuccessWhenPassingTooManyArgumentInConstructor()
|
||||||
@ -94,7 +90,7 @@ class CheckTypeHintsPassTest extends TestCase
|
|||||||
->addArgument(new Reference('foo'))
|
->addArgument(new Reference('foo'))
|
||||||
->addArgument(new Reference('foo'));
|
->addArgument(new Reference('foo'));
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
|
|
||||||
$this->addToAssertionCount(1);
|
$this->addToAssertionCount(1);
|
||||||
}
|
}
|
||||||
@ -105,62 +101,59 @@ class CheckTypeHintsPassTest extends TestCase
|
|||||||
|
|
||||||
$container->register(Foo::class, Foo::class);
|
$container->register(Foo::class, Foo::class);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
|
|
||||||
$this->assertInstanceOf(Foo::class, $container->get(Foo::class));
|
$this->assertInstanceOf(Foo::class, $container->get(Foo::class));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
|
||||||
* @expectedExceptionMessage Invalid definition for service "bar": "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\BarMethodCall::setFoo()" requires 1 arguments, 0 passed
|
|
||||||
*/
|
|
||||||
public function testProcessThrowsExceptionWhenMissingArgumentsInMethodCall()
|
public function testProcessThrowsExceptionWhenMissingArgumentsInMethodCall()
|
||||||
{
|
{
|
||||||
|
$this->expectException(\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException::class);
|
||||||
|
$this->expectExceptionMessage('Invalid definition for service "bar": "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\BarMethodCall::setFoo()" requires 1 arguments, 0 passed.');
|
||||||
|
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
$container->register('foo', \stdClass::class);
|
$container->register('foo', \stdClass::class);
|
||||||
$container->register('bar', BarMethodCall::class)
|
$container->register('bar', BarMethodCall::class)
|
||||||
->addArgument(new Reference('foo'))
|
->addArgument(new Reference('foo'))
|
||||||
->addMethodCall('setFoo', array());
|
->addMethodCall('setFoo', []);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
|
||||||
* @expectedExceptionMessage Invalid definition for service "bar": argument 1 of "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\BarMethodCall::setFoosVariadic" requires a "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\Foo", "stdClass" passed
|
|
||||||
*/
|
|
||||||
public function testProcessVariadicFails()
|
public function testProcessVariadicFails()
|
||||||
{
|
{
|
||||||
|
$this->expectException(\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException::class);
|
||||||
|
$this->expectExceptionMessage('Invalid definition for service "bar": argument 2 of "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\BarMethodCall::setFoosVariadic" accepts "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\Foo", "stdClass" passed.');
|
||||||
|
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
$container->register('stdClass', \stdClass::class);
|
$container->register('stdClass', \stdClass::class);
|
||||||
$container->register('foo', Foo::class);
|
$container->register('foo', Foo::class);
|
||||||
$container->register('bar', BarMethodCall::class)
|
$container->register('bar', BarMethodCall::class)
|
||||||
->addMethodCall('setFoosVariadic', array(
|
->addMethodCall('setFoosVariadic', [
|
||||||
new Reference('foo'),
|
new Reference('foo'),
|
||||||
new Reference('foo'),
|
new Reference('foo'),
|
||||||
new Reference('stdClass'),
|
new Reference('stdClass'),
|
||||||
));
|
]);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
|
||||||
* @expectedExceptionMessage Invalid definition for service "bar": argument 0 of "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\BarMethodCall::setFoosVariadic" requires a "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\Foo", "stdClass" passed
|
|
||||||
*/
|
|
||||||
public function testProcessVariadicFailsOnPassingBadTypeOnAnotherArgument()
|
public function testProcessVariadicFailsOnPassingBadTypeOnAnotherArgument()
|
||||||
{
|
{
|
||||||
|
$this->expectException(\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException::class);
|
||||||
|
$this->expectExceptionMessage('Invalid definition for service "bar": argument 1 of "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\BarMethodCall::setFoosVariadic" accepts "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\Foo", "stdClass" passed.');
|
||||||
|
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
$container->register('stdClass', \stdClass::class);
|
$container->register('stdClass', \stdClass::class);
|
||||||
$container->register('bar', BarMethodCall::class)
|
$container->register('bar', BarMethodCall::class)
|
||||||
->addMethodCall('setFoosVariadic', array(
|
->addMethodCall('setFoosVariadic', [
|
||||||
new Reference('stdClass'),
|
new Reference('stdClass'),
|
||||||
));
|
]);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testProcessVariadicSuccess()
|
public function testProcessVariadicSuccess()
|
||||||
@ -169,13 +162,13 @@ class CheckTypeHintsPassTest extends TestCase
|
|||||||
|
|
||||||
$container->register('foo', Foo::class);
|
$container->register('foo', Foo::class);
|
||||||
$container->register('bar', BarMethodCall::class)
|
$container->register('bar', BarMethodCall::class)
|
||||||
->addMethodCall('setFoosVariadic', array(
|
->addMethodCall('setFoosVariadic', [
|
||||||
new Reference('foo'),
|
new Reference('foo'),
|
||||||
new Reference('foo'),
|
new Reference('foo'),
|
||||||
new Reference('foo'),
|
new Reference('foo'),
|
||||||
));
|
]);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
|
|
||||||
$this->assertInstanceOf(Foo::class, $container->get('bar')->foo);
|
$this->assertInstanceOf(Foo::class, $container->get('bar')->foo);
|
||||||
}
|
}
|
||||||
@ -186,11 +179,11 @@ class CheckTypeHintsPassTest extends TestCase
|
|||||||
|
|
||||||
$container->register('foo', Foo::class);
|
$container->register('foo', Foo::class);
|
||||||
$container->register('bar', BarMethodCall::class)
|
$container->register('bar', BarMethodCall::class)
|
||||||
->addMethodCall('setFoosOptional', array(
|
->addMethodCall('setFoosOptional', [
|
||||||
new Reference('foo'),
|
new Reference('foo'),
|
||||||
));
|
]);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
|
|
||||||
$this->assertInstanceOf(Foo::class, $container->get('bar')->foo);
|
$this->assertInstanceOf(Foo::class, $container->get('bar')->foo);
|
||||||
}
|
}
|
||||||
@ -201,33 +194,32 @@ class CheckTypeHintsPassTest extends TestCase
|
|||||||
|
|
||||||
$container->register('foo', Foo::class);
|
$container->register('foo', Foo::class);
|
||||||
$container->register('bar', BarMethodCall::class)
|
$container->register('bar', BarMethodCall::class)
|
||||||
->addMethodCall('setFoosOptional', array(
|
->addMethodCall('setFoosOptional', [
|
||||||
new Reference('foo'),
|
new Reference('foo'),
|
||||||
new Reference('foo'),
|
new Reference('foo'),
|
||||||
));
|
]);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
|
|
||||||
$this->assertInstanceOf(Foo::class, $container->get('bar')->foo);
|
$this->assertInstanceOf(Foo::class, $container->get('bar')->foo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
|
||||||
* @expectedExceptionMessage Invalid definition for service "bar": argument 1 of "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\BarMethodCall::setFoosOptional" requires a "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\Foo", "stdClass" passed
|
|
||||||
*/
|
|
||||||
public function testProcessFailsWhenUsingOptionalArgumentWithBadType()
|
public function testProcessFailsWhenUsingOptionalArgumentWithBadType()
|
||||||
{
|
{
|
||||||
|
$this->expectException(\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException::class);
|
||||||
|
$this->expectExceptionMessage('Invalid definition for service "bar": argument 2 of "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\BarMethodCall::setFoosOptional" accepts "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\Foo", "stdClass" passed.');
|
||||||
|
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
$container->register('stdClass', \stdClass::class);
|
$container->register('stdClass', \stdClass::class);
|
||||||
$container->register('foo', Foo::class);
|
$container->register('foo', Foo::class);
|
||||||
$container->register('bar', BarMethodCall::class)
|
$container->register('bar', BarMethodCall::class)
|
||||||
->addMethodCall('setFoosOptional', array(
|
->addMethodCall('setFoosOptional', [
|
||||||
new Reference('foo'),
|
new Reference('foo'),
|
||||||
new Reference('stdClass'),
|
new Reference('stdClass'),
|
||||||
));
|
]);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testProcessSuccessWhenPassingNullToOptional()
|
public function testProcessSuccessWhenPassingNullToOptional()
|
||||||
@ -237,37 +229,35 @@ class CheckTypeHintsPassTest extends TestCase
|
|||||||
$container->register('bar', BarOptionalArgument::class)
|
$container->register('bar', BarOptionalArgument::class)
|
||||||
->addArgument(null);
|
->addArgument(null);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
|
|
||||||
$this->assertNull($container->get('bar')->foo);
|
$this->assertNull($container->get('bar')->foo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
|
||||||
* @expectedExceptionMessage Invalid definition for service "bar": argument 0 of "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\BarOptionalArgumentNotNull::__construct" requires a "int", "NULL" passed
|
|
||||||
*/
|
|
||||||
public function testProcessSuccessWhenPassingNullToOptionalThatDoesNotAcceptNull()
|
public function testProcessSuccessWhenPassingNullToOptionalThatDoesNotAcceptNull()
|
||||||
{
|
{
|
||||||
|
$this->expectException(\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException::class);
|
||||||
|
$this->expectExceptionMessage('Invalid definition for service "bar": argument 1 of "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\BarOptionalArgumentNotNull::__construct" accepts "int", "NULL" passed.');
|
||||||
|
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
$container->register('bar', BarOptionalArgumentNotNull::class)
|
$container->register('bar', BarOptionalArgumentNotNull::class)
|
||||||
->addArgument(null);
|
->addArgument(null);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
|
||||||
* @expectedExceptionMessage Invalid definition for service "bar": argument 0 of "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\BarOptionalArgument::__construct" requires a "stdClass", "string" passed
|
|
||||||
*/
|
|
||||||
public function testProcessFailsWhenPassingBadTypeToOptional()
|
public function testProcessFailsWhenPassingBadTypeToOptional()
|
||||||
{
|
{
|
||||||
|
$this->expectException(\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException::class);
|
||||||
|
$this->expectExceptionMessage('Invalid definition for service "bar": argument 1 of "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\BarOptionalArgument::__construct" accepts "stdClass", "string" passed.');
|
||||||
|
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
$container->register('bar', BarOptionalArgument::class)
|
$container->register('bar', BarOptionalArgument::class)
|
||||||
->addArgument('string instead of stdClass');
|
->addArgument('string instead of stdClass');
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
|
|
||||||
$this->assertNull($container->get('bar')->foo);
|
$this->assertNull($container->get('bar')->foo);
|
||||||
}
|
}
|
||||||
@ -277,97 +267,88 @@ class CheckTypeHintsPassTest extends TestCase
|
|||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
$container->register('bar', BarMethodCall::class)
|
$container->register('bar', BarMethodCall::class)
|
||||||
->addMethodCall('setScalars', array(
|
->addMethodCall('setScalars', [
|
||||||
1,
|
1,
|
||||||
'string',
|
'string',
|
||||||
));
|
]);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
|
|
||||||
$this->assertInstanceOf(BarMethodCall::class, $container->get('bar'));
|
$this->assertInstanceOf(BarMethodCall::class, $container->get('bar'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function testProcessFailsOnPassingScalarTypeToConstructorTypedWithClass()
|
||||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
|
||||||
* @expectedExceptionMessage Invalid definition for service "bar": argument 0 of "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\Bar::__construct" requires a "stdClass", "integer" passed
|
|
||||||
*/
|
|
||||||
public function testProcessFailsOnPassingScalarTypeToConstructorTypeHintedWithClass()
|
|
||||||
{
|
{
|
||||||
|
$this->expectException(\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException::class);
|
||||||
|
$this->expectExceptionMessage('Invalid definition for service "bar": argument 1 of "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\Bar::__construct" accepts "stdClass", "integer" passed.');
|
||||||
|
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
$container->register('bar', Bar::class)
|
$container->register('bar', Bar::class)
|
||||||
->addArgument(1);
|
->addArgument(1);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function testProcessFailsOnPassingScalarTypeToMethodTypedWithClass()
|
||||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
|
||||||
* @expectedExceptionMessage Invalid definition for service "bar": argument 0 of "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\BarMethodCall::setFoo" requires a "stdClass", "string" passed
|
|
||||||
*/
|
|
||||||
public function testProcessFailsOnPassingScalarTypeToMethodTypeHintedWithClass()
|
|
||||||
{
|
{
|
||||||
|
$this->expectException(\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException::class);
|
||||||
|
$this->expectExceptionMessage('Invalid definition for service "bar": argument 1 of "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\BarMethodCall::setFoo" accepts "stdClass", "string" passed.');
|
||||||
|
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
$container->register('bar', BarMethodCall::class)
|
$container->register('bar', BarMethodCall::class)
|
||||||
->addMethodCall('setFoo', array(
|
->addMethodCall('setFoo', [
|
||||||
'builtin type instead of class',
|
'builtin type instead of class',
|
||||||
));
|
]);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public function testProcessFailsOnPassingClassToScalarTypedParameter()
|
||||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
|
||||||
* @expectedExceptionMessage Invalid definition for service "bar": argument 0 of "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\BarMethodCall::setScalars" requires a "int", "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\Foo" passed
|
|
||||||
*/
|
|
||||||
public function testProcessFailsOnPassingClassToScalarTypeHintedParameter()
|
|
||||||
{
|
{
|
||||||
|
$this->expectException(\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException::class);
|
||||||
|
$this->expectExceptionMessage('Invalid definition for service "bar": argument 1 of "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\BarMethodCall::setScalars" accepts "int", "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\Foo" passed.');
|
||||||
|
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
$container->register('foo', Foo::class);
|
$container->register('foo', Foo::class);
|
||||||
$container->register('bar', BarMethodCall::class)
|
$container->register('bar', BarMethodCall::class)
|
||||||
->addMethodCall('setScalars', array(
|
->addMethodCall('setScalars', [
|
||||||
new Reference('foo'),
|
new Reference('foo'),
|
||||||
new Reference('foo'),
|
new Reference('foo'),
|
||||||
));
|
]);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Strict mode not yet handled.
|
|
||||||
*/
|
|
||||||
public function testProcessSuccessOnPassingBadScalarType()
|
public function testProcessSuccessOnPassingBadScalarType()
|
||||||
{
|
{
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
$container->register('bar', BarMethodCall::class)
|
$container->register('bar', BarMethodCall::class)
|
||||||
->addMethodCall('setScalars', array(
|
->addMethodCall('setScalars', [
|
||||||
1,
|
1,
|
||||||
true,
|
true,
|
||||||
));
|
]);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
|
|
||||||
$this->assertInstanceOf(BarMethodCall::class, $container->get('bar'));
|
$this->assertInstanceOf(BarMethodCall::class, $container->get('bar'));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Strict mode not yet handled.
|
|
||||||
*/
|
|
||||||
public function testProcessSuccessPassingBadScalarTypeOptionalArgument()
|
public function testProcessSuccessPassingBadScalarTypeOptionalArgument()
|
||||||
{
|
{
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
$container->register('bar', BarMethodCall::class)
|
$container->register('bar', BarMethodCall::class)
|
||||||
->addMethodCall('setScalars', array(
|
->addMethodCall('setScalars', [
|
||||||
1,
|
1,
|
||||||
'string',
|
'string',
|
||||||
'string instead of optional boolean',
|
'string instead of optional boolean',
|
||||||
));
|
]);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
|
|
||||||
$this->assertInstanceOf(BarMethodCall::class, $container->get('bar'));
|
$this->assertInstanceOf(BarMethodCall::class, $container->get('bar'));
|
||||||
}
|
}
|
||||||
@ -377,27 +358,24 @@ class CheckTypeHintsPassTest extends TestCase
|
|||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
$container->register('bar', BarMethodCall::class)
|
$container->register('bar', BarMethodCall::class)
|
||||||
->addMethodCall('setArray', array(
|
->addMethodCall('setArray', [[]]);
|
||||||
array(),
|
|
||||||
));
|
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
|
|
||||||
$this->assertInstanceOf(BarMethodCall::class, $container->get('bar'));
|
$this->assertInstanceOf(BarMethodCall::class, $container->get('bar'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testProcessSuccessWhenPassingIntegerToArrayTypeHintedParameter()
|
public function testProcessSuccessWhenPassingIntegerToArrayTypedParameter()
|
||||||
{
|
{
|
||||||
|
$this->expectException(\Symfony\Component\DependencyInjection\Exception\InvalidParameterTypeException::class);
|
||||||
|
$this->expectExceptionMessage('Invalid definition for service "bar": argument 1 of "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeDeclarationsPass\BarMethodCall::setArray" accepts "array", "integer" passed.');
|
||||||
|
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
$container->register('bar', BarMethodCall::class)
|
$container->register('bar', BarMethodCall::class)
|
||||||
->addMethodCall('setArray', array(
|
->addMethodCall('setArray', [1]);
|
||||||
1,
|
|
||||||
));
|
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
|
|
||||||
$this->addToAssertionCount(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testProcessSuccessWhenPassingAnIteratorArgumentToIterable()
|
public function testProcessSuccessWhenPassingAnIteratorArgumentToIterable()
|
||||||
@ -405,11 +383,9 @@ class CheckTypeHintsPassTest extends TestCase
|
|||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
$container->register('bar', BarMethodCall::class)
|
$container->register('bar', BarMethodCall::class)
|
||||||
->addMethodCall('setIterable', array(
|
->addMethodCall('setIterable', [new IteratorArgument([])]);
|
||||||
new IteratorArgument(array()),
|
|
||||||
));
|
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
|
|
||||||
$this->addToAssertionCount(1);
|
$this->addToAssertionCount(1);
|
||||||
}
|
}
|
||||||
@ -420,57 +396,43 @@ class CheckTypeHintsPassTest extends TestCase
|
|||||||
|
|
||||||
$container->register('foo', Foo::class);
|
$container->register('foo', Foo::class);
|
||||||
$container->register('bar', Bar::class)
|
$container->register('bar', Bar::class)
|
||||||
->setFactory(array(
|
->setFactory([
|
||||||
new Reference('foo'),
|
new Reference('foo'),
|
||||||
'createBar',
|
'createBar',
|
||||||
));
|
]);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
/* Asserts that the class of Bar is well detected */
|
||||||
|
$container->register('bar_call', BarMethodCall::class)
|
||||||
|
->addMethodCall('setBar', [new Reference('bar')]);
|
||||||
|
|
||||||
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
|
|
||||||
$this->assertInstanceOf(Bar::class, $container->get('bar'));
|
$this->assertInstanceOf(Bar::class, $container->get('bar'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testProcessFactoryWhithClassName()
|
|
||||||
{
|
|
||||||
$container = new ContainerBuilder();
|
|
||||||
|
|
||||||
$container->register(Foo::class, Foo::class);
|
|
||||||
$container->register(Bar::class, Bar::class)
|
|
||||||
->setFactory(array(
|
|
||||||
new Reference(Foo::class),
|
|
||||||
'createBar',
|
|
||||||
));
|
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
|
||||||
|
|
||||||
$this->assertInstanceOf(Bar::class, $container->get(Bar::class));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
|
||||||
* @expectedExceptionMessage Invalid definition for service "bar": argument 0 of "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\Foo::createBarArguments" requires a "stdClass", "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\Foo" passed
|
|
||||||
*/
|
|
||||||
public function testProcessFactoryFailsOnInvalidParameterType()
|
public function testProcessFactoryFailsOnInvalidParameterType()
|
||||||
{
|
{
|
||||||
|
$this->expectException(\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException::class);
|
||||||
|
$this->expectExceptionMessage('Invalid definition for service "bar": argument 1 of "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\Foo::createBarArguments" accepts "stdClass", "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\Foo" passed.');
|
||||||
|
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
$container->register('foo', Foo::class);
|
$container->register('foo', Foo::class);
|
||||||
$container->register('bar', Bar::class)
|
$container->register('bar', Bar::class)
|
||||||
->addArgument(new Reference('foo'))
|
->addArgument(new Reference('foo'))
|
||||||
->setFactory(array(
|
->setFactory([
|
||||||
new Reference('foo'),
|
new Reference('foo'),
|
||||||
'createBarArguments',
|
'createBarArguments',
|
||||||
));
|
]);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
|
|
||||||
* @expectedExceptionMessage Invalid definition for service "bar": argument 1 of "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\Foo::createBarArguments" requires a "stdClass", "Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass\Foo" passed
|
|
||||||
*/
|
|
||||||
public function testProcessFactoryFailsOnInvalidParameterTypeOptional()
|
public function testProcessFactoryFailsOnInvalidParameterTypeOptional()
|
||||||
{
|
{
|
||||||
|
$this->expectException(\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException::class);
|
||||||
|
$this->expectExceptionMessage('Invalid definition for service "bar": argument 2 of "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\Foo::createBarArguments" accepts "stdClass", "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\Foo" passed.');
|
||||||
|
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
$container->register('stdClass', \stdClass::class);
|
$container->register('stdClass', \stdClass::class);
|
||||||
@ -478,12 +440,12 @@ class CheckTypeHintsPassTest extends TestCase
|
|||||||
$container->register('bar', Bar::class)
|
$container->register('bar', Bar::class)
|
||||||
->addArgument(new Reference('stdClass'))
|
->addArgument(new Reference('stdClass'))
|
||||||
->addArgument(new Reference('foo'))
|
->addArgument(new Reference('foo'))
|
||||||
->setFactory(array(
|
->setFactory([
|
||||||
new Reference('foo'),
|
new Reference('foo'),
|
||||||
'createBarArguments',
|
'createBarArguments',
|
||||||
));
|
]);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testProcessFactorySuccessOnValidTypes()
|
public function testProcessFactorySuccessOnValidTypes()
|
||||||
@ -495,12 +457,12 @@ class CheckTypeHintsPassTest extends TestCase
|
|||||||
$container->register('bar', Bar::class)
|
$container->register('bar', Bar::class)
|
||||||
->addArgument(new Reference('stdClass'))
|
->addArgument(new Reference('stdClass'))
|
||||||
->addArgument(new Reference('stdClass'))
|
->addArgument(new Reference('stdClass'))
|
||||||
->setFactory(array(
|
->setFactory([
|
||||||
new Reference('foo'),
|
new Reference('foo'),
|
||||||
'createBarArguments',
|
'createBarArguments',
|
||||||
));
|
]);
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
|
|
||||||
$this->addToAssertionCount(1);
|
$this->addToAssertionCount(1);
|
||||||
}
|
}
|
||||||
@ -512,7 +474,7 @@ class CheckTypeHintsPassTest extends TestCase
|
|||||||
$container->register('bar', \DateTime::class)
|
$container->register('bar', \DateTime::class)
|
||||||
->setFactory('date_create');
|
->setFactory('date_create');
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
|
|
||||||
$this->assertInstanceOf(\DateTime::class, $container->get('bar'));
|
$this->assertInstanceOf(\DateTime::class, $container->get('bar'));
|
||||||
}
|
}
|
||||||
@ -524,13 +486,13 @@ class CheckTypeHintsPassTest extends TestCase
|
|||||||
$container->register('foo', FooNotExisting::class);
|
$container->register('foo', FooNotExisting::class);
|
||||||
$container->register('bar', BarNotExisting::class)
|
$container->register('bar', BarNotExisting::class)
|
||||||
->addArgument(new Reference('foo'))
|
->addArgument(new Reference('foo'))
|
||||||
->addMethodCall('setFoo', array(
|
->addMethodCall('setFoo', [
|
||||||
new Reference('foo'),
|
new Reference('foo'),
|
||||||
'string',
|
'string',
|
||||||
1,
|
1,
|
||||||
));
|
]);
|
||||||
|
|
||||||
(new CheckTypeHintsPass())->process($container);
|
(new CheckTypeDeclarationsPass())->process($container);
|
||||||
|
|
||||||
$this->addToAssertionCount(1);
|
$this->addToAssertionCount(1);
|
||||||
}
|
}
|
||||||
@ -541,12 +503,12 @@ class CheckTypeHintsPassTest extends TestCase
|
|||||||
|
|
||||||
$container->register('foo', FooNotExisting::class);
|
$container->register('foo', FooNotExisting::class);
|
||||||
$container->register('bar', BarNotExisting::class)
|
$container->register('bar', BarNotExisting::class)
|
||||||
->setFactory(array(
|
->setFactory([
|
||||||
new Reference('foo'),
|
new Reference('foo'),
|
||||||
'notExistingMethod',
|
'notExistingMethod',
|
||||||
));
|
]);
|
||||||
|
|
||||||
(new CheckTypeHintsPass())->process($container);
|
(new CheckTypeDeclarationsPass())->process($container);
|
||||||
|
|
||||||
$this->addToAssertionCount(1);
|
$this->addToAssertionCount(1);
|
||||||
}
|
}
|
||||||
@ -558,12 +520,12 @@ class CheckTypeHintsPassTest extends TestCase
|
|||||||
$container->register('bar', BarNotExisting::class)
|
$container->register('bar', BarNotExisting::class)
|
||||||
->addArgument(1);
|
->addArgument(1);
|
||||||
|
|
||||||
(new CheckTypeHintsPass())->process($container);
|
(new CheckTypeDeclarationsPass())->process($container);
|
||||||
|
|
||||||
$this->addToAssertionCount(1);
|
$this->addToAssertionCount(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testProcessDoesNotThrowsExceptionOnValidTypeHints()
|
public function testProcessDoesNotThrowsExceptionOnValidTypes()
|
||||||
{
|
{
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
@ -571,7 +533,22 @@ class CheckTypeHintsPassTest extends TestCase
|
|||||||
$container->register('bar', Bar::class)
|
$container->register('bar', Bar::class)
|
||||||
->addArgument(new Reference('foo'));
|
->addArgument(new Reference('foo'));
|
||||||
|
|
||||||
(new CheckTypeHintsPass(true))->process($container);
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
|
|
||||||
|
$this->assertInstanceOf(\stdClass::class, $container->get('bar')->foo);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testProcessThrowsOnIterableTypeWhenScalarPassed()
|
||||||
|
{
|
||||||
|
$this->expectException(\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException::class);
|
||||||
|
$this->expectExceptionMessage('Invalid definition for service "bar_call": argument 1 of "Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CheckTypeDeclarationsPass\\BarMethodCall::setIterable" accepts "iterable", "integer" passed.');
|
||||||
|
|
||||||
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
|
$container->register('bar_call', BarMethodCall::class)
|
||||||
|
->addMethodCall('setIterable', [2]);
|
||||||
|
|
||||||
|
(new CheckTypeDeclarationsPass(true))->process($container);
|
||||||
|
|
||||||
$this->assertInstanceOf(\stdClass::class, $container->get('bar')->foo);
|
$this->assertInstanceOf(\stdClass::class, $container->get('bar')->foo);
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass;
|
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeDeclarationsPass;
|
||||||
|
|
||||||
class Bar
|
class Bar
|
||||||
{
|
{
|
@ -1,11 +1,15 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass;
|
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeDeclarationsPass;
|
||||||
|
|
||||||
class BarMethodCall
|
class BarMethodCall
|
||||||
{
|
{
|
||||||
public $foo;
|
public $foo;
|
||||||
|
|
||||||
|
public function setBar(Bar $bar)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public function setFoo(\stdClass $foo)
|
public function setFoo(\stdClass $foo)
|
||||||
{
|
{
|
||||||
$this->foo = $foo;
|
$this->foo = $foo;
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass;
|
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeDeclarationsPass;
|
||||||
|
|
||||||
class BarOptionalArgument
|
class BarOptionalArgument
|
||||||
{
|
{
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass;
|
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeDeclarationsPass;
|
||||||
|
|
||||||
class BarOptionalArgumentNotNull
|
class BarOptionalArgumentNotNull
|
||||||
{
|
{
|
@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeHintsPass;
|
namespace Symfony\Component\DependencyInjection\Tests\Fixtures\CheckTypeDeclarationsPass;
|
||||||
|
|
||||||
class Foo
|
class Foo
|
||||||
{
|
{
|
Reference in New Issue
Block a user