Commit 1e32c494 authored by Nick Thomas's avatar Nick Thomas

Merge branch 'id-lsif-fetch-definitions' into 'master'

Code Nav PoC: Extend LSIF API with definition urls

See merge request gitlab-org/gitlab!23684
parents afecae26 8087143d
...@@ -2,7 +2,8 @@ ...@@ -2,7 +2,8 @@
module Projects module Projects
class LsifDataService class LsifDataService
attr_reader :file, :project, :path, :commit_id attr_reader :file, :project, :path, :commit_id,
:docs, :doc_ranges, :ranges, :def_refs
CACHE_EXPIRE_IN = 1.hour CACHE_EXPIRE_IN = 1.hour
...@@ -14,19 +15,18 @@ module Projects ...@@ -14,19 +15,18 @@ module Projects
end end
def execute def execute
docs, doc_ranges, ranges = fetch_data!
fetch_data.values_at('docs', 'doc_ranges', 'ranges')
doc_id = doc_id_from(docs)
doc_ranges[doc_id]&.map do |range_id| doc_ranges[doc_id]&.map do |range_id|
line_data, column_data = ranges[range_id]['loc'] location, ref_id = ranges[range_id].values_at('loc', 'ref_id')
line_data, column_data = location
{ {
start_line: line_data.first, start_line: line_data.first,
end_line: line_data.last, end_line: line_data.last,
start_char: column_data.first, start_char: column_data.first,
end_char: column_data.last end_char: column_data.last,
definition_url: definition_url_for(def_refs[ref_id])
} }
end end
end end
...@@ -47,8 +47,17 @@ module Projects ...@@ -47,8 +47,17 @@ module Projects
end end
end end
def doc_id_from(docs) def fetch_data!
docs.reduce(nil) do |doc_id, (id, doc_path)| data = fetch_data
@docs = data['docs']
@doc_ranges = data['doc_ranges']
@ranges = data['ranges']
@def_refs = data['def_refs']
end
def doc_id
@doc_id ||= docs.reduce(nil) do |doc_id, (id, doc_path)|
next doc_id unless doc_path =~ /#{path}$/ next doc_id unless doc_path =~ /#{path}$/
if doc_id.nil? || docs[doc_id].size > doc_path.size if doc_id.nil? || docs[doc_id].size > doc_path.size
...@@ -58,5 +67,24 @@ module Projects ...@@ -58,5 +67,24 @@ module Projects
doc_id doc_id
end end
end end
def dir_absolute_path
@dir_absolute_path ||= docs[doc_id]&.delete_suffix(path)
end
def definition_url_for(ref_id)
return unless range = ranges[ref_id]
def_doc_id, location = range.values_at('doc_id', 'loc')
localized_doc_url = docs[def_doc_id].delete_prefix(dir_absolute_path)
# location is stored as [[start_line, end_line], [start_char, end_char]]
start_line = location.first.first
line_anchor = "L#{start_line + 1}"
definition_ref_path = [commit_id, localized_doc_url].join('/')
Gitlab::Routing.url_helpers.project_blob_path(project, definition_ref_path, anchor: line_anchor)
end
end end
end end
...@@ -60,7 +60,8 @@ describe API::LsifData do ...@@ -60,7 +60,8 @@ describe API::LsifData do
'end_char' => 18, 'end_char' => 18,
'end_line' => 8, 'end_line' => 8,
'start_char' => 13, 'start_char' => 13,
'start_line' => 8 'start_line' => 8,
'definition_url' => project_blob_path(project, "#{commit.id}/morestrings/reverse.go", anchor: 'L5')
}) })
end end
......
...@@ -23,43 +23,51 @@ describe Projects::LsifDataService do ...@@ -23,43 +23,51 @@ describe Projects::LsifDataService do
end end
context 'for main.go' do context 'for main.go' do
let(:path_prefix) { "/#{project.full_path}/-/blob/#{commit_id}" }
it 'returns lsif ranges for the file' do it 'returns lsif ranges for the file' do
expect(service.execute).to eq([ expect(service.execute).to eq([
{ {
end_char: 9, end_char: 9,
end_line: 6, end_line: 6,
start_char: 5, start_char: 5,
start_line: 6 start_line: 6,
definition_url: "#{path_prefix}/main.go#L7"
}, },
{ {
end_char: 36, end_char: 36,
end_line: 3, end_line: 3,
start_char: 1, start_char: 1,
start_line: 3 start_line: 3,
definition_url: "#{path_prefix}/main.go#L4"
}, },
{ {
end_char: 12, end_char: 12,
end_line: 7, end_line: 7,
start_char: 1, start_char: 1,
start_line: 7 start_line: 7,
definition_url: "#{path_prefix}/main.go#L4"
}, },
{ {
end_char: 20, end_char: 20,
end_line: 7, end_line: 7,
start_char: 13, start_char: 13,
start_line: 7 start_line: 7,
definition_url: "#{path_prefix}/morestrings/reverse.go#L11"
}, },
{ {
end_char: 12, end_char: 12,
end_line: 8, end_line: 8,
start_char: 1, start_char: 1,
start_line: 8 start_line: 8,
definition_url: "#{path_prefix}/main.go#L4"
}, },
{ {
end_char: 18, end_char: 18,
end_line: 8, end_line: 8,
start_char: 13, start_char: 13,
start_line: 8 start_line: 8,
definition_url: "#{path_prefix}/morestrings/reverse.go#L5"
} }
]) ])
end end
...@@ -73,7 +81,8 @@ describe Projects::LsifDataService do ...@@ -73,7 +81,8 @@ describe Projects::LsifDataService do
end_char: 2, end_char: 2,
end_line: 11, end_line: 11,
start_char: 1, start_char: 1,
start_line: 11 start_line: 11,
definition_url: "/#{project.full_path}/-/blob/#{commit_id}/morestrings/reverse.go#L12"
}) })
end end
end end
...@@ -87,7 +96,7 @@ describe Projects::LsifDataService do ...@@ -87,7 +96,7 @@ describe Projects::LsifDataService do
end end
end end
describe '#doc_id_from' do describe '#doc_id' do
context 'when the passed path matches multiple files' do context 'when the passed path matches multiple files' do
let(:path) { 'check/main.go' } let(:path) { 'check/main.go' }
let(:docs) do let(:docs) do
...@@ -100,7 +109,9 @@ describe Projects::LsifDataService do ...@@ -100,7 +109,9 @@ describe Projects::LsifDataService do
end end
it 'fetches the document with the shortest absolute path' do it 'fetches the document with the shortest absolute path' do
expect(service.__send__(:doc_id_from, docs)).to eq(3) service.instance_variable_set(:@docs, docs)
expect(service.__send__(:doc_id)).to eq(3)
end end
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