use native get_node_text

serverCapcities
ray-x 2 years ago
parent 15e6b315b7
commit cd53b02f93

@ -1,28 +1,28 @@
--- Note: some of the functions/code coped from treesitter/refactor/navigation.lua and may be modified --- Note: some of the functions/code coped from treesitter/refactor/navigation.lua and may be modified
-- to fit in navigator.lua -- to fit in navigator.lua
local gui = require "navigator.gui" local gui = require('navigator.gui')
local fn = vim.fn local fn = vim.fn
local lru = require('navigator.lru').new(500, 1024 * 1024) local lru = require('navigator.lru').new(500, 1024 * 1024)
local ok, ts_locals = pcall(require, "nvim-treesitter.locals") local ok, ts_locals = pcall(require, 'nvim-treesitter.locals')
if not ok then if not ok then
error("treesitter not installed") error('treesitter not installed')
return nil return nil
end end
local parsers = require "nvim-treesitter.parsers" local parsers = require('nvim-treesitter.parsers')
local utils = require "nvim-treesitter.utils" local utils = require('nvim-treesitter.utils')
local locals = require 'nvim-treesitter.locals' local locals = require('nvim-treesitter.locals')
local ts_utils = require 'nvim-treesitter.ts_utils' local ts_utils = require('nvim-treesitter.ts_utils')
local api = vim.api local api = vim.api
local util = require "navigator.util" local util = require('navigator.util')
local M = {} local M = {}
local cwd = vim.loop.cwd() local cwd = vim.loop.cwd()
local log = require"navigator.util".log local log = require('navigator.util').log
local lerr = require"navigator.util".error local lerr = require('navigator.util').error
local trace = require"navigator.util".trace local trace = require('navigator.util').trace
local get_icon = function(kind) local get_icon = function(kind)
if kind == nil or _NgConfigValues.icons.match_kinds[kind] == nil then if kind == nil or _NgConfigValues.icons.match_kinds[kind] == nil then
@ -43,7 +43,7 @@ function M.goto_definition(bufnr)
local definition = locals.find_definition(node_at_point, bufnr) local definition = locals.find_definition(node_at_point, bufnr)
if definition ~= node_at_point then if definition ~= node_at_point then
log("def found:", definition:range()) log('def found:', definition:range())
ts_utils.goto_node(definition) ts_utils.goto_node(definition)
end end
end end
@ -53,7 +53,7 @@ local function node_is_definination(node)
return false return false
end end
local nd_type = node:parent():type() local nd_type = node:parent():type()
local decl = {'short_var_declaration', 'short_var_declaration', 'declaration'} local decl = { 'short_var_declaration', 'short_var_declaration', 'declaration' }
if vim.tbl_contains(decl, nd_type) then if vim.tbl_contains(decl, nd_type) then
return true return true
@ -69,25 +69,24 @@ local function node_is_definination(node)
end end
return false return false
end end
-- use lsp range to find def -- use lsp range to find def
function M.find_definition(range, bufnr) function M.find_definition(range, bufnr)
if not range or not range.start then if not range or not range.start then
lerr("find_def incorrect range", range) lerr('find_def incorrect range', range)
return return
end end
bufnr = bufnr or api.nvim_get_current_buf() bufnr = bufnr or api.nvim_get_current_buf()
local parser = parsers.get_parser(bufnr) local parser = parsers.get_parser(bufnr)
local symbolpos = {range.start.line, range.start.character} -- +1 or not? local symbolpos = { range.start.line, range.start.character } -- +1 or not?
local root = ts_utils.get_root_for_position(range.start.line, range.start.character, parser) local root = ts_utils.get_root_for_position(range.start.line, range.start.character, parser)
if not root then if not root then
return return
end end
local node_at_point = root:named_descendant_for_range(symbolpos[1], symbolpos[2], symbolpos[1], symbolpos[2]) local node_at_point = root:named_descendant_for_range(symbolpos[1], symbolpos[2], symbolpos[1], symbolpos[2])
if not node_at_point then if not node_at_point then
lerr("no node at cursor") lerr('no node at cursor')
return return
end end
@ -95,15 +94,15 @@ function M.find_definition(range, bufnr)
if definition ~= node_at_point then -- NOTE: it may not worksfor some of languages. if def not found, ts if definition ~= node_at_point then -- NOTE: it may not worksfor some of languages. if def not found, ts
-- returns current node. if your node is def, then it also return self... then I have no idea weather it is -- returns current node. if your node is def, then it also return self... then I have no idea weather it is
-- def or not -- def or not
trace("info: def found:", definition:range(), definition:type()) trace('info: def found:', definition:range(), definition:type())
local r, c = definition:range() local r, c = definition:range()
return {start = {line = r, character = c}} return { start = { line = r, character = c } }
elseif node_is_definination(node_at_point) then elseif node_is_definination(node_at_point) then
trace("declaraction here ", definition:type()) trace('declaraction here ', definition:type())
local r, c = definition:range() local r, c = definition:range()
return {start = {line = r, character = c}} return { start = { line = r, character = c } }
else else
trace("error: def not found in ", bufnr, definition:range(), definition:type(), definition:parent():type()) trace('error: def not found in ', bufnr, definition:range(), definition:type(), definition:parent():type())
end end
end end
@ -120,7 +119,7 @@ local function get_definitions(bufnr)
-- 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()
nodes_set[start] = {node = node, type = match or ""} nodes_set[start] = { node = node, type = match or '' }
end) end)
end end
end end
@ -140,7 +139,7 @@ local function prepare_node(node, kind)
local matches = {} local matches = {}
kind = kind or node.type kind = kind or node.type
if node.node then if node.node then
table.insert(matches, {kind = get_icon(kind), def = node.node, type = kind}) table.insert(matches, { kind = get_icon(kind), def = node.node, type = kind })
else else
for name, item in pairs(node) do for name, item in pairs(node) do
vim.list_extend(matches, prepare_node(item, name)) vim.list_extend(matches, prepare_node(item, name))
@ -182,8 +181,8 @@ local function get_scope(type, source)
return parent, true return parent, true
end end
if type == "var" and next ~= nil then if type == 'var' and next ~= nil then
if next:type() == "function" or next:type() == "arrow_function" or next:type() == "function_definition" then if next:type() == 'function' or next:type() == 'arrow_function' or next:type() == 'function_definition' then
trace(current:type(), current:range()) trace(current:type(), current:range())
return next, true return next, true
elseif parent:type() == 'function_declaration' then elseif parent:type() == 'function_declaration' then
@ -208,10 +207,9 @@ local function get_scope(type, source)
end end
end end
if source:type() == "type_identifier" then if source:type() == 'type_identifier' then
return source:parent(), true return source:parent(), true
end end
end end
local function get_smallest_context(source) local function get_smallest_context(source)
@ -229,10 +227,10 @@ local function get_smallest_context(source)
-- if source:type() == "identifier" then return get_var_context(source) end -- if source:type() == "identifier" then return get_var_context(source) end
end end
local lsp_reference = require"navigator.dochighlight".goto_adjent_reference local lsp_reference = require('navigator.dochighlight').goto_adjent_reference
function M.goto_adjacent_usage(bufnr, delta) function M.goto_adjacent_usage(bufnr, delta)
local opt = {forward = true} local opt = { forward = true }
-- log(delta) -- log(delta)
if delta < 0 then if delta < 0 then
opt.forward = false opt.forward = false
@ -269,7 +267,7 @@ local function key(fname, filter)
end end
local function get_all_nodes(bufnr, filter, summary) local function get_all_nodes(bufnr, filter, summary)
local fname = vim.fn.expand("%:p:f") local fname = vim.fn.expand('%:p:f')
local uri = vim.uri_from_fname(fname) local uri = vim.uri_from_fname(fname)
if bufnr ~= 0 then if bufnr ~= 0 then
uri = vim.uri_from_bufnr(bufnr) uri = vim.uri_from_bufnr(bufnr)
@ -282,7 +280,7 @@ local function get_all_nodes(bufnr, filter, summary)
local result = lru:get(hash) local result = lru:get(hash)
if result ~= nil and result.ftime == ftime then if result ~= nil and result.ftime == ftime then
log("get data from cache") log('get data from cache')
return result.nodes, result.length return result.nodes, result.length
end end
@ -292,15 +290,15 @@ local function get_all_nodes(bufnr, filter, summary)
trace(bufnr, filter, summary) trace(bufnr, filter, summary)
if not bufnr then if not bufnr then
vim.notify("get_all_node invalide bufnr", vim.lsp.log_levels.WARN) vim.notify('get_all_node invalide bufnr', vim.lsp.log_levels.WARN)
end end
summary = summary or false summary = summary or false
if not parsers.has_parser() then if not parsers.has_parser() then
vim.notify("ts not loaded", vim.lsp.log_levels.WARN) vim.notify('ts not loaded', vim.lsp.log_levels.WARN)
end end
local path_sep = require"navigator.util".path_sep() local path_sep = require('navigator.util').path_sep()
local path_cur = require"navigator.util".path_cur() local path_cur = require('navigator.util').path_cur()
local display_filename = fname:gsub(cwd .. path_sep, path_cur, 1) local display_filename = fname:gsub(cwd .. path_sep, path_cur, 1)
local all_nodes = {} local all_nodes = {}
@ -310,13 +308,13 @@ local function get_all_nodes(bufnr, filter, summary)
-- 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,
["local_function"] = true, ['local_function'] = true,
["arrow_function"] = true, ['arrow_function'] = true,
["type"] = true, ['type'] = true,
["class"] = true, ['class'] = true,
["struct"] = true, ['struct'] = true,
["method"] = true ['method'] = true,
} }
-- check and load buff -- check and load buff
@ -335,8 +333,10 @@ local function get_all_nodes(bufnr, filter, summary)
for i = 1, n do for i = 1, n do
local index = n + 1 - i local index = n + 1 - i
local parent_def = parents[index] local parent_def = parents[index]
if ts_utils.is_parent(parent_def.node, def.node) if
or (containers[parent_def.type] and ts_utils.is_parent(parent_def.node:parent(), def.node)) then ts_utils.is_parent(parent_def.node, def.node)
or (containers[parent_def.type] and ts_utils.is_parent(parent_def.node:parent(), def.node))
then
break break
else else
parents[index] = nil parents[index] = nil
@ -359,7 +359,7 @@ local function get_all_nodes(bufnr, filter, summary)
if node.def == nil then if node.def == nil then
goto continue goto continue
end end
item.node_text = ts_utils.get_node_text(tsdata, bufnr)[1] item.node_text = vim.treesitter.get_node_text(tsdata, bufnr)
local scope, is_func local scope, is_func
if summary then if summary then
@ -371,7 +371,7 @@ local function get_all_nodes(bufnr, filter, summary)
-- hack for lua and maybe other language aswell -- hack for lua and maybe other language aswell
local parent = tsdata:parent() local parent = tsdata:parent()
if parent ~= nil and parent:type() == 'function_name' or parent:type() == 'function_name_field' then if parent ~= nil and parent:type() == 'function_name' or parent:type() == 'function_name_field' then
item.node_text = ts_utils.get_node_text(parent, bufnr)[1] item.node_text = vim.treesitter.get_node_text(parent, bufnr)
log(parent:type(), item.node_text) log(parent:type(), item.node_text)
end end
end end
@ -390,18 +390,26 @@ local function get_all_nodes(bufnr, filter, summary)
end end
if item.node_scope then if item.node_scope then
trace(item.type, tsdata:type(), item.node_text, item.kind, item.node_text, "range", trace(
item.node_scope.start.line, item.node_scope['end'].line) -- set to log if need to trace result item.type,
tsdata:type(),
item.node_text,
item.kind,
item.node_text,
'range',
item.node_scope.start.line,
item.node_scope['end'].line
) -- set to log if need to trace result
end end
goto continue goto continue
end end
item.range = ts_utils.node_to_lsp_range(tsdata) item.range = ts_utils.node_to_lsp_range(tsdata)
local start_line_node, _, _ = tsdata:start() local start_line_node, _, _ = tsdata:start()
if item.node_text == "_" then if item.node_text == '_' then
goto continue goto continue
end end
item.full_text = vim.trim(api.nvim_buf_get_lines(bufnr, start_line_node, start_line_node + 1, false)[1] or "") item.full_text = vim.trim(api.nvim_buf_get_lines(bufnr, start_line_node, start_line_node + 1, false)[1] or '')
item.full_text = item.full_text:gsub('%s*[%[%(%{]*%s*$', '') item.full_text = item.full_text:gsub('%s*[%[%(%{]*%s*$', '')
item.uri = uri item.uri = uri
@ -411,12 +419,12 @@ local function get_all_nodes(bufnr, filter, summary)
item.lnum, item.col, _ = def.node:start() item.lnum, item.col, _ = def.node:start()
item.lnum = item.lnum + 1 item.lnum = item.lnum + 1
item.col = item.col + 1 item.col = item.col + 1
local indent = "" local indent = ''
if #parents > 1 then if #parents > 1 then
indent = string.rep(" ", #parents - 1) .. "" indent = string.rep(' ', #parents - 1) .. ''
end end
item.text = string.format(" %s %s%-10s\t %s", item.kind, indent, item.node_text, item.full_text) item.text = string.format(' %s %s%-10s\t %s', item.kind, indent, item.node_text, item.full_text)
if #item.text > length then if #item.text > length then
length = #item.text length = #item.text
end end
@ -425,31 +433,31 @@ local function get_all_nodes(bufnr, filter, summary)
end end
end end
trace(all_nodes) trace(all_nodes)
local nd = {nodes = all_nodes, ftime = vim.fn.getftime(fname), length = length} local nd = { nodes = all_nodes, ftime = vim.fn.getftime(fname), length = length }
lru:set(hash, nd) lru:set(hash, nd)
if should_unload then if should_unload then
vim.api.nvim_buf_delete(bufnr, {unload = true}) vim.api.nvim_buf_delete(bufnr, { unload = true })
end end
return all_nodes, length return all_nodes, length
end end
function M.buf_func(bufnr) function M.buf_func(bufnr)
if not ok or ts_locals == nil then if not ok or ts_locals == nil then
error("treesitter not loaded") error('treesitter not loaded')
return return
end end
bufnr = bufnr or api.nvim_get_current_buf() bufnr = bufnr or api.nvim_get_current_buf()
local all_nodes, width = get_all_nodes(bufnr, { local all_nodes, width = get_all_nodes(bufnr, {
["function"] = true, ['function'] = true,
["var"] = true, ['var'] = true,
["method"] = true, ['method'] = true,
["class"] = true, ['class'] = true,
["type"] = true ['type'] = true,
}, true) }, true)
if #all_nodes < 1 then if #all_nodes < 1 then
trace("no node found for ", bufnr) -- set to log trace('no node found for ', bufnr) -- set to log
return return
end end
@ -478,26 +486,25 @@ function M.buf_func(bufnr)
end end
return all_nodes, width return all_nodes, width
end end
function M.buf_ts() function M.buf_ts()
if ts_locals == nil then if ts_locals == nil then
error("treesitter not loaded") error('treesitter not loaded')
return return
end end
local bufnr = api.nvim_get_current_buf() local bufnr = api.nvim_get_current_buf()
local all_nodes, width = get_all_nodes(bufnr) local all_nodes, width = get_all_nodes(bufnr)
local ft = vim.api.nvim_buf_get_option(bufnr, "ft") local ft = vim.api.nvim_buf_get_option(bufnr, 'ft')
gui.new_list_view({ gui.new_list_view({
items = all_nodes, items = all_nodes,
prompt = true, prompt = true,
ft = ft, ft = ft,
rawdata = true, rawdata = true,
width = width + 10, width = width + 10,
api = _NgConfigValues.icons.treesitter_defult api = _NgConfigValues.icons.treesitter_defult,
}) })
end end
@ -505,7 +512,7 @@ M.get_all_nodes = get_all_nodes
function M.bufs_ts() function M.bufs_ts()
if ts_locals == nil then if ts_locals == nil then
error("treesitter not loaded") error('treesitter not loaded')
return return
end end
local bufs = vim.api.nvim_list_bufs() local bufs = vim.api.nvim_list_bufs()
@ -528,13 +535,13 @@ function M.bufs_ts()
if #ts_opened > 1 then if #ts_opened > 1 then
trace(ts_opened) trace(ts_opened)
local ft = vim.api.nvim_buf_get_option(0, "ft") local ft = vim.api.nvim_buf_get_option(0, 'ft')
gui.new_list_view({ gui.new_list_view({
items = ts_opened, items = ts_opened,
prompt = true, prompt = true,
ft = ft, ft = ft,
width = max_length + 10, width = max_length + 10,
api = _NgConfigValues.icons.treesitter_defult api = _NgConfigValues.icons.treesitter_defult,
}) })
end end
end end
@ -543,7 +550,7 @@ local function node_in_range(parser, range)
for _, child in pairs(parser._children) do for _, child in pairs(parser._children) do
if child:contains(range) then if child:contains(range) then
local result = node_in_range(child, range) local result = node_in_range(child, range)
if not vim.tbl_contains({vim.bo.filetype}, result:lang()) then if not vim.tbl_contains({ vim.bo.filetype }, result:lang()) then
-- log("not correct tree embedded or comment?", result:lang()) -- log("not correct tree embedded or comment?", result:lang())
return parser return parser
end end
@ -564,7 +571,7 @@ function M.get_node_at_line(lnum)
lnum = cursor[1] lnum = cursor[1]
end end
local first_non_whitespace_col = fn.match(fn.getline(lnum), '\\S') local first_non_whitespace_col = fn.match(fn.getline(lnum), '\\S')
local range = {lnum - 1, first_non_whitespace_col, lnum - 1, first_non_whitespace_col} local range = { lnum - 1, first_non_whitespace_col, lnum - 1, first_non_whitespace_col }
-- Get the language tree with nodes inside the given range -- Get the language tree with nodes inside the given range
local root = parsers.get_parser() local root = parsers.get_parser()
@ -578,7 +585,7 @@ function M.get_node_at_line(lnum)
return node return node
end end
local usage_namespace = vim.api.nvim_create_namespace("nvim-treesitter-usages") local usage_namespace = vim.api.nvim_create_namespace('nvim-treesitter-usages')
function M.highlight_usages(bufnr) function M.highlight_usages(bufnr)
M.clear_usage_highlights(bufnr) M.clear_usage_highlights(bufnr)
@ -595,12 +602,12 @@ function M.highlight_usages(bufnr)
for _, usage_node in ipairs(usages) do for _, usage_node in ipairs(usages) do
if usage_node ~= node_at_point then if usage_node ~= node_at_point then
ts_utils.highlight_node(usage_node, bufnr, usage_namespace, "TSDefinitionUsage") ts_utils.highlight_node(usage_node, bufnr, usage_namespace, 'TSDefinitionUsage')
end end
end end
if def_node ~= node_at_point then if def_node ~= node_at_point then
ts_utils.highlight_node(def_node, bufnr, usage_namespace, "TSDefinition") ts_utils.highlight_node(def_node, bufnr, usage_namespace, 'TSDefinition')
end end
end end
@ -610,7 +617,7 @@ end
function M.get_node_at_pos(pos, parser) function M.get_node_at_pos(pos, parser)
-- local cursor = api.nvim_win_get_cursor(winnr or 0) -- local cursor = api.nvim_win_get_cursor(winnr or 0)
local cursor_range = {pos[1], pos[2]} local cursor_range = { pos[1], pos[2] }
log(cursor_range) log(cursor_range)
local root = ts_utils.get_root_for_position(unpack(cursor_range), parser) local root = ts_utils.get_root_for_position(unpack(cursor_range), parser)
@ -651,7 +658,6 @@ function M.get_node_scope(node)
end end
return sr, sc, er, ec return sr, sc, er, ec
end end
return M return M

Loading…
Cancel
Save