lib/solargraph/source/change.rb
# frozen_string_literal: true module Solargraph class Source # A change to be applied to text. # class Change include EncodingFixes # @return [Range] attr_reader :range # @return [String] attr_reader :new_text # @param range [Range] The starting and ending positions of the change. # If nil, the original text will be overwritten. # @param new_text [String] The text to be changed. def initialize range, new_text @range = range @new_text = new_text end # Write the change to the specified text. # # @param text [String] The text to be changed. # @param nullable [Boolean] If true, minor changes that could generate # syntax errors will be repaired. # @return [String] The updated text. def write text, nullable = false if nullable and !range.nil? and new_text.match(/[\.\[\{\(@\$:]$/) [':', '@'].each do |dupable| next unless new_text == dupable offset = Position.to_offset(text, range.start) if text[offset - 1] == dupable p = Position.from_offset(text, offset - 1) r = Change.new(Range.new(p, range.start), ' ') text = r.write(text) end break end commit text, "#{new_text[0..-2]} " elsif range.nil? new_text else commit text, new_text end end # Repair an update by replacing the new text with similarly formatted # whitespace. # # @param text [String] The text to be changed. # @return [String] The updated text. def repair text fixed = new_text.gsub(/[^\s]/, ' ') if range.nil? fixed else result = commit text, fixed off = Position.to_offset(text, range.start) match = result[0, off].match(/[\.:]+\z/) if match result = result[0, off].sub(/#{match[0]}\z/, ' ' * match[0].length) + result[off..-1] end result end end private # @param text [String] # @param insert [String] # @return [String] def commit text, insert start_offset = Position.to_offset(text, range.start) end_offset = Position.to_offset(text, range.ending) (start_offset == 0 ? '' : text[0..start_offset-1].to_s) + normalize(insert) + text[end_offset..-1].to_s end end end end