summaryrefslogtreecommitdiff
path: root/app/services/suggestions/create_service.rb
blob: c7ac2452c53074fc6362d9d1d275f197d8f9744c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# frozen_string_literal: true

module Suggestions
  class CreateService
    def initialize(note)
      @note = note
    end

    def execute
      return unless @note.supports_suggestion?

      diff_file = @note.latest_diff_file

      return unless diff_file

      suggestions = Banzai::SuggestionsParser.parse(@note.note)

      # For single line suggestion we're only looking forward to
      # change the line receiving the comment. Though, in
      # https://gitlab.com/gitlab-org/gitlab-ce/issues/53310
      # we'll introduce a ```suggestion:L<x>-<y>, so this will
      # slightly change.
      comment_line = @note.position.new_line

      rows =
        suggestions.map.with_index do |suggestion, index|
          from_content = changing_lines(diff_file, comment_line, comment_line)

          # The parsed suggestion doesn't have information about the correct
          # ending characters (we may have a line break, or not), so we take
          # this information from the last line being changed (last
          # characters).
          endline_chars = line_break_chars(from_content.lines.last)
          to_content = "#{suggestion}#{endline_chars}"

          {
            note_id: @note.id,
            from_content: from_content,
            to_content: to_content,
            relative_order: index
          }
        end

      rows.in_groups_of(100, false) do |rows|
        Gitlab::Database.bulk_insert('suggestions', rows)
      end
    end

    private

    def changing_lines(diff_file, from_line, to_line)
      diff_file.new_blob_lines_between(from_line, to_line).join
    end

    def line_break_chars(line)
      match = /\r\n|\r|\n/.match(line)
      match[0] if match
    end
  end
end