Skip to content

Commit

Permalink
java_type_hierarchy: class, method type hierarchy on the quickfix list
Browse files Browse the repository at this point in the history
java_type_hierarchy uses java.navigate.openTypeHierarchy and
java.navigate.resolveTypeHierarchy to show type hierarchy information of
a class or method on the quickfix list.
  • Loading branch information
lbrayner committed Jul 2, 2023
1 parent 0261cf5 commit 34ec0a4
Showing 1 changed file with 113 additions and 0 deletions.
113 changes: 113 additions & 0 deletions lua/jdtls.lua
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,119 @@ function M.organize_imports()
end


-- Type hierarchy
local maximum_resolve_depth = 10

function M.java_type_hierarchy(reuse_win, on_list)
local function resolve_command(result)
return {
command = 'java.navigate.resolveTypeHierarchy',
arguments = {
vim.fn.json_encode(result), -- toResolve: TypeHierarchyItem
'1', -- direction: Children(0), Parents(1), Both(2)
'1', -- resolveDepth
},
}
end

local hierarchy = {}
local depth = 0
local open_type_hierarchy

local function resolve_handler(err, result)
assert(not err, vim.inspect(err))
depth = depth + 1

local parents = vim.tbl_filter(function(parent)
-- Filtering out SymbolKind.Null items
return parent.kind ~= vim.lsp.protocol.SymbolKind.Null
end, result.parents)

if #parents > 0 and depth > maximum_resolve_depth then
vim.notify(string.format('Type hierarchy: maximum resolve depth is %d.', maximum_resolve_depth),
vim.log.levels.WARN)
elseif #parents > 0 then
local parent_classes = vim.tbl_filter(function(parent)
return parent.kind == vim.lsp.protocol.SymbolKind.Class
end, parents)

assert(#parent_classes <= 1, 'Type hierarchy: more than one parent class')

local parent = parent_classes[1]
if not parent then
assert(#parents == 1, string.format('Type hierarchy: could not determine parent with result %s',
vim.inspect(result)))
-- Symbol at point is a SymbolKind.Method, parent is a SymbolKind.Interface
parent = parents[1]
end

for _, parent in ipairs(parents) do
table.insert(hierarchy, parent)
end
return execute_command(resolve_command(parent), resolve_handler)
end

if #hierarchy > 0 then
local root = hierarchy[#hierarchy]
if root.detail..'.'..root.name == 'java.lang.Object' then
table.remove(hierarchy) -- Pop the top
end
end

if #hierarchy == 0 then return print('Type hierarchy: no results.') end

local locations = vim.tbl_map(function(parent)
return { uri = parent.uri, range = parent.selectionRange }
end, hierarchy)

local title = string.format('Type hierarchy: %s.%s', open_type_hierarchy.detail, open_type_hierarchy.name)
if vim.tbl_get(open_type_hierarchy, 'data', 'method_name') then
title = string.format('%s.%s', title, open_type_hierarchy.data.method_name)
end

hierarchy = nil
depth = nil
open_type_hierarchy = nil

local items = {}
for _, location in ipairs(locations) do -- Preserving table order
table.insert(items, vim.lsp.util.locations_to_items({ location }, offset_encoding)[1])
end

if on_list then
assert(type(on_list) == 'function', 'on_list is not a function')
return on_list({ title = title, items = items })
end

if #locations == 1 then
return vim.lsp.util.jump_to_location(locations[1], offset_encoding, reuse_win)
end

vim.fn.setqflist({}, ' ', { title = title, items = items })
vim.api.nvim_command('botright copen')
end

local position = vim.lsp.util.make_position_params(0, offset_encoding)
local command = {
command = 'java.navigate.openTypeHierarchy',
arguments = {
vim.fn.json_encode(position), -- textParams: TextDocumentPositionParams
'1', -- direction: Children(0), Parents(1), Both(2)
'0', -- resolveDepth
},
}
execute_command(command, function(err, result)
assert(not err, vim.inspect(err))
if not result then
return vim.notify('Type hierarchy: openTypeHierarchy returned no results',
vim.log.levels.ERROR)
end
open_type_hierarchy = result
execute_command(resolve_command(result), resolve_handler)
end)
end


---@private
function M._complete_compile()
return 'full\nincremental'
Expand Down

0 comments on commit 34ec0a4

Please sign in to comment.