Skip to content

Commit 7e2ca4a

Browse files
committed
merged branch jmikola/master-DependencyInjectionExceptions (PR #2786)
Commits ------- da0773c Note DependencyInjection exception changes in the 2.1 changelog 9a090bc [DependencyInjection] Fix class check and failure message in PhpDumper test 2334596 [DependencyInjection] Use component's SPL classes in dumped service container 3c02ea2 [DependencyInjection] Use exception class for API doc generation 47256ea [DependencyInjection] Make exceptions consistent when ContainerBuilder is frozen b7300d2 [DependencyInjection] Fix up @throws documentation 123f514 [DependencyInjection] Use component-specific SPL exceptions cf2ca9b [DependencyInjection] Create additional SPL exceptions ba8322e [DependencyInjection] Format base exception classes consistently Discussion ---------- [DependencyInjection] Refactor usage of SPL exceptions ``` Bug fix: no Feature addition: no Backwards compatibility break: yes Symfony2 tests pass: yes Fixes the following tickets: - ``` This was something discussed on the mailing list recently and a topic at the last IRC meeting. The DependencyInjection component was what I had in mind while discussing this with @lsmith a few weeks ago, as I found that it already had some local SPL exceptions, which weren't being used directly (only as base classes for the compiler exceptions). This PR replaces uses of core SPL exceptions with the component's equivalents. I've listed it as BC-breaking to be safe, but I don't think it should cause any trouble, since the new exceptions are sub-classes of those originally used. I purposely avoided changing the exceptions in the dumped PHP container. If we agree that's worth doing, it would be a trivial addition to the PR. --------------------------------------------------------------------------- by jmikola at 2011/12/04 22:38:47 -0800 One question I came across while implementing this PR: the doc blocks in ContainerInterface reference InvalidArgumentException (actually the component's local SPL equivalent), but there is no practical need for that class to be used in the file. How will the API doc generator handle this? Do we need to change the doc block reference to the full class path? --------------------------------------------------------------------------- by fabpot at 2011/12/05 01:20:31 -0800 Why have you not replaced the exception in the dumped container code? I don't see any drawback. --------------------------------------------------------------------------- by stof at 2011/12/05 03:39:25 -0800 it would even be better to be consistent in the generated code --------------------------------------------------------------------------- by jmikola at 2011/12/05 09:48:05 -0800 I'll update the exceptions in the dumped container code as well. Thanks for the feedback. --------------------------------------------------------------------------- by jmikola at 2011/12/05 10:41:21 -0800 Ok, this should be ready to review and merge. Tests needed some updating, but they still pass.
2 parents e316a2f + da0773c commit 7e2ca4a

34 files changed

+229
-117
lines changed

CHANGELOG-2.1.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c
106106

107107
* added support for loading globally-installed PEAR packages
108108

109+
### DependencyInjection
110+
111+
* component exceptions that inherit base SPL classes are now used exclusively (this includes dumped containers)
112+
109113
### DomCrawler
110114

111115
* added a way to get parsing errors for Crawler::addHtmlContent() and Crawler::addXmlContent() via libxml functions

src/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public function process(ContainerBuilder $container)
5050
* Checks for circular references.
5151
*
5252
* @param array $edges An array of Nodes
53-
* @throws \RuntimeException When a circular reference is found.
53+
* @throws ServiceCircularReferenceException When a circular reference is found.
5454
*/
5555
private function checkOutEdges(array $edges)
5656
{

src/Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.php

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\DependencyInjection\ContainerInterface;
1515
use Symfony\Component\DependencyInjection\ContainerBuilder;
16+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
1617

1718
/**
1819
* This pass validates each definition individually only taking the information
@@ -33,22 +34,22 @@ class CheckDefinitionValidityPass implements CompilerPassInterface
3334
* Processes the ContainerBuilder to validate the Definition.
3435
*
3536
* @param ContainerBuilder $container
36-
* @throws \RuntimeException When the Definition is invalid
37+
* @throws RuntimeException When the Definition is invalid
3738
*/
3839
public function process(ContainerBuilder $container)
3940
{
4041
foreach ($container->getDefinitions() as $id => $definition) {
4142
// synthetic service is public
4243
if ($definition->isSynthetic() && !$definition->isPublic()) {
43-
throw new \RuntimeException(sprintf(
44+
throw new RuntimeException(sprintf(
4445
'A synthetic service ("%s") must be public.',
4546
$id
4647
));
4748
}
4849

4950
// synthetic service has non-prototype scope
5051
if ($definition->isSynthetic() && ContainerInterface::SCOPE_PROTOTYPE === $definition->getScope()) {
51-
throw new \RuntimeException(sprintf(
52+
throw new RuntimeException(sprintf(
5253
'A synthetic service ("%s") cannot be of scope "prototype".',
5354
$id
5455
));
@@ -57,14 +58,14 @@ public function process(ContainerBuilder $container)
5758
// non-synthetic, non-abstract service has class
5859
if (!$definition->isAbstract() && !$definition->isSynthetic() && !$definition->getClass()) {
5960
if ($definition->getFactoryClass() || $definition->getFactoryService()) {
60-
throw new \RuntimeException(sprintf(
61+
throw new RuntimeException(sprintf(
6162
'Please add the class to service "%s" even if it is constructed by a factory '
6263
.'since we might need to add method calls based on compile-time checks.',
6364
$id
6465
));
6566
}
6667

67-
throw new \RuntimeException(sprintf(
68+
throw new RuntimeException(sprintf(
6869
'The definition for "%s" has no class. If you intend to inject '
6970
.'this service dynamically at runtime, please mark it as synthetic=true. '
7071
.'If this is an abstract definition solely used by child definitions, '

src/Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,13 @@
1111

1212
namespace Symfony\Component\DependencyInjection\Compiler;
1313

14-
use Symfony\Component\DependencyInjection\Exception\ScopeWideningInjectionException;
15-
use Symfony\Component\DependencyInjection\Exception\ScopeCrossingInjectionException;
1614
use Symfony\Component\DependencyInjection\Definition;
1715
use Symfony\Component\DependencyInjection\ContainerInterface;
1816
use Symfony\Component\DependencyInjection\Reference;
1917
use Symfony\Component\DependencyInjection\ContainerBuilder;
18+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
19+
use Symfony\Component\DependencyInjection\Exception\ScopeCrossingInjectionException;
20+
use Symfony\Component\DependencyInjection\Exception\ScopeWideningInjectionException;
2021

2122
/**
2223
* Checks the validity of references
@@ -85,7 +86,7 @@ public function process(ContainerBuilder $container)
8586
* Validates an array of References.
8687
*
8788
* @param array $arguments An array of Reference objects
88-
* @throws \RuntimeException when there is a reference to an abstract definition.
89+
* @throws RuntimeException when there is a reference to an abstract definition.
8990
*/
9091
private function validateReferences(array $arguments)
9192
{
@@ -96,7 +97,7 @@ private function validateReferences(array $arguments)
9697
$targetDefinition = $this->getDefinition((string) $argument);
9798

9899
if (null !== $targetDefinition && $targetDefinition->isAbstract()) {
99-
throw new \RuntimeException(sprintf(
100+
throw new RuntimeException(sprintf(
100101
'The definition "%s" has a reference to an abstract definition "%s". '
101102
.'Abstract definitions cannot be the target of references.',
102103
$this->currentId,
@@ -114,7 +115,8 @@ private function validateReferences(array $arguments)
114115
*
115116
* @param Reference $reference
116117
* @param Definition $definition
117-
* @throws \RuntimeException when there is an issue with the Reference scope
118+
* @throws ScopeWideningInjectionException when the definition references a service of a narrower scope
119+
* @throws ScopeCrossingInjectionException when the definition references a service of another scope hierarchy
118120
*/
119121
private function validateScope(Reference $reference, Definition $definition = null)
120122
{

src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Component\DependencyInjection\Compiler;
1313

14+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
15+
1416
/**
1517
* Compiler Pass Configuration
1618
*
@@ -95,15 +97,15 @@ public function getPasses()
9597
*
9698
* @param CompilerPassInterface $pass A Compiler pass
9799
* @param string $type The pass type
98-
* @throws \InvalidArgumentException when a pass type doesn't exist
100+
* @throws InvalidArgumentException when a pass type doesn't exist
99101
*
100102
* @api
101103
*/
102104
public function addPass(CompilerPassInterface $pass, $type = self::TYPE_BEFORE_OPTIMIZATION)
103105
{
104106
$property = $type.'Passes';
105107
if (!isset($this->$property)) {
106-
throw new \InvalidArgumentException(sprintf('Invalid type "%s".', $type));
108+
throw new InvalidArgumentException(sprintf('Invalid type "%s".', $type));
107109
}
108110

109111
$passes = &$this->$property;

src/Symfony/Component/DependencyInjection/Compiler/RepeatedPass.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\DependencyInjection\Compiler;
1313

1414
use Symfony\Component\DependencyInjection\ContainerBuilder;
15+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
1516

1617
/**
1718
* A pass that might be run repeatedly.
@@ -27,12 +28,13 @@ class RepeatedPass implements CompilerPassInterface
2728
* Constructor.
2829
*
2930
* @param array $passes An array of RepeatablePassInterface objects
31+
* @throws InvalidArgumentException if a pass is not a RepeatablePassInterface instance
3032
*/
3133
public function __construct(array $passes)
3234
{
3335
foreach ($passes as $pass) {
3436
if (!$pass instanceof RepeatablePassInterface) {
35-
throw new \InvalidArgumentException('$passes must be an array of RepeatablePassInterface.');
37+
throw new InvalidArgumentException('$passes must be an array of RepeatablePassInterface.');
3638
}
3739

3840
$pass->setRepeatedPass($this);

src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Component\DependencyInjection\Definition;
1515
use Symfony\Component\DependencyInjection\DefinitionDecorator;
1616
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
1718

1819
/**
1920
* This replaces all DefinitionDecorator instances with their equivalent fully
@@ -60,7 +61,7 @@ public function process(ContainerBuilder $container)
6061
private function resolveDefinition($id, DefinitionDecorator $definition)
6162
{
6263
if (!$this->container->hasDefinition($parent = $definition->getParent())) {
63-
throw new \RuntimeException(sprintf('The parent definition "%s" defined for definition "%s" does not exist.', $parent, $id));
64+
throw new RuntimeException(sprintf('The parent definition "%s" defined for definition "%s" does not exist.', $parent, $id));
6465
}
6566

6667
$parentDef = $this->container->getDefinition($parent);
@@ -116,7 +117,7 @@ private function resolveDefinition($id, DefinitionDecorator $definition)
116117
}
117118

118119
if (0 !== strpos($k, 'index_')) {
119-
throw new \RuntimeException(sprintf('Invalid argument key "%s" found.', $k));
120+
throw new RuntimeException(sprintf('Invalid argument key "%s" found.', $k));
120121
}
121122

122123
$index = (integer) substr($k, strlen('index_'));

src/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Component\DependencyInjection\ContainerInterface;
1515
use Symfony\Component\DependencyInjection\Reference;
1616
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
1718

1819
/**
1920
* Emulates the invalid behavior if the reference is not found within the
@@ -46,7 +47,7 @@ public function process(ContainerBuilder $container)
4647
foreach ($definition->getMethodCalls() as $call) {
4748
try {
4849
$calls[] = array($call[0], $this->processArguments($call[1], true));
49-
} catch (\RuntimeException $ignore) {
50+
} catch (RuntimeException $ignore) {
5051
// this call is simply removed
5152
}
5253
}
@@ -57,7 +58,7 @@ public function process(ContainerBuilder $container)
5758
try {
5859
$value = $this->processArguments(array($value), true);
5960
$properties[$name] = reset($value);
60-
} catch (\RuntimeException $ignore) {
61+
} catch (RuntimeException $ignore) {
6162
// ignore property
6263
}
6364
}
@@ -89,7 +90,7 @@ private function processArguments(array $arguments, $inMethodCall = false)
8990
$arguments[$k] = null;
9091
} else if (!$exists && ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) {
9192
if ($inMethodCall) {
92-
throw new \RuntimeException('Method shouldn\'t be called.');
93+
throw new RuntimeException('Method shouldn\'t be called.');
9394
}
9495

9596
$arguments[$k] = null;

src/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraph.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Component\DependencyInjection\Compiler;
1313

14+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
15+
1416
/**
1517
* This is a directed graph of your services.
1618
*
@@ -46,12 +48,12 @@ public function hasNode($id)
4648
*
4749
* @param string $id The id to retrieve
4850
* @return ServiceReferenceGraphNode The node matching the supplied identifier
49-
* @throws \InvalidArgumentException
51+
* @throws InvalidArgumentException if no node matches the supplied identifier
5052
*/
5153
public function getNode($id)
5254
{
5355
if (!isset($this->nodes[$id])) {
54-
throw new \InvalidArgumentException(sprintf('There is no node with id "%s".', $id));
56+
throw new InvalidArgumentException(sprintf('There is no node with id "%s".', $id));
5557
}
5658

5759
return $this->nodes[$id];

src/Symfony/Component/DependencyInjection/Container.php

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111

1212
namespace Symfony\Component\DependencyInjection;
1313

14+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
15+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
1416
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
1517
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
1618
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
@@ -135,7 +137,7 @@ public function getParameterBag()
135137
*
136138
* @return mixed The parameter value
137139
*
138-
* @throws \InvalidArgumentException if the parameter is not defined
140+
* @throws InvalidArgumentException if the parameter is not defined
139141
*
140142
* @api
141143
*/
@@ -183,14 +185,14 @@ public function setParameter($name, $value)
183185
public function set($id, $service, $scope = self::SCOPE_CONTAINER)
184186
{
185187
if (self::SCOPE_PROTOTYPE === $scope) {
186-
throw new \InvalidArgumentException('You cannot set services of scope "prototype".');
188+
throw new InvalidArgumentException('You cannot set services of scope "prototype".');
187189
}
188190

189191
$id = strtolower($id);
190192

191193
if (self::SCOPE_CONTAINER !== $scope) {
192194
if (!isset($this->scopedServices[$scope])) {
193-
throw new \RuntimeException('You cannot set services of inactive scopes.');
195+
throw new RuntimeException('You cannot set services of inactive scopes.');
194196
}
195197

196198
$this->scopedServices[$scope][$id] = $service;
@@ -226,7 +228,7 @@ public function has($id)
226228
*
227229
* @return object The associated service
228230
*
229-
* @throws \InvalidArgumentException if the service is not defined
231+
* @throws InvalidArgumentException if the service is not defined
230232
*
231233
* @see Reference
232234
*
@@ -292,11 +294,11 @@ public function getServiceIds()
292294
public function enterScope($name)
293295
{
294296
if (!isset($this->scopes[$name])) {
295-
throw new \InvalidArgumentException(sprintf('The scope "%s" does not exist.', $name));
297+
throw new InvalidArgumentException(sprintf('The scope "%s" does not exist.', $name));
296298
}
297299

298300
if (self::SCOPE_CONTAINER !== $this->scopes[$name] && !isset($this->scopedServices[$this->scopes[$name]])) {
299-
throw new \RuntimeException(sprintf('The parent scope "%s" must be active when entering this scope.', $this->scopes[$name]));
301+
throw new RuntimeException(sprintf('The parent scope "%s" must be active when entering this scope.', $this->scopes[$name]));
300302
}
301303

302304
// check if a scope of this name is already active, if so we need to
@@ -330,14 +332,14 @@ public function enterScope($name)
330332
* scope.
331333
*
332334
* @param string $name The name of the scope to leave
333-
* @throws \InvalidArgumentException if the scope is not active
335+
* @throws InvalidArgumentException if the scope is not active
334336
*
335337
* @api
336338
*/
337339
public function leaveScope($name)
338340
{
339341
if (!isset($this->scopedServices[$name])) {
340-
throw new \InvalidArgumentException(sprintf('The scope "%s" is not active.', $name));
342+
throw new InvalidArgumentException(sprintf('The scope "%s" is not active.', $name));
341343
}
342344

343345
// remove all services of this scope, or any of its child scopes from
@@ -377,13 +379,13 @@ public function addScope(ScopeInterface $scope)
377379
$parentScope = $scope->getParentName();
378380

379381
if (self::SCOPE_CONTAINER === $name || self::SCOPE_PROTOTYPE === $name) {
380-
throw new \InvalidArgumentException(sprintf('The scope "%s" is reserved.', $name));
382+
throw new InvalidArgumentException(sprintf('The scope "%s" is reserved.', $name));
381383
}
382384
if (isset($this->scopes[$name])) {
383-
throw new \InvalidArgumentException(sprintf('A scope with name "%s" already exists.', $name));
385+
throw new InvalidArgumentException(sprintf('A scope with name "%s" already exists.', $name));
384386
}
385387
if (self::SCOPE_CONTAINER !== $parentScope && !isset($this->scopes[$parentScope])) {
386-
throw new \InvalidArgumentException(sprintf('The parent scope "%s" does not exist, or is invalid.', $parentScope));
388+
throw new InvalidArgumentException(sprintf('The parent scope "%s" does not exist, or is invalid.', $parentScope));
387389
}
388390

389391
$this->scopes[$name] = $parentScope;

0 commit comments

Comments
 (0)