107 lines
2.3 KiB
Ruby
107 lines
2.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Gitlab
|
|
module Suggestions
|
|
class FileSuggestion
|
|
include Gitlab::Utils::StrongMemoize
|
|
|
|
SuggestionForDifferentFileError = Class.new(StandardError)
|
|
|
|
def initialize
|
|
@suggestions = []
|
|
end
|
|
|
|
def add_suggestion(new_suggestion)
|
|
if for_different_file?(new_suggestion)
|
|
raise SuggestionForDifferentFileError,
|
|
'Only add suggestions for the same file.'
|
|
end
|
|
|
|
suggestions << new_suggestion
|
|
end
|
|
|
|
def line_conflict?
|
|
strong_memoize(:line_conflict) do
|
|
_line_conflict?
|
|
end
|
|
end
|
|
|
|
def new_content
|
|
@new_content ||= _new_content
|
|
end
|
|
|
|
def file_path
|
|
@file_path ||= _file_path
|
|
end
|
|
|
|
private
|
|
|
|
attr_accessor :suggestions
|
|
|
|
def blob
|
|
first_suggestion&.diff_file&.new_blob
|
|
end
|
|
|
|
def blob_data_lines
|
|
blob.load_all_data!
|
|
blob.data.lines
|
|
end
|
|
|
|
def current_content
|
|
@current_content ||= blob.nil? ? [''] : blob_data_lines
|
|
end
|
|
|
|
def _new_content
|
|
current_content.tap do |content|
|
|
suggestions.each do |suggestion|
|
|
range = line_range(suggestion)
|
|
content[range] = suggestion.to_content
|
|
end
|
|
end.join
|
|
end
|
|
|
|
def line_range(suggestion)
|
|
suggestion.from_line_index..suggestion.to_line_index
|
|
end
|
|
|
|
def for_different_file?(suggestion)
|
|
file_path && file_path != suggestion_file_path(suggestion)
|
|
end
|
|
|
|
def suggestion_file_path(suggestion)
|
|
suggestion&.diff_file&.file_path
|
|
end
|
|
|
|
def first_suggestion
|
|
suggestions.first
|
|
end
|
|
|
|
def _file_path
|
|
suggestion_file_path(first_suggestion)
|
|
end
|
|
|
|
def _line_conflict?
|
|
has_conflict = false
|
|
|
|
suggestions.each_with_object([]) do |suggestion, ranges|
|
|
range_in_test = line_range(suggestion)
|
|
|
|
if has_range_conflict?(range_in_test, ranges)
|
|
has_conflict = true
|
|
break
|
|
end
|
|
|
|
ranges << range_in_test
|
|
end
|
|
|
|
has_conflict
|
|
end
|
|
|
|
def has_range_conflict?(range_in_test, ranges)
|
|
ranges.any? do |range|
|
|
range.overlaps?(range_in_test)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|