diff --git a/lua/telescope/builtin/__lsp.lua b/lua/telescope/builtin/__lsp.lua index edb6efbd16..bd416d7fd3 100644 --- a/lua/telescope/builtin/__lsp.lua +++ b/lua/telescope/builtin/__lsp.lua @@ -117,6 +117,85 @@ local function calls(opts, direction) end) end +local function type_hierarchy(opts, method, title, item) + lsp.buf_request(opts.bufnr, method, { item = item }, function(err, result) + if err then + utils.notify("lsp.type_hierarchy", { msg = title .. ": " .. err.message, level = "ERROR" }) + return + end + + if not result or vim.tbl_isempty(result) then + return + end + + local locations = {} + for _, unit in pairs(result) do + local rng = unit.range + table.insert(locations, { + filename = vim.uri_to_fname(unit.uri), + text = unit.name, + lnum = rng.start.line + 1, + col = rng.start.character + 1, + }) + end + + pickers + .new(opts, { + prompt_title = title, + finder = finders.new_table { + results = locations, + entry_maker = opts.entry_maker or make_entry.gen_from_quickfix(opts), + }, + previewer = conf.qflist_previewer(opts), + sorter = conf.generic_sorter(opts), + push_cursor_on_edit = true, + push_tagstack_on_edit = true, + }) + :find() + end) +end + +local function pick_type_hierarchy_item(type_hierarchy_items) + if not type_hierarchy_items or vim.tbl_isempty(type_hierarchy_items) then + return + end + if #type_hierarchy_items == 1 then + return type_hierarchy_items[1] + end + local items = {} + for i, item in pairs(type_hierarchy_items) do + local entry = item.detail or item.name + table.insert(items, string.format("%d. %s", i, entry)) + end + local choice = vim.fn.inputlist(items) + if choice < 1 or choice > #items then + return + end + return type_hierarchy_items[choice] +end + +---@param direction 'super'|'sub' +local function types(opts, direction) + local params = client_position_params() + lsp.buf_request(opts.bufnr, "textDocument/prepareTypeHierarchy", params, function(err, result) + if err then + utils.notify("lsp.types", { msg = err.message, level = "ERROR" }) + return + end + + local type_hierarchy_item = pick_type_hierarchy_item(result) + if not type_hierarchy_item then + return + end + + if direction == "super" then + type_hierarchy(opts, "typeHierarchy/supertypes", "LSP Super Types", type_hierarchy_item) + else + type_hierarchy(opts, "typeHierarchy/subtypes", "LSP Sub Types", type_hierarchy_item) + end + end) +end + M.incoming_calls = function(opts) calls(opts, "from") end @@ -125,6 +204,14 @@ M.outgoing_calls = function(opts) calls(opts, "to") end +M.super_types = function(opts) + types(opts, "super") +end + +M.sub_types = function(opts) + types(opts, "sub") +end + ---@alias telescope.lsp.list_or_jump_action ---| "textDocument/references" ---| "textDocument/definition" diff --git a/lua/telescope/builtin/init.lua b/lua/telescope/builtin/init.lua index 6e27c27ab3..b07091a5a6 100644 --- a/lua/telescope/builtin/init.lua +++ b/lua/telescope/builtin/init.lua @@ -444,6 +444,14 @@ builtin.lsp_incoming_calls = require_on_exported_call("telescope.builtin.__lsp") ---@field file_encoding string: file encoding for the previewer builtin.lsp_outgoing_calls = require_on_exported_call("telescope.builtin.__lsp").outgoing_calls +--- Lists LSP Supertypes for symbol under the cursor, jumps to reference on `` +---@param opts table: options to pass to the picker +builtin.lsp_super_types = require_on_exported_call("telescope.builtin.__lsp").super_types + +--- Lists LSP Subtypes for symbol under the cursor, jumps to reference on `` +---@param opts table: options to pass to the picker +builtin.lsp_sub_types = require_on_exported_call("telescope.builtin.__lsp").sub_types + --- Goto the definition of the word under the cursor, if there's only one, otherwise show all options in Telescope ---@param opts table: options to pass to the picker ---@field jump_type string: how to goto definition if there is only one and the definition file is different from the current file, values: "tab", "tab drop", "split", "vsplit", "never"