Commit 4d460c88 authored by Nick Thomas's avatar Nick Thomas

Merge branch '222780-batched-suggestions-get-applied-in-wrong-location' into 'master'

Fix incorrect Batched suggestions applications

See merge request gitlab-org/gitlab!34828
parents d0981554 98f96742
...@@ -7,17 +7,14 @@ module Gitlab ...@@ -7,17 +7,14 @@ module Gitlab
SuggestionForDifferentFileError = Class.new(StandardError) SuggestionForDifferentFileError = Class.new(StandardError)
def initialize attr_reader :file_path
@suggestions = [] attr_reader :blob
end attr_reader :suggestions
def add_suggestion(new_suggestion)
if for_different_file?(new_suggestion)
raise SuggestionForDifferentFileError,
'Only add suggestions for the same file.'
end
suggestions << new_suggestion def initialize(file_path, suggestions)
@file_path = file_path
@suggestions = suggestions.sort_by(&:from_line_index)
@blob = suggestions.first&.diff_file&.new_blob
end end
def line_conflict? def line_conflict?
...@@ -30,18 +27,8 @@ module Gitlab ...@@ -30,18 +27,8 @@ module Gitlab
@new_content ||= _new_content @new_content ||= _new_content
end end
def file_path
@file_path ||= _file_path
end
private private
attr_accessor :suggestions
def blob
first_suggestion&.diff_file&.new_blob
end
def blob_data_lines def blob_data_lines
blob.load_all_data! blob.load_all_data!
blob.data.lines blob.data.lines
...@@ -53,31 +40,19 @@ module Gitlab ...@@ -53,31 +40,19 @@ module Gitlab
def _new_content def _new_content
current_content.tap do |content| current_content.tap do |content|
# NOTE: We need to cater for line number changes when the range is more than one line.
offset = 0
suggestions.each do |suggestion| suggestions.each do |suggestion|
range = line_range(suggestion) range = line_range(suggestion, offset)
content[range] = suggestion.to_content content[range] = suggestion.to_content
offset += range.count - 1
end end
end.join end.join
end end
def line_range(suggestion) def line_range(suggestion, offset = 0)
suggestion.from_line_index..suggestion.to_line_index (suggestion.from_line_index - offset)..(suggestion.to_line_index - offset)
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 end
def _line_conflict? def _line_conflict?
......
...@@ -26,10 +26,10 @@ module Gitlab ...@@ -26,10 +26,10 @@ module Gitlab
end end
def actions def actions
@actions ||= suggestions_per_file.map do |file_path, file_suggestion| @actions ||= suggestions_per_file.map do |file_suggestion|
{ {
action: 'update', action: 'update',
file_path: file_path, file_path: file_suggestion.file_path,
content: file_suggestion.new_content content: file_suggestion.new_content
} }
end end
...@@ -50,19 +50,9 @@ module Gitlab ...@@ -50,19 +50,9 @@ module Gitlab
end end
def _suggestions_per_file def _suggestions_per_file
suggestions.each_with_object({}) do |suggestion, result| suggestions
file_path = suggestion.diff_file.file_path .group_by { |suggestion| suggestion.diff_file.file_path }
file_suggestion = result[file_path] ||= FileSuggestion.new .map { |file_path, group| FileSuggestion.new(file_path, group) }
file_suggestion.add_suggestion(suggestion)
end
end
def file_suggestions
suggestions_per_file.values
end
def first_file_suggestion
file_suggestions.first
end end
def _error_message def _error_message
...@@ -72,7 +62,7 @@ module Gitlab ...@@ -72,7 +62,7 @@ module Gitlab
return message if message return message if message
end end
has_line_conflict = file_suggestions.any? do |file_suggestion| has_line_conflict = suggestions_per_file.any? do |file_suggestion|
file_suggestion.line_conflict? file_suggestion.line_conflict?
end end
......
...@@ -87,11 +87,10 @@ describe Gitlab::Suggestions::SuggestionSet do ...@@ -87,11 +87,10 @@ describe Gitlab::Suggestions::SuggestionSet do
it 'returns an array of hashes with proper key/value pairs' do it 'returns an array of hashes with proper key/value pairs' do
first_action = suggestion_set.actions.first first_action = suggestion_set.actions.first
file_path, file_suggestion = suggestion_set file_suggestion = suggestion_set.send(:suggestions_per_file).first
.send(:suggestions_per_file).first
expect(first_action[:action]).to be('update') expect(first_action[:action]).to be('update')
expect(first_action[:file_path]).to eq(file_path) expect(first_action[:file_path]).to eq(file_suggestion.file_path)
expect(first_action[:content]).to eq(file_suggestion.new_content) expect(first_action[:content]).to eq(file_suggestion.new_content)
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment