Class: Gitlab::Diff::InlineDiff

Inherits:
Object
  • Object
show all
Defined in:
lib/gitlab/diff/inline_diff.rb

Constant Summary collapse

LINE_PAIRS_PATTERN =

Regex to find a run of deleted lines followed by the same number of added lines

%r{
  # Runs start at the beginning of the string (the first line) or after a space (for an unchanged line)
  (?:\A|\s)

  # This matches a number of `-`s followed by the same number of `+`s through recursion
  (?<del_ins>
    -
    \g<del_ins>?
    \+
  )

  # Runs end at the end of the string (the last line) or before a space (for an unchanged line)
  (?=\s|\z)
}x.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(old_line, new_line, offset: 0) ⇒ InlineDiff

Returns a new instance of InlineDiff.


24
25
26
27
28
# File 'lib/gitlab/diff/inline_diff.rb', line 24

def initialize(old_line, new_line, offset: 0)
  @old_line = old_line[offset..-1]
  @new_line = new_line[offset..-1]
  @offset = offset
end

Instance Attribute Details

#new_lineObject

Returns the value of attribute new_line


22
23
24
# File 'lib/gitlab/diff/inline_diff.rb', line 22

def new_line
  @new_line
end

#offsetObject

Returns the value of attribute offset


22
23
24
# File 'lib/gitlab/diff/inline_diff.rb', line 22

def offset
  @offset
end

#old_lineObject

Returns the value of attribute old_line


22
23
24
# File 'lib/gitlab/diff/inline_diff.rb', line 22

def old_line
  @old_line
end

Class Method Details

.for_lines(lines) ⇒ Object


51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/gitlab/diff/inline_diff.rb', line 51

def for_lines(lines)
  changed_line_pairs = find_changed_line_pairs(lines)

  inline_diffs = []

  changed_line_pairs.each do |old_index, new_index|
    old_line = lines[old_index]
    new_line = lines[new_index]

    old_diffs, new_diffs = new(old_line, new_line, offset: 1).inline_diffs

    inline_diffs[old_index] = old_diffs
    inline_diffs[new_index] = new_diffs
  end

  inline_diffs
end

Instance Method Details

#inline_diffsObject


30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/gitlab/diff/inline_diff.rb', line 30

def inline_diffs
  # Skip inline diff if empty line was replaced with content
  return if old_line == ""

  lcp = longest_common_prefix(old_line, new_line)
  lcs = longest_common_suffix(old_line[lcp..-1], new_line[lcp..-1])

  lcp += offset
  old_length = old_line.length + offset
  new_length = new_line.length + offset

  old_diff_range = lcp..(old_length - lcs - 1)
  new_diff_range = lcp..(new_length - lcs - 1)

  old_diffs = [old_diff_range] if old_diff_range.begin <= old_diff_range.end
  new_diffs = [new_diff_range] if new_diff_range.begin <= new_diff_range.end

  [old_diffs, new_diffs]
end