зеркало из https://github.com/github/ruby.git
[ruby/prism] Raise diagnostics for parser
https://github.com/ruby/prism/commit/102b4a16f5
This commit is contained in:
Родитель
adf29c9a98
Коммит
e050097beb
|
@ -9,6 +9,20 @@ module Prism
|
|||
# the parser gem, and overrides the parse* methods to parse with prism and
|
||||
# then translate.
|
||||
class Parser < ::Parser::Base
|
||||
# The parser gem has a list of diagnostics with a hard-coded set of error
|
||||
# messages. We create our own diagnostic class in order to set our own
|
||||
# error messages.
|
||||
class Diagnostic < ::Parser::Diagnostic
|
||||
# The message generated by prism.
|
||||
attr_reader :message
|
||||
|
||||
# Initialize a new diagnostic with the given message and location.
|
||||
def initialize(message, location)
|
||||
@message = message
|
||||
super(:error, :prism_error, {}, location, [])
|
||||
end
|
||||
end
|
||||
|
||||
Racc_debug_parser = false # :nodoc:
|
||||
|
||||
def version # :nodoc:
|
||||
|
@ -28,10 +42,9 @@ module Prism
|
|||
@source_buffer = source_buffer
|
||||
source = source_buffer.source
|
||||
|
||||
build_ast(
|
||||
Prism.parse(source, filepath: source_buffer.name).value,
|
||||
build_offset_cache(source)
|
||||
)
|
||||
result = unwrap(Prism.parse(source, filepath: source_buffer.name))
|
||||
|
||||
build_ast(result.value, build_offset_cache(source))
|
||||
ensure
|
||||
@source_buffer = nil
|
||||
end
|
||||
|
@ -42,7 +55,7 @@ module Prism
|
|||
source = source_buffer.source
|
||||
|
||||
offset_cache = build_offset_cache(source)
|
||||
result = Prism.parse(source, filepath: source_buffer.name)
|
||||
result = unwrap(Prism.parse(source, filepath: source_buffer.name))
|
||||
|
||||
[
|
||||
build_ast(result.value, offset_cache),
|
||||
|
@ -59,7 +72,8 @@ module Prism
|
|||
source = source_buffer.source
|
||||
|
||||
offset_cache = build_offset_cache(source)
|
||||
result = Prism.parse_lex(source, filepath: source_buffer.name)
|
||||
result = unwrap(Prism.parse_lex(source, filepath: source_buffer.name))
|
||||
|
||||
program, tokens = result.value
|
||||
|
||||
[
|
||||
|
@ -79,6 +93,18 @@ module Prism
|
|||
|
||||
private
|
||||
|
||||
# If there was a error generated during the parse, then raise an
|
||||
# appropriate syntax error. Otherwise return the result.
|
||||
def unwrap(result)
|
||||
return result if result.success?
|
||||
|
||||
error = result.errors.first
|
||||
offset_cache = build_offset_cache(source_buffer.source)
|
||||
|
||||
diagnostic = Diagnostic.new(error.message, build_range(error.location, offset_cache))
|
||||
raise ::Parser::SyntaxError, diagnostic
|
||||
end
|
||||
|
||||
# Prism deals with offsets in bytes, while the parser gem deals with
|
||||
# offsets in characters. We need to handle this conversion in order to
|
||||
# build the parser gem AST.
|
||||
|
@ -109,15 +135,7 @@ module Prism
|
|||
# Build the parser gem comments from the prism comments.
|
||||
def build_comments(comments, offset_cache)
|
||||
comments.map do |comment|
|
||||
location = comment.location
|
||||
|
||||
::Parser::Source::Comment.new(
|
||||
::Parser::Source::Range.new(
|
||||
source_buffer,
|
||||
offset_cache[location.start_offset],
|
||||
offset_cache[location.end_offset]
|
||||
)
|
||||
)
|
||||
::Parser::Source::Comment.new(build_range(comment.location, offset_cache))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -126,6 +144,15 @@ module Prism
|
|||
Lexer.new(source_buffer, tokens.map(&:first), offset_cache).to_a
|
||||
end
|
||||
|
||||
# Build a range from a prism location.
|
||||
def build_range(location, offset_cache)
|
||||
::Parser::Source::Range.new(
|
||||
source_buffer,
|
||||
offset_cache[location.start_offset],
|
||||
offset_cache[location.end_offset]
|
||||
)
|
||||
end
|
||||
|
||||
require_relative "parser/compiler"
|
||||
require_relative "parser/lexer"
|
||||
|
||||
|
|
|
@ -83,11 +83,16 @@ module Prism
|
|||
elements = [*node.requireds]
|
||||
elements << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode)
|
||||
elements.concat(node.posts)
|
||||
visited = visit_all(elements)
|
||||
|
||||
if node.rest.is_a?(ImplicitRestNode)
|
||||
visited[-1] = builder.match_with_trailing_comma(visited[-1], token(node.rest.location))
|
||||
end
|
||||
|
||||
if node.constant
|
||||
builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.array_pattern(nil, visit_all(elements), nil), token(node.closing_loc))
|
||||
builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.array_pattern(nil, visited, nil), token(node.closing_loc))
|
||||
else
|
||||
builder.array_pattern(token(node.opening_loc), visit_all(elements), token(node.closing_loc))
|
||||
builder.array_pattern(token(node.opening_loc), visited, token(node.closing_loc))
|
||||
end
|
||||
end
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче