Class: Prosereflect::Transform::StepMap

Inherits:
Object
  • Object
show all
Defined in:
lib/prosereflect/transform/step_map.rb

Overview

Maps positions through a step. Represents how positions change when a step is applied.

Defined Under Namespace

Classes: Result

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(ranges = []) ⇒ StepMap

Returns a new instance of StepMap.



10
11
12
# File 'lib/prosereflect/transform/step_map.rb', line 10

def initialize(ranges = [])
  @ranges = ranges
end

Instance Attribute Details

#rangesObject (readonly)

Array of [old_start, old_end, new_start, new_end]



8
9
10
# File 'lib/prosereflect/transform/step_map.rb', line 8

def ranges
  @ranges
end

Class Method Details

.delete(from, to) ⇒ Object

Create a step map for a single deletion



89
90
91
# File 'lib/prosereflect/transform/step_map.rb', line 89

def self.delete(from, to)
  new([[from, to, from, from]])
end

.emptyObject

Create an empty step map



84
85
86
# File 'lib/prosereflect/transform/step_map.rb', line 84

def self.empty
  new
end

.replace(from, to, target_from, target_to) ⇒ Object

Create a step map for a single replacement



94
95
96
97
# File 'lib/prosereflect/transform/step_map.rb', line 94

def self.replace(from, to, target_from, target_to)
  delta = target_to - target_from
  new([[from, to, target_from, target_from + delta]])
end

Instance Method Details

#add_map(other) ⇒ Object

Add another map to this one (composition)



45
46
47
48
49
50
# File 'lib/prosereflect/transform/step_map.rb', line 45

def add_map(other)
  return StepMap.new(other.ranges.dup) if @ranges.empty?
  return StepMap.new(@ranges.dup) if other.ranges.empty?

  StepMap.new(merge_ranges_arrays(@ranges.dup, other.ranges.dup))
end

#compute_merged_head(head1, head2, _ranges1, _ranges2) ⇒ Object



63
64
65
66
67
68
69
70
71
# File 'lib/prosereflect/transform/step_map.rb', line 63

def compute_merged_head(head1, head2, _ranges1, _ranges2)
  if head1[1] <= head2[0]
    head1
  elsif head2[1] <= head1[0]
    head2
  else
    merge_ranges(head1, head2)
  end
end

#compute_tail(head1, head2, ranges1, ranges2) ⇒ Object



73
74
75
76
77
78
79
80
81
# File 'lib/prosereflect/transform/step_map.rb', line 73

def compute_tail(head1, head2, ranges1, ranges2)
  if head1[1] <= head2[0]
    merge_ranges_arrays(ranges1[1..], ranges2)
  elsif head2[1] <= head1[0]
    merge_ranges_arrays(ranges1, ranges2[1..])
  else
    merge_ranges_arrays(ranges1[1..], ranges2[1..])
  end
end

#deleted?(pos) ⇒ Boolean

Check if a position was deleted by this step

Returns:

  • (Boolean)


38
39
40
41
42
# File 'lib/prosereflect/transform/step_map.rb', line 38

def deleted?(pos)
  @ranges.any? do |old_start, old_end, _new_start, _new_end|
    pos >= old_start && pos < old_end
  end
end

#inspectObject



103
104
105
# File 'lib/prosereflect/transform/step_map.rb', line 103

def inspect
  to_s
end

#map(pos) ⇒ Object

Map a position through this step map Returns the new position



16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/prosereflect/transform/step_map.rb', line 16

def map(pos)
  offset = 0
  @ranges.each do |old_start, old_end, new_start, new_end|
    if pos <= old_start
      return pos + (new_start - old_start)
    elsif pos < old_end
      return new_start + (pos - old_start)
    elsif pos >= old_end
      offset += (new_end - old_end)
    end
  end
  pos + offset
end

#map_result(pos, on_del: nil) ⇒ Object

Map a position, returning result with deletion information



31
32
33
34
35
# File 'lib/prosereflect/transform/step_map.rb', line 31

def map_result(pos, on_del: nil) # rubocop:disable Lint:UnusedMethodArgument
  new_pos = map(pos)
  deleted = deleted?(pos)
  Result.new(pos: new_pos, deleted: deleted, transformed: new_pos != pos)
end

#merge_ranges_arrays(ranges1, ranges2) ⇒ Object



52
53
54
55
56
57
58
59
60
61
# File 'lib/prosereflect/transform/step_map.rb', line 52

def merge_ranges_arrays(ranges1, ranges2)
  return ranges1 if ranges2.empty?
  return ranges2 if ranges1.empty?

  head1 = ranges1.first
  head2 = ranges2.first
  merged_head = compute_merged_head(head1, head2, ranges1, ranges2)
  tail = compute_tail(head1, head2, ranges1, ranges2)
  [merged_head] + tail
end

#to_sObject



99
100
101
# File 'lib/prosereflect/transform/step_map.rb', line 99

def to_s
  "<StepMap #{@ranges.inspect}>"
end