Class: RBS::Rewriter
- Inherits:
-
Object
- Object
- RBS::Rewriter
- Defined in:
- sig/rewriter.rbs,
lib/rbs/rewriter.rb
Overview
Rewriter performs targeted character-range replacements on Buffer content.
Unlike Writer which regenerates entire source from AST, Rewriter preserves everything outside the rewritten ranges, including non-documentation comments.
Rewrite requests are buffered and applied all at once when #string is called.
Instance Attribute Summary collapse
-
#buffer ⇒ Buffer
readonly
Returns the value of attribute buffer.
Instance Method Summary collapse
-
#add_comment(*locations, content:) ⇒ self
Add a new comment before the earliest of the given locations.
-
#delete_comment(comment) ⇒ self
Delete an existing comment.
- #format_comment(content, indent) ⇒ String
-
#initialize(buffer) ⇒ Rewriter
constructor
Initialize with a toplevel buffer.
-
#replace_comment(comment, content:) ⇒ self
Replace an existing comment's content.
-
#rewrite(location, string) ⇒ self
Register a rewrite request for the given location.
-
#string ⇒ String
Apply all buffered rewrites and return the resulting string.
Constructor Details
#initialize(buffer) ⇒ Rewriter
Initialize with a toplevel buffer. Raises if the buffer has a parent (non-toplevel).
15 16 17 18 19 20 |
# File 'sig/rewriter.rbs', line 15 def initialize(buffer) raise "Rewriter only supports toplevel buffers" if buffer.parent @buffer = buffer @rewrites = [] end |
Instance Attribute Details
#buffer ⇒ Buffer (readonly)
Returns the value of attribute buffer.
5 6 7 |
# File 'lib/rbs/rewriter.rb', line 5 def buffer @buffer end |
Instance Method Details
#add_comment(*locations, content:) ⇒ self
Add a new comment before the earliest of the given locations.
23 24 25 26 27 28 29 30 31 32 |
# File 'sig/rewriter.rbs', line 23 def add_comment(*locations, content:) earliest = locations.min_by(&:start_pos) or raise "At least one location is required" insert_pos = earliest.start_pos indent = " " * earliest.start_column formatted = format_comment(content, indent) loc = Location.new(buffer, insert_pos, insert_pos) rewrite(loc, "#{formatted}\n#{indent}") end |
#delete_comment(comment) ⇒ self
Delete an existing comment.
31 32 33 34 35 36 37 |
# File 'sig/rewriter.rbs', line 31 def delete_comment(comment) location = comment.location or raise "Comment must have a location" line_start = location.start_pos - location.start_column line_end = location.end_pos + 1 loc = Location.new(buffer, line_start, line_end) rewrite(loc, "") end |
#format_comment(content, indent) ⇒ String
63 64 65 66 67 68 |
# File 'lib/rbs/rewriter.rb', line 63 def format_comment(content, indent) content.lines.map do |line| line = line.chomp line.empty? ? "#" : "# #{line}" end.join("\n#{indent}") end |
#replace_comment(comment, content:) ⇒ self
Replace an existing comment's content.
27 28 29 30 31 32 |
# File 'sig/rewriter.rbs', line 27 def replace_comment(comment, content:) location = comment.location or raise "Comment must have a location" indent = " " * location.start_column rewrite(location, format_comment(content, indent)) end |
#rewrite(location, string) ⇒ self
Register a rewrite request for the given location.
19 20 21 22 23 24 25 26 27 28 |
# File 'sig/rewriter.rbs', line 19 def rewrite(location, string) @rewrites.each do |existing_location, _| if location.start_pos < existing_location.end_pos && existing_location.start_pos < location.end_pos raise "Overlapping rewrites: #{existing_location} and #{location}" end end @rewrites << [location, string] self end |
#string ⇒ String
Apply all buffered rewrites and return the resulting string.
Raises if any rewrite ranges overlap.
37 38 39 40 41 42 43 44 45 |
# File 'sig/rewriter.rbs', line 37 def string result = buffer.content.dup @rewrites.sort_by { |location, _| location.start_pos }.reverse_each do |location, replacement| result[location.start_pos...location.end_pos] = replacement end result end |