local nodes = require('go.ts.nodes') local tsutil = require('nvim-treesitter.ts_utils') local log = require('go.utils').log local warn = require('go.utils').warn local info = require('go.utils').info local debug = require('go.utils').debug -- debug = log local M = { query_struct = '(type_spec name:(type_identifier) @definition.struct type: (struct_type))', query_package = '(package_clause (package_identifier)@package.name)@package.clause', query_struct_id = '(type_spec name:(type_identifier) @definition.struct (struct_type))', query_em_struct_id = '(field_declaration name:(field_identifier) @definition.struct (struct_type))', query_struct_block = [[((type_declaration (type_spec name:(type_identifier) @struct.name type: (struct_type)))@struct.declaration)]], query_type_declaration = [[((type_declaration (type_spec name:(type_identifier)@type_decl.name type:(type_identifier)@type_decl.type))@type_decl.declaration)]], -- rename to gotype so not confuse with type query_em_struct_block = [[(field_declaration name:(field_identifier)@struct.name type: (struct_type)) @struct.declaration]], query_struct_block_from_id = [[(((type_spec name:(type_identifier) type: (struct_type)))@block.struct_from_id)]], -- query_em_struct = "(field_declaration name:(field_identifier) @definition.struct type: (struct_type))", query_interface_id = [[((type_declaration (type_spec name:(type_identifier) @interface.name type:(interface_type)))@interface.declaration)]], query_interface_method = [[((method_spec name: (field_identifier)@method.name)@interface.method.declaration)]], query_func = '((function_declaration name: (identifier)@function.name) @function.declaration)', query_method = '(method_declaration receiver: (parameter_list (parameter_declaration name:(identifier)@method.receiver.name type:(type_identifier)@method.receiver.type)) name:(field_identifier)@method.name)@method.declaration', query_method_name = [[((method_declaration receiver: (parameter_list)@method.receiver name: (field_identifier)@method.name body:(block))@method.declaration)]], query_method_void = [[((method_declaration receiver: (parameter_list (parameter_declaration name: (identifier)@method.receiver.name type: (pointer_type)@method.receiver.type) ) name: (field_identifier)@method.name parameters: (parameter_list)@method.parameter body:(block) )@method.declaration)]], query_method_multi_ret = [[(method_declaration receiver: (parameter_list (parameter_declaration name: (identifier)@method.receiver.name type: (pointer_type)@method.receiver.type) ) name: (field_identifier)@method.name parameters: (parameter_list)@method.parameter result: (parameter_list)@method.result body:(block) )@method.declaration]], query_method_single_ret = [[((method_declaration receiver: (parameter_list (parameter_declaration name: (identifier)@method.receiver.name type: (pointer_type)@method.receiver.type) ) name: (field_identifier)@method.name parameters: (parameter_list)@method.parameter result: (type_identifier)@method.result body:(block) )@method.declaration)]], query_tr_method_void = [[((method_declaration receiver: (parameter_list (parameter_declaration name: (identifier)@method.receiver.name type: (type_identifier)@method.receiver.type) ) name: (field_identifier)@method.name parameters: (parameter_list)@method.parameter body:(block) )@method.declaration)]], query_tr_method_multi_ret = [[((method_declaration receiver: (parameter_list (parameter_declaration name: (identifier)@method.receiver.name type: (type_identifier)@method.receiver.type) ) name: (field_identifier)@method.name parameters: (parameter_list)@method.parameter result: (parameter_list)@method.result body:(block) )@method.declaration)]], query_tr_method_single_ret = [[((method_declaration receiver: (parameter_list (parameter_declaration name: (identifier)@method.receiver.name type: (type_identifier)@method.receiver.type) ) name: (field_identifier)@method.name parameters: (parameter_list)@method.parameter result: (type_identifier)@method.result body:(block) )@method.declaration)]], query_test_func = [[((function_declaration name: (identifier) @test_name parameters: (parameter_list (parameter_declaration name: (identifier) type: (pointer_type (qualified_type package: (package_identifier) @_param_package name: (type_identifier) @_param_name)))) ) @testfunc (#contains? @test_name "Test") (#match? @_param_package "testing") (#match? @_param_name "T"))]], query_testcase_node = [[(literal_value (literal_element (literal_value .(keyed_element (literal_element (identifier)) (literal_element (interpreted_string_literal) @test.name)))))]], query_string_literal = [[((interpreted_string_literal) @string.value)]], } local function get_name_defaults() return { ['func'] = 'function', ['if'] = 'if', ['else'] = 'else', ['for'] = 'for' } end M.get_struct_node_at_pos = function(bufnr) local query = M.query_struct_block .. ' ' .. M.query_em_struct_block local bufn = bufnr or vim.api.nvim_get_current_buf() local ns = nodes.nodes_at_cursor(query, get_name_defaults(), bufn) if ns == nil then debug('struct not found') else log('struct node', ns) return ns[#ns] end end M.get_type_node_at_pos = function(bufnr) local query = M.query_type_declaration local bufn = bufnr or vim.api.nvim_get_current_buf() local ns = nodes.nodes_at_cursor(query, get_name_defaults(), bufn) if ns == nil then debug('type not found') else log('type node', ns) return ns[#ns] end end M.get_interface_node_at_pos = function(bufnr) local query = M.query_interface_id local bufn = bufnr or vim.api.nvim_get_current_buf() local ns = nodes.nodes_at_cursor(query, get_name_defaults(), bufn) if ns == nil then debug('interface not found') else return ns[#ns] end end M.get_interface_method_node_at_pos = function(bufnr) local query = M.query_interface_method bufnr = bufnr or vim.api.nvim_get_current_buf() local ns = nodes.nodes_at_cursor(query, get_name_defaults(), bufnr) if ns == nil then warn('interface method not found') else return ns[#ns] end end M.get_func_method_node_at_pos = function(bufnr) local query = M.query_func .. ' ' .. M.query_method_name -- local query = require("go.ts.go").query_method_name local bufn = bufnr or vim.api.nvim_get_current_buf() local ns = nodes.nodes_at_cursor(query, get_name_defaults(), bufn) if ns == nil then return nil end if ns == nil then warn('function not found') else return ns[#ns] end end M.get_testcase_node = function(bufnr) local query = M.query_testcase_node local bufn = bufnr or vim.api.nvim_get_current_buf() local ns = nodes.nodes_at_cursor(query, get_name_defaults(), bufn, 'name') if ns == nil then debug('test case not found') else log('testcase node', ns[#ns]) return ns[#ns] end end M.get_string_node = function(bufnr) local query = M.query_string_literal local bufn = bufnr or vim.api.nvim_get_current_buf() local ns = nodes.nodes_at_cursor(query, get_name_defaults(), bufn, 'value') if ns == nil then debug('struct not found') else log('struct node', ns[#ns]) return ns[#ns] end end M.get_import_node_at_pos = function(bufnr) local bufn = bufnr or vim.api.nvim_get_current_buf() local cur_node = tsutil.get_node_at_cursor() if cur_node and (cur_node:type() == 'import_spec' or cur_node:parent():type() == 'import_spec') then return cur_node end end M.get_module_at_pos = function(bufnr) local node = M.get_import_node_at_pos(bufnr) if node then local module = vim.treesitter.query.get_node_text(node, vim.api.nvim_get_current_buf()) -- log module = string.gsub(module, '"', '') return module end end M.get_package_node_at_pos = function(bufnr) local row, col = unpack(vim.api.nvim_win_get_cursor(0)) row, col = row, col + 1 if row > 10 then return end local query = M.query_package -- local query = require("go.ts.go").query_method_name local bufn = bufnr or vim.api.nvim_get_current_buf() local ns = nodes.nodes_at_cursor(query, get_name_defaults(), bufn) if ns == nil then return nil end if ns == nil then warn('package not found') else return ns[#ns] end end function M.in_func() local ok, ts_utils = pcall(require, 'nvim-treesitter.ts_utils') if not ok then return false end local current_node = ts_utils.get_node_at_cursor() if not current_node then return false end local expr = current_node while expr do if expr:type() == 'function_declaration' or expr:type() == 'method_declaration' then return true end expr = expr:parent() end return false end return M