From c12acb559445c25b21a464633cc4a1df7a644cc3 Mon Sep 17 00:00:00 2001 From: fujitani sora Date: Sun, 1 Feb 2026 12:39:21 +0900 Subject: [PATCH 1/2] feat: heardoc cmt del --- lib/rfmt/prism_bridge.rb | 46 +++++++++++++++++++++++++++++++--------- spec/rfmt_spec.rb | 45 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 10 deletions(-) diff --git a/lib/rfmt/prism_bridge.rb b/lib/rfmt/prism_bridge.rb index 2af825b..2c24deb 100644 --- a/lib/rfmt/prism_bridge.rb +++ b/lib/rfmt/prism_bridge.rb @@ -125,16 +125,14 @@ def self.extract_location(node) end end - # Check child nodes for heredoc (e.g., LocalVariableWriteNode containing StringNode) - node.child_nodes.compact.each do |child| - next unless child.respond_to?(:closing_loc) && child.closing_loc - - closing = child.closing_loc - next unless closing.end_offset > end_offset - - end_offset = closing.end_offset - end_line = closing.end_line - end_column = closing.end_column + # Recursively check all descendant nodes for heredoc closing_loc + # Issue #74: handled direct children (e.g., LocalVariableWriteNode -> StringNode) + # Issue #86: handles deeper nesting (e.g., CallNode -> ArgumentsNode -> StringNode) + max_closing = find_max_closing_loc_recursive(node) + if max_closing && max_closing[:end_offset] > end_offset + end_offset = max_closing[:end_offset] + end_line = max_closing[:end_line] + end_column = max_closing[:end_column] end { @@ -147,6 +145,34 @@ def self.extract_location(node) } end + # Recursively find the maximum closing_loc among all descendant nodes + # Returns nil if no closing_loc found, otherwise { end_offset:, end_line:, end_column: } + def self.find_max_closing_loc_recursive(node, depth: 0) + return nil if depth > 10 + + max_closing = nil + + node.child_nodes.compact.each do |child| + if child.respond_to?(:closing_loc) && child.closing_loc + closing = child.closing_loc + if max_closing.nil? || closing.end_offset > max_closing[:end_offset] + max_closing = { + end_offset: closing.end_offset, + end_line: closing.end_line, + end_column: closing.end_column + } + end + end + + child_max = find_max_closing_loc_recursive(child, depth: depth + 1) + if child_max && (max_closing.nil? || child_max[:end_offset] > max_closing[:end_offset]) + max_closing = child_max + end + end + + max_closing + end + # Extract child nodes def self.extract_children(node) children = [] diff --git a/spec/rfmt_spec.rb b/spec/rfmt_spec.rb index 36220ee..7bdda28 100644 --- a/spec/rfmt_spec.rb +++ b/spec/rfmt_spec.rb @@ -184,6 +184,51 @@ def bar = 42 end end + describe 'heredoc in method call arguments (Issue #86)' do + it 'preserves multiple heredocs as method arguments' do + source = <<~RUBY + puts(<<~HEREDOC, <<~HEREDOC2) + This is a heredoc. + HEREDOC + This is another heredoc. + HEREDOC2 + RUBY + result = Rfmt.format(source) + + expect(result).to include('This is a heredoc.') + expect(result).to include('This is another heredoc.') + expect(result).to match(/^HEREDOC$/m) + expect(result).to match(/^HEREDOC2$/m) + expect(Prism.parse(result).errors).to be_empty + end + + it 'preserves single heredoc as method argument' do + source = <<~RUBY + puts(<<~HEREDOC) + Single heredoc content. + HEREDOC + RUBY + result = Rfmt.format(source) + + expect(result).to include('Single heredoc content.') + expect(result).to match(/^HEREDOC$/m) + expect(Prism.parse(result).errors).to be_empty + end + + it 'preserves heredoc with method chain' do + source = <<~RUBY + foo.bar(<<~SQL) + SELECT * FROM users + SQL + RUBY + result = Rfmt.format(source) + + expect(result).to include('SELECT * FROM users') + expect(result).to match(/^SQL$/m) + expect(Prism.parse(result).errors).to be_empty + end + end + describe 'inline then style preservation (Issue #75)' do describe 'case...in with then' do it 'preserves inline then style in pattern matching' do From 2bec84b0a836da70bb7babc8df8d3cbb8d3053bf Mon Sep 17 00:00:00 2001 From: fujitani sora Date: Sun, 1 Feb 2026 12:40:29 +0900 Subject: [PATCH 2/2] cop --- lib/rfmt/prism_bridge.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/rfmt/prism_bridge.rb b/lib/rfmt/prism_bridge.rb index 2c24deb..f735675 100644 --- a/lib/rfmt/prism_bridge.rb +++ b/lib/rfmt/prism_bridge.rb @@ -165,9 +165,7 @@ def self.find_max_closing_loc_recursive(node, depth: 0) end child_max = find_max_closing_loc_recursive(child, depth: depth + 1) - if child_max && (max_closing.nil? || child_max[:end_offset] > max_closing[:end_offset]) - max_closing = child_max - end + max_closing = child_max if child_max && (max_closing.nil? || child_max[:end_offset] > max_closing[:end_offset]) end max_closing