Commit 26962cde authored by Robert Speicher's avatar Robert Speicher

Merge branch '239386-fix-scroll-window-code-search' into 'master'

Fix the scroll position in code search results

See merge request gitlab-org/gitlab!43083
parents c580b306 296f70a0
---
title: Fix the scroll position in code search results
merge_request: 43083
author:
type: fixed
...@@ -4,6 +4,8 @@ module Elastic ...@@ -4,6 +4,8 @@ module Elastic
module Latest module Latest
module GitClassProxy module GitClassProxy
SHA_REGEX = /\A[0-9a-f]{5,40}\z/i.freeze SHA_REGEX = /\A[0-9a-f]{5,40}\z/i.freeze
HIGHLIGHT_START_TAG = 'gitlabelasticsearch→'
HIGHLIGHT_END_TAG = '←gitlabelasticsearch'
def elastic_search(query, type: 'all', page: 1, per: 20, options: {}) def elastic_search(query, type: 'all', page: 1, per: 20, options: {})
results = { blobs: [], commits: [] } results = { blobs: [], commits: [] }
...@@ -95,8 +97,8 @@ module Elastic ...@@ -95,8 +97,8 @@ module Elastic
end end
query_hash[:highlight] = { query_hash[:highlight] = {
pre_tags: ["gitlabelasticsearch→"], pre_tags: [HIGHLIGHT_START_TAG],
post_tags: ["←gitlabelasticsearch"], post_tags: [HIGHLIGHT_END_TAG],
fields: es_fields fields: es_fields
} }
end end
...@@ -157,9 +159,9 @@ module Elastic ...@@ -157,9 +159,9 @@ module Elastic
if options[:highlight] if options[:highlight]
query_hash[:highlight] = { query_hash[:highlight] = {
pre_tags: ["gitlabelasticsearch→"], pre_tags: [HIGHLIGHT_START_TAG],
post_tags: ["←gitlabelasticsearch"], post_tags: [HIGHLIGHT_END_TAG],
order: "score", number_of_fragments: 0, # highlighted text fragments do not work well for code as we want to show a few whole lines of code. We need to get the whole content to determine the exact line number that was highlighted.
fields: { fields: {
"blob.content" => {}, "blob.content" => {},
"blob.file_name" => {} "blob.file_name" => {}
......
...@@ -123,16 +123,12 @@ module Gitlab ...@@ -123,16 +123,12 @@ module Gitlab
project_id = result['_source']['project_id'].to_i project_id = result['_source']['project_id'].to_i
total_lines = content.lines.size total_lines = content.lines.size
term = highlight_content = result.dig('highlight', 'blob.content')&.first || ''
if result['highlight']
highlighted = result['highlight']['blob.content']
highlighted && highlighted[0].match(/gitlabelasticsearch→(.*?)←gitlabelasticsearch/)[1]
end
found_line_number = 0 found_line_number = 0
content.each_line.each_with_index do |line, index| highlight_content.each_line.each_with_index do |line, index|
if term && line.include?(term) if line.include?(::Elastic::Latest::GitClassProxy::HIGHLIGHT_START_TAG)
found_line_number = index found_line_number = index
break break
end end
......
...@@ -58,11 +58,12 @@ RSpec.describe Gitlab::Elastic::SearchResults, :elastic, :sidekiq_might_not_need ...@@ -58,11 +58,12 @@ RSpec.describe Gitlab::Elastic::SearchResults, :elastic, :sidekiq_might_not_need
describe 'parse_search_result' do describe 'parse_search_result' do
let(:project) { double(:project) } let(:project) { double(:project) }
let(:content) { "foo\nbar\nbaz\n" }
let(:blob) do let(:blob) do
{ {
'blob' => { 'blob' => {
'commit_sha' => 'sha', 'commit_sha' => 'sha',
'content' => "foo\nbar\nbaz\n", 'content' => content,
'path' => 'path/file.ext' 'path' => 'path/file.ext'
} }
} }
...@@ -83,7 +84,7 @@ RSpec.describe Gitlab::Elastic::SearchResults, :elastic, :sidekiq_might_not_need ...@@ -83,7 +84,7 @@ RSpec.describe Gitlab::Elastic::SearchResults, :elastic, :sidekiq_might_not_need
result = { result = {
'_source' => blob, '_source' => blob,
'highlight' => { 'highlight' => {
'blob.content' => ["foo\ngitlabelasticsearch→bar←gitlabelasticsearch\nbaz\n"] 'blob.content' => ["foo\n#{::Elastic::Latest::GitClassProxy::HIGHLIGHT_START_TAG}bar#{::Elastic::Latest::GitClassProxy::HIGHLIGHT_END_TAG}\nbaz\n"]
} }
} }
...@@ -100,6 +101,60 @@ RSpec.describe Gitlab::Elastic::SearchResults, :elastic, :sidekiq_might_not_need ...@@ -100,6 +101,60 @@ RSpec.describe Gitlab::Elastic::SearchResults, :elastic, :sidekiq_might_not_need
data: "bar\n" data: "bar\n"
) )
end end
context 'when the highlighting finds the same terms multiple times' do
let(:content) do
<<~END
bar
bar
foo
bar # this is the highlighted bar
baz
boo
bar
END
end
it 'does not mistake a line that happens to include the same term that was highlighted on a later line' do
highlighted_content = <<~END
bar
bar
foo
#{::Elastic::Latest::GitClassProxy::HIGHLIGHT_START_TAG}bar#{::Elastic::Latest::GitClassProxy::HIGHLIGHT_END_TAG} # this is the highlighted bar
baz
boo
bar
END
result = {
'_source' => blob,
'highlight' => {
'blob.content' => [highlighted_content]
}
}
parsed = described_class.parse_search_result(result, project)
expected_data = <<~END
bar
foo
bar # this is the highlighted bar
baz
boo
END
expect(parsed).to be_kind_of(::Gitlab::Search::FoundBlob)
expect(parsed).to have_attributes(
id: nil,
path: 'path/file.ext',
basename: 'path/file',
ref: 'sha',
startline: 2,
project: project,
data: expected_data
)
end
end
end end
describe 'issues' do describe 'issues' do
...@@ -571,7 +626,7 @@ RSpec.describe Gitlab::Elastic::SearchResults, :elastic, :sidekiq_might_not_need ...@@ -571,7 +626,7 @@ RSpec.describe Gitlab::Elastic::SearchResults, :elastic, :sidekiq_might_not_need
results = described_class.new(user, 'defau*', limit_project_ids) results = described_class.new(user, 'defau*', limit_project_ids)
blobs = results.objects('blobs') blobs = results.objects('blobs')
expect(blobs.first.data).to include('default') expect(blobs.first.data).to match(/default/i)
expect(results.blobs_count).to eq 3 expect(results.blobs_count).to eq 3
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