Skip to content

Commit

Permalink
ContainerBuilder::completeStatement() improved error message
Browse files Browse the repository at this point in the history
  • Loading branch information
dg committed Jun 11, 2018
1 parent 0ce93cb commit 3f8f212
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 33 deletions.
53 changes: 32 additions & 21 deletions src/DI/ContainerBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -673,29 +673,40 @@ public function completeStatement(Statement $statement)
}
}

array_walk_recursive($arguments, function (&$val) {
if ($val instanceof Statement) {
$val = $this->completeStatement($val);

} elseif ($val === $this) {
trigger_error("Replace object ContainerBuilder in Statement arguments with '@container'.", E_USER_DEPRECATED);
$val = self::literal('$this');

} elseif ($val instanceof ServiceDefinition) {
$val = '@' . current(array_keys($this->getDefinitions(), $val, true));

} elseif (is_string($val) && strlen($val) > 1 && $val[0] === '@' && $val[1] !== '@') {
$pair = explode('::', $val, 2);
$name = $this->getServiceName($pair[0]);
if (!isset($pair[1])) { // @service
$val = '@' . $name;
} elseif (preg_match('#^[A-Z][A-Z0-9_]*\z#', $pair[1], $m)) { // @service::CONSTANT
$val = self::literal($this->getDefinition($name)->getType() . '::' . $pair[1]);
} else { // @service::property
$val = new Statement(['@' . $name, '$' . $pair[1]]);
try {
array_walk_recursive($arguments, function (&$val) {
if ($val instanceof Statement) {
$val = $this->completeStatement($val);

} elseif ($val === $this) {
trigger_error("Replace object ContainerBuilder in Statement arguments with '@container'.", E_USER_DEPRECATED);
$val = self::literal('$this');

} elseif ($val instanceof ServiceDefinition) {
$val = '@' . current(array_keys($this->getDefinitions(), $val, true));

} elseif (is_string($val) && strlen($val) > 1 && $val[0] === '@' && $val[1] !== '@') {
$pair = explode('::', $val, 2);
$name = $this->getServiceName($pair[0]);
if (!isset($pair[1])) { // @service
$val = '@' . $name;
} elseif (preg_match('#^[A-Z][A-Z0-9_]*\z#', $pair[1], $m)) { // @service::CONSTANT
$val = self::literal($this->getDefinition($name)->getType() . '::' . $pair[1]);
} else { // @service::property
$val = new Statement(['@' . $name, '$' . $pair[1]]);
}
}
});

} catch (ServiceCreationException $e) {
if ((is_string($entity) || is_array($entity)) && !strpos($e->getMessage(), ' (used in')) {
$desc = is_string($entity)
? $entity . '::__construct'
: (is_string($entity[0]) ? ($entity[0] . '::') : 'method ') . $entity[1];
$e->setMessage($e->getMessage() . " (used in $desc)");
}
});
throw $e;
}

return new Statement($entity, $arguments);
}
Expand Down
24 changes: 12 additions & 12 deletions tests/DI/ContainerBuilder.factory.error.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -164,14 +164,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.");
}, Nette\InvalidStateException::class, "Service 'one' (type of Good): Class Unknown not found. (used in Good::__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.");
}, Nette\InvalidStateException::class, "Service 'one' (type of Good): Class Bad8 has private constructor. (used in Good::__construct)");


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


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


// autowiring fail in argument
Expand All @@ -271,7 +271,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())");
}, 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)");


// forced autowiring fail in argument
Expand All @@ -282,7 +282,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");
}, 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 @@ -293,7 +293,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())");
}, 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)");


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


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


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


// autowiring fail in method calling
Expand Down Expand Up @@ -360,7 +360,7 @@ services:
setup:
- bar(@\stdClass)
');
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b");
}, 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 @@ -374,4 +374,4 @@ services:
setup:
- bar(MethodParam()::foo(@\stdClass))
');
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b");
}, Nette\DI\ServiceCreationException::class, "Service 'bad' (type of Good): Multiple services of type stdClass found: a, b (used in method foo)");

0 comments on commit 3f8f212

Please sign in to comment.