diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb index 2207a44fe5..e01aa070c2 100644 --- a/lib/prism/parse_result.rb +++ b/lib/prism/parse_result.rb @@ -45,6 +45,12 @@ module Prism offsets[find_line(byte_offset)] end + # Returns the byte offset of the end of the line corresponding to the given + # byte offset. + def line_end(byte_offset) + offsets[find_line(byte_offset) + 1] || source.bytesize + end + # Return the column number for the given byte offset. def column(byte_offset) byte_offset - line_start(byte_offset) @@ -176,6 +182,15 @@ module Prism source.slice(start_offset, length) end + # The source code that this location represents starting from the beginning + # of the line that this location starts on to the end of the line that this + # location ends on. + def slice_lines + line_start = source.line_start(start_offset) + line_end = source.line_end(end_offset) + source.slice(line_start, line_end - line_start) + end + # The character offset from the beginning of the source where this location # starts. def start_character_offset diff --git a/prism/templates/lib/prism/node.rb.erb b/prism/templates/lib/prism/node.rb.erb index 2606af5704..ddbe53e594 100644 --- a/prism/templates/lib/prism/node.rb.erb +++ b/prism/templates/lib/prism/node.rb.erb @@ -45,6 +45,13 @@ module Prism location.slice end + # Slice the location of the node from the source, starting at the beginning + # of the line that the location starts on, ending at the end of the line + # that the location ends on. + def slice_lines + location.slice_lines + end + # Similar to inspect, but respects the current level of indentation given by # the pretty print object. def pretty_print(q) diff --git a/test/prism/ruby_api_test.rb b/test/prism/ruby_api_test.rb index bf493666d2..9e408d1edd 100644 --- a/test/prism/ruby_api_test.rb +++ b/test/prism/ruby_api_test.rb @@ -209,6 +209,13 @@ module Prism assert_equal "", location.slice end + def test_location_slice_lines + result = Prism.parse("\nprivate def foo\nend\n") + method = result.value.statements.body.first.arguments.arguments.first + + assert_equal "private def foo\nend\n", method.slice_lines + end + def test_heredoc? refute parse_expression("\"foo\"").heredoc? refute parse_expression("\"foo \#{1}\"").heredoc?