Repository: ruby/prism
Pull request #2692 (2024-04-11 18:38:59)

Add Location#chop


Patch:
diff --git a/lib/prism/desugar_compiler.rb b/lib/prism/desugar_compiler.rb
index 8d059b0c..9b62c00d 100644
--- a/lib/prism/desugar_compiler.rb
+++ b/lib/prism/desugar_compiler.rb
@@ -73,6 +73,8 @@ module Prism
 
     # Desugar `x += y` to `x = x + y`
     def compile
+      operator_loc = node.operator_loc.chop
+
       write_class.new(
         source,
         *arguments,
@@ -82,8 +84,8 @@ module Prism
           0,
           read_class.new(source, *arguments, node.name_loc),
           nil,
-          node.operator_loc.slice.chomp("=").to_sym,
-          node.operator_loc.copy(length: node.operator_loc.length - 1),
+          operator_loc.slice.to_sym,
+          operator_loc,
           nil,
           ArgumentsNode.new(source, 0, [node.value], node.value.location),
           nil,
diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb
index b6109b09..39e15f60 100644
--- a/lib/prism/parse_result.rb
+++ b/lib/prism/parse_result.rb
@@ -161,6 +161,11 @@ module Prism
       Location.new(source, start_offset, length)
     end
 
+    # Returns a new location that is the result of chopping off the last byte.
+    def chop
+      copy(length: length == 0 ? length : length - 1)
+    end
+
     # Returns a string representation of this location.
     def inspect
       "#<Prism::Location @start_offset=#{@start_offset} @length=#{@length} start_line=#{start_line}>"
diff --git a/rbi/prism/parse_result.rbi b/rbi/prism/parse_result.rbi
index 00bf3514..dd465e00 100644
--- a/rbi/prism/parse_result.rbi
+++ b/rbi/prism/parse_result.rbi
@@ -72,6 +72,9 @@ class Prism::Location
   sig { params(source: Prism::Source, start_offset: Integer, length: Integer).returns(Prism::Location) }
   def copy(source: self.source, start_offset: self.start_offset, length: self.length); end
 
+  sig { returns(Prism::Location) }
+  def chop; end
+
   sig { returns(String) }
   def inspect; end
 
diff --git a/sig/prism/parse_result.rbs b/sig/prism/parse_result.rbs
index 1faf6ac1..b0022c6b 100644
--- a/sig/prism/parse_result.rbs
+++ b/sig/prism/parse_result.rbs
@@ -29,6 +29,7 @@ module Prism
     def trailing_comment: (comment) -> void
     def comments: () -> Array[comment]
     def copy: (?source: Source, ?start_offset: Integer, ?length: Integer) -> Location
+    def chop: () -> Location
     def slice: () -> String
     def start_character_offset: () -> Integer
     def end_offset: () -> Integer


Test patch:
diff --git a/test/prism/ruby_api_test.rb b/test/prism/ruby_api_test.rb
index 49296117..64188871 100644
--- a/test/prism/ruby_api_test.rb
+++ b/test/prism/ruby_api_test.rb
@@ -198,6 +198,17 @@ module Prism
       assert_equal 7, location.end_code_units_column(Encoding::UTF_32LE)
     end
 
+    def test_location_chop
+      location = Prism.parse("foo").value.location
+
+      assert_equal "fo", location.chop.slice
+      assert_equal "", location.chop.chop.chop.slice
+
+      # Check that we don't go negative.
+      10.times { location = location.chop }
+      assert_equal "", location.slice
+    end
+
     def test_heredoc?
       refute parse_expression("\"foo\"").heredoc?
       refute parse_expression("\"foo \#{1}\"").heredoc?