feature #28085 [Config] show proposals when unsupported option is provided (fmata)

This PR was merged into the 4.2-dev branch.

Discussion
----------

[Config] show proposals when unsupported option is provided

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #28075
| License       | MIT
| Doc PR        | none

In case of proposals match with the provided option, all proposals are displayed.
In case of no pertinent proposal is available, all options are displayed in alpha order.

Commits
-------

15f69a3e81 [Config] show proposals when unsupported option is provided
This commit is contained in:
Nicolas Grekas 2018-08-10 08:46:52 +02:00
commit 550b8b88d5
2 changed files with 48 additions and 0 deletions

View File

@ -307,7 +307,30 @@ class ArrayNode extends BaseNode implements PrototypeNodeInterface
// if extra fields are present, throw exception
if (\count($value) && !$this->ignoreExtraKeys) {
$proposals = array_keys($this->children);
sort($proposals);
$guesses = array();
foreach (array_keys($value) as $subject) {
$minScore = INF;
foreach ($proposals as $proposal) {
$distance = levenshtein($subject, $proposal);
if ($distance <= $minScore && $distance < 3) {
$guesses[$proposal] = $distance;
$minScore = $distance;
}
}
}
$msg = sprintf('Unrecognized option%s "%s" under "%s"', 1 === \count($value) ? '' : 's', implode(', ', array_keys($value)), $this->getPath());
if (\count($guesses)) {
asort($guesses);
$msg .= sprintf('. Did you mean "%s"?', implode('", "', array_keys($guesses)));
} else {
$msg .= sprintf('. Available option%s %s "%s".', 1 === \count($proposals) ? '' : 's', 1 === \count($proposals) ? 'is' : 'are', implode('", "', $proposals));
}
$ex = new InvalidConfigurationException($msg);
$ex->setPath($this->getPath());

View File

@ -37,6 +37,31 @@ class ArrayNodeTest extends TestCase
$node->normalize(array('foo' => 'bar'));
}
/**
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
* @expectedExceptionMessage Did you mean "alpha1", "alpha2"?
*/
public function testNormalizeWithProposals()
{
$node = new ArrayNode('root');
$node->addChild(new ArrayNode('alpha1'));
$node->addChild(new ArrayNode('alpha2'));
$node->addChild(new ArrayNode('beta'));
$node->normalize(array('alpha3' => 'foo'));
}
/**
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
* @expectedExceptionMessage Available options are "alpha1", "alpha2".
*/
public function testNormalizeWithoutProposals()
{
$node = new ArrayNode('root');
$node->addChild(new ArrayNode('alpha1'));
$node->addChild(new ArrayNode('alpha2'));
$node->normalize(array('beta' => 'foo'));
}
public function ignoreAndRemoveMatrixProvider()
{
$unrecognizedOptionException = new InvalidConfigurationException('Unrecognized option "foo" under "root"');