Skip to content

Commit

Permalink
Display all syntax error messages when catching SyntaxException
Browse files Browse the repository at this point in the history
Previously when catching syntax errors in the REPL, we were only showing
the last syntax error displayed by the ruby output. However, ruby can
generate multiple syntax error messages within a single SyntaxException.
For example, this code generates multiple syntax error messages:
```
$ ruby -e 'puts {"key"=>"val"}.to_json'
-e:1: syntax error, unexpected =>, expecting '}'
puts {"key"=>"val"}.to_json
-e:1: syntax error, unexpected '}', expecting end-of-input
puts {"key"=>"val"}.to_json
```
We can't predict which error message would be most helpful for the
consumer - we should show both of them.

This commit modifies the string replacement we're doing when printing
SyntaxExceptions so any number of syntax error lines will be shown
correctly.

Issue: #2102
The error message of SyntaxError is different from Ruby's one
  • Loading branch information
bingram-eab committed Mar 21, 2020
1 parent 2208ed3 commit 773350c
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 6 deletions.
2 changes: 1 addition & 1 deletion lib/pry/pry_instance.rb
Expand Up @@ -627,7 +627,7 @@ def handle_line(line, options)
begin
complete_expr = Pry::Code.complete_expression?(@eval_string)
rescue SyntaxError => e
output.puts "SyntaxError: #{e.message.sub(/.*syntax error, */m, '')}"
output.puts e.message.gsub(/^.*syntax error, */, "SyntaxError: ")
reset_eval_string
end

Expand Down
28 changes: 23 additions & 5 deletions spec/syntax_checking_spec.rb
Expand Up @@ -23,24 +23,42 @@
end
end

([
[
["end"],
["puts )("],
["1 1"],
["puts :"]
] + [
["puts :"],

# in this case the syntax error is "expecting ')'".
["def", "method(1"],

# in this case the syntax error is "expecting keyword_end".
["o = Object.new.tap{ def o.render;", "'MEH'", "}"]
]).compact.each do |foo|
["o = Object.new.tap{ def o.render;", "'MEH'", "}"],

# multiple syntax errors reported in one SyntaxException
["puts {'key'=>'val'}.to_json"]
].compact.each do |foo|
it "should raise an error on invalid syntax like #{foo.inspect}" do
redirect_pry_io(InputTester.new(*foo), @str_output) do
Pry.start
end

expect(@str_output.string).to match(/SyntaxError/)
end

it "should display the correct number of errors on invalid syntax like #{foo.inspect}" do
begin
# rubocop:disable Security/Eval
eval(foo.join("\n"))
# rubocop:enable Security/Eval
rescue SyntaxError => e
error_count = e.message.scan(/syntax error/).count
end
expect(error_count).not_to be_nil

pry_output = mock_pry(*foo)
expect(pry_output.scan(/SyntaxError/).count).to eq(error_count)
end
end

it "should not intefere with syntax errors explicitly raised" do
Expand Down

0 comments on commit 773350c

Please sign in to comment.