Skip to content

Commit

Permalink
Resolver: improved error messages
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Dec 5, 2018
1 parent 2a7e1d0 commit 9d64740
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 26 deletions.
17 changes: 14 additions & 3 deletions src/DI/Resolver.php
Expand Up @@ -391,7 +391,15 @@ private function completeException(\Exception $e, Definition $def): ServiceCreat
if ($e instanceof ServiceCreationException && Strings::startsWith($e->getMessage(), "Service '")) {
return $e;
} else {
$message = "Service '{$def->getName()}'" . ($def->getType() ? " (type of {$def->getType()})" : '') . ': ' . $e->getMessage();
$name = $def->getName();
$type = $def->getType();
if (!$type) {
$message = "Service '$name': " . $e->getMessage();
} elseif (!$name || ctype_digit($name)) {
$message = "Service of type $type: " . str_replace("$type::", '', $e->getMessage());
} else {
$message = "Service '$name' (type of $type): " . str_replace("$type::", '', $e->getMessage());
}
return $e instanceof ServiceCreationException
? $e->setMessage($message)
: new ServiceCreationException($message, 0, $e);
Expand All @@ -407,14 +415,17 @@ private function entityToString($entity): string
: '@' . $ref->getValue();
};
if (is_string($entity)) {
return $entity . '::__construct';
return $entity . '::__construct()';
} elseif ($entity instanceof Reference) {
$entity = $referenceToText($entity);
} elseif (is_array($entity)) {
if (strpos($entity[1], '$') === false) {
$entity[1] .= '()';
}
if ($entity[0] instanceof Reference) {
$entity[0] = $referenceToText($entity[0]);
} elseif (!is_string($entity[0])) {
return 'method ' . $entity[1];
return $entity[1];
}
return implode('::', $entity);
}
Expand Down
6 changes: 3 additions & 3 deletions tests/DI/Compiler.generatedFactory.phpt
Expand Up @@ -287,7 +287,7 @@ Assert::exception(function () {
->getResultDefinition()
->setFactory('Bad1');
$builder->complete();
}, Nette\InvalidStateException::class, "Service 'one' (type of Bad2): Type hint for \$bar in Bad2::create() doesn't match type hint in Bad1 constructor.");
}, Nette\InvalidStateException::class, "Service 'one' (type of Bad2): Type hint for \$bar in create() doesn't match type hint in Bad1 constructor.");



Expand All @@ -310,7 +310,7 @@ Assert::exception(function () {
->getResultDefinition()
->setFactory('Bad3');
$builder->complete();
}, Nette\InvalidStateException::class, "Service 'one' (type of Bad4): Unused parameter \$baz when implementing method Bad4::create(), did you mean \$bar?");
}, Nette\InvalidStateException::class, "Service 'one' (type of Bad4): Unused parameter \$baz when implementing method create(), did you mean \$bar?");



Expand All @@ -333,7 +333,7 @@ Assert::exception(function () {
->getResultDefinition()
->setFactory('Bad5');
$builder->complete();
}, Nette\InvalidStateException::class, "Service 'one' (type of Bad6): Unused parameter \$baz when implementing method Bad6::create().");
}, Nette\InvalidStateException::class, "Service 'one' (type of Bad6): Unused parameter \$baz when implementing method create().");



Expand Down
4 changes: 2 additions & 2 deletions tests/DI/ContainerBuilder.autowiring.novalue.phpt
Expand Up @@ -24,7 +24,7 @@ Assert::exception(function () {
$builder = new DI\ContainerBuilder;
$builder->addDefinition('foo')->setType('Foo');
$container = createContainer($builder);
}, Nette\DI\ServiceCreationException::class, "Service 'foo' (type of Foo): Parameter \$x in Foo::__construct() has no class type hint or default value, so its value must be specified.");
}, Nette\DI\ServiceCreationException::class, "Service 'foo' (type of Foo): Parameter \$x in __construct() has no class type hint or default value, so its value must be specified.");


class Bar
Expand All @@ -38,7 +38,7 @@ Assert::exception(function () {
$builder = new DI\ContainerBuilder;
$builder->addDefinition('foo')->setType('Bar');
$container = createContainer($builder);
}, Nette\DI\ServiceCreationException::class, "Service 'foo' (type of Bar): Parameter \$x in Bar::__construct() has no class type hint or default value, so its value must be specified.");
}, Nette\DI\ServiceCreationException::class, "Service 'foo' (type of Bar): Parameter \$x in __construct() has no class type hint or default value, so its value must be specified.");


class Bar2
Expand Down
30 changes: 15 additions & 15 deletions tests/DI/ContainerBuilder.factory.error.phpt
Expand Up @@ -69,7 +69,7 @@ Assert::exception(function () {
$builder->addFactoryDefinition('one')
->setImplement('Bad4');
$builder->complete();
}, Nette\InvalidStateException::class, "Service 'one' (type of Bad4): Method Bad4::create() has not return type hint or annotation @return.");
}, Nette\InvalidStateException::class, "Service 'one' (type of Bad4): Method create() has not return type hint or annotation @return.");


interface Bad5
Expand Down Expand Up @@ -139,14 +139,14 @@ Assert::exception(function () {
$builder = new DI\ContainerBuilder;
$builder->addDefinition('one')->setFactory('Good', [new Statement('Unknown')]);
$builder->complete();
}, Nette\InvalidStateException::class, "Service 'one' (type of Good): Class Unknown not found. (used in Good::__construct)");
}, Nette\InvalidStateException::class, "Service 'one' (type of Good): Class Unknown not found. (used in __construct())");

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


abstract class Bad9
Expand Down Expand Up @@ -201,7 +201,7 @@ services:
b: stdClass
bad: ConstructorParam
');
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of ConstructorParam): Multiple services of type stdClass found: a, b (needed by \$x in ConstructorParam::__construct())");
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of ConstructorParam): Multiple services of type stdClass found: a, b (needed by \$x in __construct())");


// forced autowiring fail
Expand All @@ -212,7 +212,7 @@ services:
b: stdClass
bad: ConstructorParam(@\stdClass)
');
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of ConstructorParam): Multiple services of type stdClass found: a, b (used in ConstructorParam::__construct)");
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of ConstructorParam): Multiple services of type stdClass found: a, b (used in __construct())");


// autowiring fail in chain
Expand All @@ -223,7 +223,7 @@ services:
b: stdClass
bad: MethodParam()::foo()
');
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of MethodParam): Multiple services of type stdClass found: a, b (needed by \$x in MethodParam::foo())");
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of MethodParam): Multiple services of type stdClass found: a, b (needed by \$x in foo())");


// forced autowiring fail in chain
Expand All @@ -234,7 +234,7 @@ services:
b: stdClass
bad: MethodParam()::foo(@\stdClass)
');
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of MethodParam): Multiple services of type stdClass found: a, b (used in method foo)");
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of MethodParam): Multiple services of type stdClass found: a, b (used in foo())");


// autowiring fail in argument
Expand All @@ -245,7 +245,7 @@ services:
b: stdClass
bad: Good(ConstructorParam())
');
}, 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)");
}, 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 __construct())");


// forced autowiring fail in argument
Expand All @@ -256,7 +256,7 @@ services:
b: stdClass
bad: Good(ConstructorParam(@\stdClass))
');
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in ConstructorParam::__construct)");
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in ConstructorParam::__construct())");


// autowiring fail in chain in argument
Expand All @@ -267,7 +267,7 @@ services:
b: stdClass
bad: Good(MethodParam()::foo())
');
}, 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)");
}, 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 __construct())");


// forced autowiring fail in chain in argument
Expand All @@ -278,7 +278,7 @@ services:
b: stdClass
bad: Good(MethodParam()::foo(@\stdClass))
');
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in method foo)");
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in foo())");


// forced autowiring fail in property passing
Expand Down Expand Up @@ -306,7 +306,7 @@ services:
setup:
- $a = MethodParam()::foo(@\stdClass)
');
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in method foo)");
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in foo())");


// autowiring fail in method calling
Expand All @@ -320,7 +320,7 @@ services:
setup:
- foo
');
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of MethodParam): Multiple services of type stdClass found: a, b (needed by \$x in MethodParam::foo())");
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of MethodParam): Multiple services of type stdClass found: a, b (needed by \$x in foo())");


// forced autowiring fail in method calling
Expand All @@ -334,7 +334,7 @@ services:
setup:
- bar(@\stdClass)
');
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in @bad::bar)");
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in @bad::bar())");


// autowiring fail in rich method calling
Expand All @@ -348,4 +348,4 @@ services:
setup:
- bar(MethodParam()::foo(@\stdClass))
');
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in method foo)");
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in foo())");
4 changes: 2 additions & 2 deletions tests/DI/Definitions.AccessorDefinition.resolve.phpt
Expand Up @@ -37,7 +37,7 @@ Assert::exception(function () {
$resolver = new Nette\DI\Resolver(new Nette\DI\ContainerBuilder);
$resolver->resolveDefinition($def);
$resolver->completeDefinition($def);
}, Nette\DI\ServiceCreationException::class, "Service '' (type of Good1): Method Good1::get() has not return type hint or annotation @return.");
}, Nette\DI\ServiceCreationException::class, "Service of type Good1: Method get() has not return type hint or annotation @return.");


Assert::noError(function () {
Expand Down Expand Up @@ -66,4 +66,4 @@ Assert::exception(function () {
$resolver = new Nette\DI\Resolver(new Nette\DI\ContainerBuilder);
$resolver->resolveDefinition($def);
$resolver->completeDefinition($def);
}, Nette\DI\ServiceCreationException::class, "Service '' (type of Good2): Service of type 'stdClass' not found.");
}, Nette\DI\ServiceCreationException::class, "Service of type Good2: Service of type 'stdClass' not found.");
2 changes: 1 addition & 1 deletion tests/DI/Definitions.FactoryDefinition.resolve.phpt
Expand Up @@ -36,7 +36,7 @@ Assert::exception(function () {
$def->setImplement('Good1');
$resolver = new Nette\DI\Resolver(new Nette\DI\ContainerBuilder);
$resolver->resolveDefinition($def);
}, Nette\DI\ServiceCreationException::class, "Service '' (type of Good1): Method Good1::create() has not return type hint or annotation @return.");
}, Nette\DI\ServiceCreationException::class, "Service of type Good1: Method create() has not return type hint or annotation @return.");


Assert::noError(function () {
Expand Down

0 comments on commit 9d64740

Please sign in to comment.