Commit 8087143d authored by Igor Drozdov's avatar Igor Drozdov

Code Nav PoC: Extend LSIF API with definition urls

This will allow us to implement Go-To-Definition feature
parent 61fb75f7
......@@ -2,7 +2,8 @@
module Projects
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
......@@ -14,19 +15,18 @@ module Projects
end
def execute
docs, doc_ranges, ranges =
fetch_data.values_at('docs', 'doc_ranges', 'ranges')
doc_id = doc_id_from(docs)
fetch_data!
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,
end_line: line_data.last,
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
......@@ -47,8 +47,17 @@ module Projects
end
end
def doc_id_from(docs)
docs.reduce(nil) do |doc_id, (id, doc_path)|
def fetch_data!
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}$/
if doc_id.nil? || docs[doc_id].size > doc_path.size
......@@ -58,5 +67,24 @@ module Projects
doc_id
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
......@@ -60,7 +60,8 @@ describe API::LsifData do
'end_char' => 18,
'end_line' => 8,
'start_char' => 13,
'start_line' => 8
'start_line' => 8,
'definition_url' => project_blob_path(project, "#{commit.id}/morestrings/reverse.go", anchor: 'L5')
})
end
......
......@@ -23,43 +23,51 @@ describe Projects::LsifDataService do
end
context 'for main.go' do
let(:path_prefix) { "/#{project.full_path}/-/blob/#{commit_id}" }
it 'returns lsif ranges for the file' do
expect(service.execute).to eq([
{
end_char: 9,
end_line: 6,
start_char: 5,
start_line: 6
start_line: 6,
definition_url: "#{path_prefix}/main.go#L7"
},
{
end_char: 36,
end_line: 3,
start_char: 1,
start_line: 3
start_line: 3,
definition_url: "#{path_prefix}/main.go#L4"
},
{
end_char: 12,
end_line: 7,
start_char: 1,
start_line: 7
start_line: 7,
definition_url: "#{path_prefix}/main.go#L4"
},
{
end_char: 20,
end_line: 7,
start_char: 13,
start_line: 7
start_line: 7,
definition_url: "#{path_prefix}/morestrings/reverse.go#L11"
},
{
end_char: 12,
end_line: 8,
start_char: 1,
start_line: 8
start_line: 8,
definition_url: "#{path_prefix}/main.go#L4"
},
{
end_char: 18,
end_line: 8,
start_char: 13,
start_line: 8
start_line: 8,
definition_url: "#{path_prefix}/morestrings/reverse.go#L5"
}
])
end
......@@ -73,7 +81,8 @@ describe Projects::LsifDataService do
end_char: 2,
end_line: 11,
start_char: 1,
start_line: 11
start_line: 11,
definition_url: "/#{project.full_path}/-/blob/#{commit_id}/morestrings/reverse.go#L12"
})
end
end
......@@ -87,7 +96,7 @@ describe Projects::LsifDataService do
end
end
describe '#doc_id_from' do
describe '#doc_id' do
context 'when the passed path matches multiple files' do
let(:path) { 'check/main.go' }
let(:docs) do
......@@ -100,7 +109,9 @@ describe Projects::LsifDataService do
end
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
......
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