From f19cf8a9164183614c69fa3180d51281ff765ac5 Mon Sep 17 00:00:00 2001 From: Florent Mata Date: Mon, 28 Aug 2017 15:28:19 +0200 Subject: [PATCH] [ExpressionLanguage] make a proposal in SyntaxError message --- .../Component/ExpressionLanguage/Parser.php | 4 ++-- .../ExpressionLanguage/SyntaxError.php | 17 ++++++++++++++++- .../ExpressionLanguage/Tests/ParserTest.php | 12 ++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/ExpressionLanguage/Parser.php b/src/Symfony/Component/ExpressionLanguage/Parser.php index c75972447d..3b36703015 100644 --- a/src/Symfony/Component/ExpressionLanguage/Parser.php +++ b/src/Symfony/Component/ExpressionLanguage/Parser.php @@ -195,13 +195,13 @@ class Parser default: if ('(' === $this->stream->current->value) { if (false === isset($this->functions[$token->value])) { - throw new SyntaxError(sprintf('The function "%s" does not exist', $token->value), $token->cursor, $this->stream->getExpression()); + throw new SyntaxError(sprintf('The function "%s" does not exist', $token->value), $token->cursor, $this->stream->getExpression(), $token->value, array_keys($this->functions)); } $node = new Node\FunctionNode($token->value, $this->parseArguments()); } else { if (!in_array($token->value, $this->names, true)) { - throw new SyntaxError(sprintf('Variable "%s" is not valid', $token->value), $token->cursor, $this->stream->getExpression()); + throw new SyntaxError(sprintf('Variable "%s" is not valid', $token->value), $token->cursor, $this->stream->getExpression(), $token->value, $this->names); } // is the name used in the compiled code different diff --git a/src/Symfony/Component/ExpressionLanguage/SyntaxError.php b/src/Symfony/Component/ExpressionLanguage/SyntaxError.php index 9373e9980b..12348e6830 100644 --- a/src/Symfony/Component/ExpressionLanguage/SyntaxError.php +++ b/src/Symfony/Component/ExpressionLanguage/SyntaxError.php @@ -13,7 +13,7 @@ namespace Symfony\Component\ExpressionLanguage; class SyntaxError extends \LogicException { - public function __construct($message, $cursor = 0, $expression = '') + public function __construct($message, $cursor = 0, $expression = '', $subject = null, array $proposals = null) { $message = sprintf('%s around position %d', $message, $cursor); if ($expression) { @@ -21,6 +21,21 @@ class SyntaxError extends \LogicException } $message .= '.'; + if (null !== $subject && null !== $proposals) { + $minScore = INF; + foreach ($proposals as $proposal) { + $distance = levenshtein($subject, $proposal); + if ($distance < $minScore) { + $guess = $proposal; + $minScore = $distance; + } + } + + if (isset($guess) && $minScore < 3) { + $message .= sprintf(' Did you mean "%s"?', $guess); + } + } + parent::__construct($message); } } diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php index 13b80cd64f..11464abd23 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php @@ -195,4 +195,16 @@ class ParserTest extends TestCase ), ); } + + /** + * @expectedException \Symfony\Component\ExpressionLanguage\SyntaxError + * @expectedExceptionMessage Did you mean "baz"? + */ + public function testNameProposal() + { + $lexer = new Lexer(); + $parser = new Parser(array()); + + $parser->parse($lexer->tokenize('foo > bar'), array('foo', 'baz')); + } }