Class: Bugsage::CodePatch

Inherits:
Object
  • Object
show all
Defined in:
lib/bugsage/code_patch.rb

Constant Summary collapse

ACTIONS =
%w[replace_lines delete_lines insert_before no_change].freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(action:, start_line:, end_line: nil, replacement: "") ⇒ CodePatch

Returns a new instance of CodePatch.



9
10
11
12
13
14
# File 'lib/bugsage/code_patch.rb', line 9

def initialize(action:, start_line:, end_line: nil, replacement: "")
  @action = normalize_action(action)
  @start_line = start_line.to_i
  @end_line = (end_line || start_line).to_i
  @replacement = replacement.to_s
end

Instance Attribute Details

#actionObject (readonly)

Returns the value of attribute action.



7
8
9
# File 'lib/bugsage/code_patch.rb', line 7

def action
  @action
end

#end_lineObject (readonly)

Returns the value of attribute end_line.



7
8
9
# File 'lib/bugsage/code_patch.rb', line 7

def end_line
  @end_line
end

#replacementObject (readonly)

Returns the value of attribute replacement.



7
8
9
# File 'lib/bugsage/code_patch.rb', line 7

def replacement
  @replacement
end

#start_lineObject (readonly)

Returns the value of attribute start_line.



7
8
9
# File 'lib/bugsage/code_patch.rb', line 7

def start_line
  @start_line
end

Class Method Details

.from_ai(payload, error_line:) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
# File 'lib/bugsage/code_patch.rb', line 16

def self.from_ai(payload, error_line:)
  patch = payload["code_patch"]
  return from_legacy(payload["code_fix"], error_line) if patch.nil? || patch.empty?

  new(
    action: patch["action"],
    start_line: patch["start_line"] || error_line,
    end_line: patch["end_line"] || patch["start_line"] || error_line,
    replacement: patch["replacement"]
  )
end

.from_hash(hash) ⇒ Object



42
43
44
45
46
47
48
49
50
51
# File 'lib/bugsage/code_patch.rb', line 42

def self.from_hash(hash)
  return nil if hash.nil? || hash.empty?

  new(
    action: hash[:action] || hash["action"],
    start_line: hash[:start_line] || hash["start_line"],
    end_line: hash[:end_line] || hash["end_line"],
    replacement: hash[:replacement] || hash["replacement"]
  )
end

.from_legacy(code_fix, error_line) ⇒ Object



28
29
30
31
32
33
# File 'lib/bugsage/code_patch.rb', line 28

def self.from_legacy(code_fix, error_line)
  text = code_fix.to_s.strip
  return nil if text.empty?

  new(action: "replace_lines", start_line: error_line, end_line: error_line, replacement: text)
end

.preview_for(patch) ⇒ Object



35
36
37
38
39
40
# File 'lib/bugsage/code_patch.rb', line 35

def self.preview_for(patch)
  return nil if patch.nil?

  instance = patch.is_a?(self) ? patch : from_hash(patch)
  instance&.preview
end

Instance Method Details

#apply!(lines) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/bugsage/code_patch.rb', line 53

def apply!(lines)
  validate_range!(lines)

  case action
  when "no_change"
    nil
  when "delete_lines"
    delete_lines!(lines)
  when "insert_before"
    insert_before!(lines)
  else
    replace_lines!(lines)
  end
end

#duplicates_existing?(lines) ⇒ Boolean

Returns:

  • (Boolean)


89
90
91
92
93
94
95
# File 'lib/bugsage/code_patch.rb', line 89

def duplicates_existing?(lines)
  return false if %w[delete_lines no_change].include?(action)
  return true if replacement.strip.empty?

  normalized = normalize_line(replacement)
  lines.any? { |line| normalize_line(line) == normalized }
end

#previewObject



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/bugsage/code_patch.rb', line 68

def preview
  case action
  when "no_change"
    Bugsage.t("code_patch.no_change")
  when "delete_lines"
    if start_line == end_line
      Bugsage.t("code_patch.delete_line", line: start_line)
    else
      Bugsage.t("code_patch.delete_lines", start_line: start_line, end_line: end_line)
    end
  when "insert_before"
    Bugsage.t("code_patch.insert_before", line: start_line, replacement: replacement)
  else
    if start_line == end_line
      Bugsage.t("code_patch.replace_line", line: start_line, replacement: replacement)
    else
      Bugsage.t("code_patch.replace_lines", start_line: start_line, end_line: end_line, replacement: replacement)
    end
  end
end

#to_hObject



97
98
99
100
101
102
103
104
# File 'lib/bugsage/code_patch.rb', line 97

def to_h
  {
    action: action,
    start_line: start_line,
    end_line: end_line,
    replacement: replacement
  }
end