|
|
@ -1,12 +1,12 @@
|
|
|
|
local api = vim.api
|
|
|
|
local api = vim.api
|
|
|
|
|
|
|
|
|
|
|
|
local HAS09 = vim.fn.has("nvim-0.9") == 1
|
|
|
|
local HAS09 = vim.fn.has('nvim-0.9') == 1
|
|
|
|
local get_node_text = vim.treesitter.get_node_text
|
|
|
|
local get_node_text = vim.treesitter.get_node_text
|
|
|
|
if not HAS09 then
|
|
|
|
if not HAS09 then
|
|
|
|
local get_node_text = vim.treesitter.query.get_node_text
|
|
|
|
local get_node_text = vim.treesitter.query.get_node_text
|
|
|
|
end
|
|
|
|
end
|
|
|
|
local ts_utils = require("nvim-treesitter.ts_utils")
|
|
|
|
local ts_utils = require('nvim-treesitter.ts_utils')
|
|
|
|
local util = require("go.utils")
|
|
|
|
local util = require('go.utils')
|
|
|
|
local log = util.log
|
|
|
|
local log = util.log
|
|
|
|
local trace = util.trace
|
|
|
|
local trace = util.trace
|
|
|
|
-- local trace = util.log
|
|
|
|
-- local trace = util.log
|
|
|
@ -30,7 +30,7 @@ M.intersects = function(row, col, sRow, sCol, eRow, eCol)
|
|
|
|
return true
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
local locals = require("nvim-treesitter.locals")
|
|
|
|
local locals = require('nvim-treesitter.locals')
|
|
|
|
-- from navigator/treesitter.lua
|
|
|
|
-- from navigator/treesitter.lua
|
|
|
|
-- modified from nvim-treesitter/treesitter-refactor plugin
|
|
|
|
-- modified from nvim-treesitter/treesitter-refactor plugin
|
|
|
|
-- Get definitions of bufnr (unique and sorted by order of appearance).
|
|
|
|
-- Get definitions of bufnr (unique and sorted by order of appearance).
|
|
|
@ -40,35 +40,41 @@ local function get_definitions(bufnr)
|
|
|
|
-- Make sure the nodes are unique.
|
|
|
|
-- Make sure the nodes are unique.
|
|
|
|
local nodes_set = {}
|
|
|
|
local nodes_set = {}
|
|
|
|
for _, loc in ipairs(local_nodes) do
|
|
|
|
for _, loc in ipairs(local_nodes) do
|
|
|
|
loc = loc["local"]
|
|
|
|
loc = loc['local'] or loc -- TODO: remove when 0.9.6
|
|
|
|
if loc.definition then
|
|
|
|
if loc.definition then
|
|
|
|
locals.recurse_local_nodes(loc.definition, function(_, node, _, match)
|
|
|
|
locals.recurse_local_nodes(loc.definition, function(_, node, _, match)
|
|
|
|
-- lua doesn't compare tables by value,
|
|
|
|
-- lua doesn't compare tables by value,
|
|
|
|
-- use the value from byte count instead.
|
|
|
|
-- use the value from byte count instead.
|
|
|
|
local _, _, start = node:start()
|
|
|
|
local _, _, start = node:start()
|
|
|
|
-- variadic_parameter_declaration
|
|
|
|
-- variadic_parameter_declaration
|
|
|
|
if node and node:parent() and string.find(node:parent():type(), "parameter_declaration") then
|
|
|
|
if
|
|
|
|
log("parameter_declaration skip")
|
|
|
|
node
|
|
|
|
|
|
|
|
and node:parent()
|
|
|
|
|
|
|
|
and string.find(node:parent():type(), 'parameter_declaration')
|
|
|
|
|
|
|
|
then
|
|
|
|
|
|
|
|
log('parameter_declaration skip')
|
|
|
|
return
|
|
|
|
return
|
|
|
|
end
|
|
|
|
end
|
|
|
|
nodes_set[start] = { node = node, type = match or "" }
|
|
|
|
nodes_set[start] = { node = node, type = match or '' }
|
|
|
|
end)
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if loc.method then -- for go
|
|
|
|
if loc.method then -- for go
|
|
|
|
locals.recurse_local_nodes(loc.method, function(_, node, full_match, match)
|
|
|
|
locals.recurse_local_nodes(loc.method, function(_, node, full_match, match)
|
|
|
|
local k, l, start = node:start()
|
|
|
|
local k, l, start = node:start()
|
|
|
|
trace(node, k, l, full_match, match) -- match: parameter_list
|
|
|
|
trace(node, k, l, full_match, match) -- match: parameter_list
|
|
|
|
if node:type() == "field_identifier" and nodes_set[start] == nil then
|
|
|
|
if node:type() == 'field_identifier' and nodes_set[start] == nil then
|
|
|
|
nodes_set[start] = { node = node, type = "method" }
|
|
|
|
nodes_set[start] = { node = node, type = 'method' }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if loc.interface then -- for go using interface can output full method definition
|
|
|
|
if loc.interface then -- for go using interface can output full method definition
|
|
|
|
locals.recurse_local_nodes(loc.interface, function(def, node, full_match, match)
|
|
|
|
locals.recurse_local_nodes(loc.interface, function(def, node, full_match, match)
|
|
|
|
local k, l, start = node:start()
|
|
|
|
local k, l, start = node:start()
|
|
|
|
trace(k, l, start, def, node, full_match, match, node:parent(), node:parent():start(), node:parent():type())
|
|
|
|
-- stylua: ignore start
|
|
|
|
|
|
|
|
trace( k, l, start, def, node, full_match, match, node:parent(), node:parent():start(), node:parent():type())
|
|
|
|
|
|
|
|
-- stylua: ignore end
|
|
|
|
if nodes_set[start] == nil then
|
|
|
|
if nodes_set[start] == nil then
|
|
|
|
nodes_set[start] = { node = node, type = match or "" }
|
|
|
|
nodes_set[start] = { node = node, type = match or '' }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
end
|
|
|
@ -76,7 +82,9 @@ local function get_definitions(bufnr)
|
|
|
|
locals.recurse_local_nodes(loc.reference, function(def, node, full_match, match)
|
|
|
|
locals.recurse_local_nodes(loc.reference, function(def, node, full_match, match)
|
|
|
|
local k, l, start = node:start()
|
|
|
|
local k, l, start = node:start()
|
|
|
|
|
|
|
|
|
|
|
|
trace(k, l, start, def, node, full_match, match, node:parent(), node:parent():start(), node:parent():type())
|
|
|
|
-- stylua: ignore start
|
|
|
|
|
|
|
|
trace( k, l, start, def, node, full_match, match, node:parent(), node:parent():start(), node:parent():type())
|
|
|
|
|
|
|
|
-- stylua: ignore end
|
|
|
|
if nodes_set[start] == nil then
|
|
|
|
if nodes_set[start] == nil then
|
|
|
|
-- if node:parent() and node:parent():type() == "field_declaration" then
|
|
|
|
-- if node:parent() and node:parent():type() == "field_declaration" then
|
|
|
|
-- nodes_set[start] = { node = node, type = match or "field" }
|
|
|
|
-- nodes_set[start] = { node = node, type = match or "field" }
|
|
|
@ -85,11 +93,11 @@ local function get_definitions(bufnr)
|
|
|
|
if
|
|
|
|
if
|
|
|
|
node:parent()
|
|
|
|
node:parent()
|
|
|
|
and node:parent():parent()
|
|
|
|
and node:parent():parent()
|
|
|
|
and node:type() == "type_identifier"
|
|
|
|
and node:type() == 'type_identifier'
|
|
|
|
and node:parent():type() == "qualified_type"
|
|
|
|
and node:parent():type() == 'qualified_type'
|
|
|
|
and string.find(node:parent():parent():type(), "interface")
|
|
|
|
and string.find(node:parent():parent():type(), 'interface')
|
|
|
|
then
|
|
|
|
then
|
|
|
|
nodes_set[start] = { node = node, type = "interface" }
|
|
|
|
nodes_set[start] = { node = node, type = 'interface' }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end)
|
|
|
@ -110,11 +118,11 @@ end
|
|
|
|
-- a hack to treesitter-refactor plugin to return list node for outline
|
|
|
|
-- a hack to treesitter-refactor plugin to return list node for outline
|
|
|
|
function M.list_definitions_toc(bufnr)
|
|
|
|
function M.list_definitions_toc(bufnr)
|
|
|
|
bufnr = bufnr or api.nvim_win_get_buf(api.nvim_get_current_win())
|
|
|
|
bufnr = bufnr or api.nvim_win_get_buf(api.nvim_get_current_win())
|
|
|
|
vim.api.nvim_buf_set_option(bufnr, "filetype", "go")
|
|
|
|
vim.api.nvim_buf_set_option(bufnr, 'filetype', 'go')
|
|
|
|
vim.api.nvim_buf_set_option(bufnr, "syntax", "enable")
|
|
|
|
vim.api.nvim_buf_set_option(bufnr, 'syntax', 'enable')
|
|
|
|
log('get_definitions', bufnr)
|
|
|
|
log('get_definitions', bufnr)
|
|
|
|
local definitions = get_definitions(bufnr)
|
|
|
|
local definitions = get_definitions(bufnr)
|
|
|
|
log("definitions: ", definitions)
|
|
|
|
log('definitions: ', definitions)
|
|
|
|
|
|
|
|
|
|
|
|
if #definitions < 1 then
|
|
|
|
if #definitions < 1 then
|
|
|
|
log('unable to find definitions')
|
|
|
|
log('unable to find definitions')
|
|
|
@ -126,9 +134,9 @@ function M.list_definitions_toc(bufnr)
|
|
|
|
-- Force some types to act like they are parents
|
|
|
|
-- Force some types to act like they are parents
|
|
|
|
-- instead of neighbors of the next nodes.
|
|
|
|
-- instead of neighbors of the next nodes.
|
|
|
|
local containers = {
|
|
|
|
local containers = {
|
|
|
|
["function"] = true,
|
|
|
|
['function'] = true,
|
|
|
|
["type"] = true,
|
|
|
|
['type'] = true,
|
|
|
|
["method"] = true,
|
|
|
|
['method'] = true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
local parents = {}
|
|
|
|
local parents = {}
|
|
|
@ -155,13 +163,13 @@ function M.list_definitions_toc(bufnr)
|
|
|
|
local lnum, col, _ = def.node:start()
|
|
|
|
local lnum, col, _ = def.node:start()
|
|
|
|
local type = def.type
|
|
|
|
local type = def.type
|
|
|
|
-- local kind = string.upper(def.type:sub(1, 1))
|
|
|
|
-- local kind = string.upper(def.type:sub(1, 1))
|
|
|
|
local symbol = get_node_text(def.node, bufnr) or ""
|
|
|
|
local symbol = get_node_text(def.node, bufnr) or ''
|
|
|
|
local text = symbol
|
|
|
|
local text = symbol
|
|
|
|
|
|
|
|
|
|
|
|
local line_before = api.nvim_buf_get_lines(bufnr, lnum - 1, lnum, false)[1]
|
|
|
|
local line_before = api.nvim_buf_get_lines(bufnr, lnum - 1, lnum, false)[1]
|
|
|
|
|
|
|
|
|
|
|
|
local hint = {}
|
|
|
|
local hint = {}
|
|
|
|
if line_before and not line_before:find("^%s*//") then
|
|
|
|
if line_before and not line_before:find('^%s*//') then
|
|
|
|
hint = { line_before }
|
|
|
|
hint = { line_before }
|
|
|
|
end
|
|
|
|
end
|
|
|
|
-- go pkg hack
|
|
|
|
-- go pkg hack
|
|
|
@ -170,32 +178,32 @@ function M.list_definitions_toc(bufnr)
|
|
|
|
-- lets do a match if it is method
|
|
|
|
-- lets do a match if it is method
|
|
|
|
|
|
|
|
|
|
|
|
-- Note: the gopls can not find MethodName with MethodName, the format must be ReceviverType.MethodName
|
|
|
|
-- Note: the gopls can not find MethodName with MethodName, the format must be ReceviverType.MethodName
|
|
|
|
if type == "method" then
|
|
|
|
if type == 'method' then
|
|
|
|
local method_def = vim.fn.matchlist(line_text, regx)
|
|
|
|
local method_def = vim.fn.matchlist(line_text, regx)
|
|
|
|
if method_def == nil or method_def[3] == nil then
|
|
|
|
if method_def == nil or method_def[3] == nil then
|
|
|
|
log("incorrect format", line_text, method_def)
|
|
|
|
log('incorrect format', line_text, method_def)
|
|
|
|
else
|
|
|
|
else
|
|
|
|
if method_def[4] ~= symbol then -- field 4 is Method name
|
|
|
|
if method_def[4] ~= symbol then -- field 4 is Method name
|
|
|
|
log("please check regex", method_def, method_def[4], symbol)
|
|
|
|
log('please check regex', method_def, method_def[4], symbol)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if method_def[3] then -- field 3 is ReceiverType
|
|
|
|
if method_def[3] then -- field 3 is ReceiverType
|
|
|
|
symbol = method_def[3] .. "." .. symbol
|
|
|
|
symbol = method_def[3] .. '.' .. symbol
|
|
|
|
log(symbol)
|
|
|
|
log(symbol)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if type == "var" and definitions[idx + 1] and definitions[idx + 1].type == "method" then
|
|
|
|
if type == 'var' and definitions[idx + 1] and definitions[idx + 1].type == 'method' then
|
|
|
|
-- we should remove receiver
|
|
|
|
-- we should remove receiver
|
|
|
|
local method_def = vim.fn.matchlist(line_text, regx)
|
|
|
|
local method_def = vim.fn.matchlist(line_text, regx)
|
|
|
|
if method_def ~= nil and util.trim(method_def[2]) == util.trim(symbol) then
|
|
|
|
if method_def ~= nil and util.trim(method_def[2]) == util.trim(symbol) then
|
|
|
|
log("we ignore var", symbol)
|
|
|
|
log('we ignore var', symbol)
|
|
|
|
goto continue
|
|
|
|
goto continue
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
table.insert(hint, line_text)
|
|
|
|
table.insert(hint, line_text)
|
|
|
|
for i = 1, 5 do
|
|
|
|
for i = 1, 5 do
|
|
|
|
local line_after = api.nvim_buf_get_lines(bufnr, lnum + i, lnum + i + 1, false)[1]
|
|
|
|
local line_after = api.nvim_buf_get_lines(bufnr, lnum + i, lnum + i + 1, false)[1]
|
|
|
|
if line_after and line_after:find("^%s*//") then
|
|
|
|
if line_after and line_after:find('^%s*//') then
|
|
|
|
table.insert(hint, line_after)
|
|
|
|
table.insert(hint, line_after)
|
|
|
|
else
|
|
|
|
else
|
|
|
|
break
|
|
|
|
break
|
|
|
|