Skip to content

Commit 9d3541e

Browse files
committed
ContainerBuilder::completeStatement() improved error message
1 parent 829b47f commit 9d3541e

File tree

2 files changed

+40
-29
lines changed

2 files changed

+40
-29
lines changed

src/DI/ContainerBuilder.php

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -629,25 +629,36 @@ public function completeStatement(Statement $statement): Statement
629629
}
630630
}
631631

632-
array_walk_recursive($arguments, function (&$val): void {
633-
if ($val instanceof Statement) {
634-
$val = $this->completeStatement($val);
635-
636-
} elseif ($val instanceof ServiceDefinition) {
637-
$val = '@' . current(array_keys($this->getDefinitions(), $val, true));
638-
639-
} elseif (is_string($val) && strlen($val) > 1 && $val[0] === '@' && $val[1] !== '@') {
640-
$pair = explode('::', $val, 2);
641-
$name = $this->getServiceName($pair[0]);
642-
if (!isset($pair[1])) { // @service
643-
$val = '@' . $name;
644-
} elseif (preg_match('#^[A-Z][A-Z0-9_]*\z#', $pair[1], $m)) { // @service::CONSTANT
645-
$val = self::literal($this->getDefinition($name)->getType() . '::' . $pair[1]);
646-
} else { // @service::property
647-
$val = new Statement(['@' . $name, '$' . $pair[1]]);
632+
try {
633+
array_walk_recursive($arguments, function (&$val): void {
634+
if ($val instanceof Statement) {
635+
$val = $this->completeStatement($val);
636+
637+
} elseif ($val instanceof ServiceDefinition) {
638+
$val = '@' . current(array_keys($this->getDefinitions(), $val, true));
639+
640+
} elseif (is_string($val) && strlen($val) > 1 && $val[0] === '@' && $val[1] !== '@') {
641+
$pair = explode('::', $val, 2);
642+
$name = $this->getServiceName($pair[0]);
643+
if (!isset($pair[1])) { // @service
644+
$val = '@' . $name;
645+
} elseif (preg_match('#^[A-Z][A-Z0-9_]*\z#', $pair[1], $m)) { // @service::CONSTANT
646+
$val = self::literal($this->getDefinition($name)->getType() . '::' . $pair[1]);
647+
} else { // @service::property
648+
$val = new Statement(['@' . $name, '$' . $pair[1]]);
649+
}
648650
}
651+
});
652+
653+
} catch (ServiceCreationException $e) {
654+
if ((is_string($entity) || is_array($entity)) && !strpos($e->getMessage(), ' (used in')) {
655+
$desc = is_string($entity)
656+
? $entity . '::__construct'
657+
: (is_string($entity[0]) ? ($entity[0] . '::') : 'method ') . $entity[1];
658+
$e->setMessage($e->getMessage() . " (used in $desc)");
649659
}
650-
});
660+
throw $e;
661+
}
651662

652663
return new Statement($entity, $arguments);
653664
}

tests/DI/ContainerBuilder.factory.error.phpt

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -166,14 +166,14 @@ Assert::exception(function () {
166166
$builder = new DI\ContainerBuilder;
167167
$builder->addDefinition('one')->setFactory('Good', [new Statement('Unknown')]);
168168
$builder->complete();
169-
}, Nette\InvalidStateException::class, "Service 'one' (type of Good): Class Unknown not found.");
169+
}, Nette\InvalidStateException::class, "Service 'one' (type of Good): Class Unknown not found. (used in Good::__construct)");
170170

171171
// fail in argument
172172
Assert::exception(function () {
173173
$builder = new DI\ContainerBuilder;
174174
$builder->addDefinition('one')->setFactory('Good', [new Statement('Bad8')]);
175175
$builder->complete();
176-
}, Nette\InvalidStateException::class, "Service 'one' (type of Good): Class Bad8 has private constructor.");
176+
}, Nette\InvalidStateException::class, "Service 'one' (type of Good): Class Bad8 has private constructor. (used in Good::__construct)");
177177

178178

179179
abstract class Bad9
@@ -239,7 +239,7 @@ services:
239239
b: stdClass
240240
bad: ConstructorParam(@\stdClass)
241241
');
242-
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of ConstructorParam): Multiple services of type stdClass found: a, b");
242+
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of ConstructorParam): Multiple services of type stdClass found: a, b (used in ConstructorParam::__construct)");
243243

244244

245245
// autowiring fail in chain
@@ -261,7 +261,7 @@ services:
261261
b: stdClass
262262
bad: MethodParam()::foo(@\stdClass)
263263
');
264-
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of MethodParam): Multiple services of type stdClass found: a, b");
264+
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of MethodParam): Multiple services of type stdClass found: a, b (used in method foo)");
265265

266266

267267
// autowiring fail in argument
@@ -272,7 +272,7 @@ services:
272272
b: stdClass
273273
bad: Good(ConstructorParam())
274274
');
275-
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (needed by \$x in ConstructorParam::__construct())");
275+
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (needed by \$x in ConstructorParam::__construct()) (used in Good::__construct)");
276276

277277

278278
// forced autowiring fail in argument
@@ -283,7 +283,7 @@ services:
283283
b: stdClass
284284
bad: Good(ConstructorParam(@\stdClass))
285285
');
286-
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b");
286+
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in ConstructorParam::__construct)");
287287

288288

289289
// autowiring fail in chain in argument
@@ -294,7 +294,7 @@ services:
294294
b: stdClass
295295
bad: Good(MethodParam()::foo())
296296
');
297-
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (needed by \$x in MethodParam::foo())");
297+
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (needed by \$x in MethodParam::foo()) (used in Good::__construct)");
298298

299299

300300
// forced autowiring fail in chain in argument
@@ -305,7 +305,7 @@ services:
305305
b: stdClass
306306
bad: Good(MethodParam()::foo(@\stdClass))
307307
');
308-
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b");
308+
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in method foo)");
309309

310310

311311
// forced autowiring fail in property passing
@@ -319,7 +319,7 @@ services:
319319
setup:
320320
- $a = @\stdClass
321321
');
322-
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b");
322+
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in @bad::\$a)");
323323

324324

325325
// autowiring fail in rich property passing
@@ -333,7 +333,7 @@ services:
333333
setup:
334334
- $a = MethodParam()::foo(@\stdClass)
335335
');
336-
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b");
336+
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in method foo)");
337337

338338

339339
// autowiring fail in method calling
@@ -361,7 +361,7 @@ services:
361361
setup:
362362
- bar(@\stdClass)
363363
');
364-
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b");
364+
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in @bad::bar)");
365365

366366

367367
// autowiring fail in rich method calling
@@ -375,4 +375,4 @@ services:
375375
setup:
376376
- bar(MethodParam()::foo(@\stdClass))
377377
');
378-
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b");
378+
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in method foo)");

0 commit comments

Comments
 (0)