From 8963a2176b5201239191e67d988937b1fa73da19 Mon Sep 17 00:00:00 2001 From: Marc-Andre Lafortune Date: Tue, 21 Jul 2020 23:25:41 -0400 Subject: [PATCH] - Circumvent bug with `racc` where Parser#parse could return `false` --- lib/parser/base.rb | 11 ++++++----- test/test_parser.rb | 10 ++++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/lib/parser/base.rb b/lib/parser/base.rb index b8096a23c..89dbc8589 100644 --- a/lib/parser/base.rb +++ b/lib/parser/base.rb @@ -177,16 +177,16 @@ def reset end ## - # Parses a source buffer and returns the AST. + # Parses a source buffer and returns the AST, or `nil` in case of a non fatal error. # # @param [Parser::Source::Buffer] source_buffer The source buffer to parse. - # @return [Parser::AST::Node] + # @return [Parser::AST::Node, nil] # def parse(source_buffer) @lexer.source_buffer = source_buffer @source_buffer = source_buffer - do_parse + do_parse || nil # Force `false` to `nil`, see https://github.com/ruby/racc/pull/136 ensure # Don't keep references to the source file. @source_buffer = nil @@ -210,8 +210,9 @@ def parse_with_comments(source_buffer) ## # Parses a source buffer and returns the AST, the source code comments, - # and the tokens emitted by the lexer. If `recover` is true and a fatal - # {SyntaxError} is encountered, `nil` is returned instead of the AST, and + # and the tokens emitted by the lexer. In case of a fatal error, a {SyntaxError} + # is raised, unless `recover` is true. In case of an error + # (non-fatal or recovered), `nil` is returned instead of the AST, and # comments as well as tokens are only returned up to the location of # the error. # diff --git a/test/test_parser.rb b/test/test_parser.rb index b87028091..eab8445fa 100644 --- a/test/test_parser.rb +++ b/test/test_parser.rb @@ -9796,4 +9796,14 @@ def test_find_pattern %q{ ~~~~~~~~ expression (in_pattern.find_pattern)}, SINCE_2_8) end + + def test_invalid_source + with_versions(ALL_VERSIONS) do |_ver, parser| + source_file = Parser::Source::Buffer.new('(comments)', source: "def foo; en") + + parser.diagnostics.all_errors_are_fatal = false + ast = parser.parse(source_file) + assert_nil(ast) + end + end end