From fd9cee5fc39a858ab513a102c9b7f7296feeb860 Mon Sep 17 00:00:00 2001 From: Earlopain <14981592+Earlopain@users.noreply.github.com> Date: Thu, 23 Apr 2026 15:26:25 +0200 Subject: [ruby/prism] Fix incompatibilities for `on_word_sep` in ripper It was mostly good, just a few edgecases: * word_sep always only contains a single line. if there are multiple lines, it is also multiple word_sep * Handle trailing whitespace The excluded testcase is interpolation mixed with heredoc. That is not currently handled properly and word_sep contains the content of the heredoc I also switched start/end_offset names in the method, they seem to be backwards https://github.com/ruby/prism/commit/2e151ad41b --- lib/prism/translation/ripper.rb | 28 +++++++++++++++++++++------- test/prism/ruby/ripper_test.rb | 5 +++-- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/lib/prism/translation/ripper.rb b/lib/prism/translation/ripper.rb index b066f3e3ac..00506d650e 100644 --- a/lib/prism/translation/ripper.rb +++ b/lib/prism/translation/ripper.rb @@ -704,6 +704,8 @@ module Prism previous = element end + visit_words_sep(opening_loc, node.elements.last, node.closing_loc) + bounds(node.closing_loc) on_tstring_end(node.closing) when /^%i/ @@ -723,6 +725,8 @@ module Prism previous = element end + visit_words_sep(opening_loc, node.elements.last, node.closing_loc) + bounds(node.closing_loc) on_tstring_end(node.closing) when /^%W/ @@ -760,6 +764,8 @@ module Prism previous = element end + visit_words_sep(opening_loc, node.elements.last, node.closing_loc) + bounds(node.closing_loc) on_tstring_end(node.closing) when /^%I/ @@ -797,6 +803,8 @@ module Prism previous = element end + visit_words_sep(opening_loc, node.elements.last, node.closing_loc) + bounds(node.closing_loc) on_tstring_end(node.closing) else @@ -813,15 +821,21 @@ module Prism on_array(elements) end - # Dispatch a words_sep event that contains the space between the elements + # Dispatch words_sep events that contains the whitespace between the elements # of list literals. private def visit_words_sep(opening_loc, previous, current) - end_offset = (previous.nil? ? opening_loc : previous.location).end_offset - start_offset = current.location.start_offset - - if end_offset != start_offset - bounds(current.location.copy(start_offset: end_offset)) - on_words_sep(source.byteslice(end_offset...start_offset)) + start_offset = (previous.nil? ? opening_loc : previous.location).end_offset + end_offset = current.start_offset + length = end_offset - start_offset + + if length > 0 + whitespace = source.byteslice(start_offset, length) + current_offset = start_offset + whitespace.each_line do |part| + bounds(opening_loc.copy(start_offset: current_offset, length: part.bytesize)) + on_words_sep(part) + current_offset += part.bytesize + end end end diff --git a/test/prism/ruby/ripper_test.rb b/test/prism/ruby/ripper_test.rb index 61065e3ffc..cdb8375f96 100644 --- a/test/prism/ruby/ripper_test.rb +++ b/test/prism/ruby/ripper_test.rb @@ -101,6 +101,7 @@ module Prism "seattlerb/messy_op_asgn_lineno.txt", "seattlerb/op_asgn_primary_colon_const_command_call.txt", "seattlerb/parse_pattern_076.txt", + "seattlerb/pct_w_heredoc_interp_nested.txt", "tilde_heredocs.txt", "unparser/corpus/literal/assignment.txt", "unparser/corpus/literal/pattern.txt", @@ -138,11 +139,11 @@ module Prism end end - UNSUPPORTED_EVENTS = %i[comma ignored_nl label_end nl semicolon sp words_sep ignored_sp] + UNSUPPORTED_EVENTS = %i[comma ignored_nl label_end nl semicolon sp ignored_sp] # Events that are currently not emitted SUPPORTED_EVENTS = Translation::Ripper::EVENTS - UNSUPPORTED_EVENTS # Events that assert against their line/column - CHECK_LOCATION_EVENTS = %i[kw op lbrace rbrace lbracket rbracket lparen rparen] + CHECK_LOCATION_EVENTS = %i[kw op lbrace rbrace lbracket rbracket lparen rparen words_sep] module Events attr_reader :events -- cgit v1.2.3