138 lines
4.0 KiB
Lua
138 lines
4.0 KiB
Lua
local M = {}
|
|
|
|
-- Parse method signature from a line
|
|
local function parse_method(line)
|
|
-- Match: func (receiver) MethodName(params) (returns)
|
|
local pattern = "^func%s+%([^)]+%)%s+([%w_]+)%s*(%b())%s*(.*)"
|
|
local name, params, returns = line:match(pattern)
|
|
|
|
if name then
|
|
-- Clean up returns (remove leading spaces and parentheses if single return)
|
|
returns = returns:gsub("^%s+", "")
|
|
if returns:match("^%b()") then
|
|
returns = " " .. returns
|
|
elseif returns ~= "" then
|
|
returns = " " .. returns
|
|
end
|
|
|
|
return name .. params .. returns
|
|
end
|
|
return nil
|
|
end
|
|
|
|
-- Find all methods for a given struct type
|
|
local function find_struct_methods(struct_name, bufnr)
|
|
local methods = {}
|
|
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
|
|
|
|
-- Pattern to match methods with the struct as receiver
|
|
-- Matches both pointer and value receivers
|
|
local patterns = {
|
|
"^func%s+%(%s*%w+%s+%*?" .. struct_name .. "%s*%)", -- Standard pattern
|
|
}
|
|
|
|
for i, line in ipairs(lines) do
|
|
for _, pattern in ipairs(patterns) do
|
|
if line:match(pattern) then
|
|
local method_sig = parse_method(line)
|
|
if method_sig then
|
|
table.insert(methods, method_sig)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return methods
|
|
end
|
|
|
|
-- Get struct name under cursor
|
|
local function get_struct_name()
|
|
local line = vim.api.nvim_get_current_line()
|
|
|
|
-- Try to match: type StructName struct
|
|
local struct_name = line:match("^type%s+([%w_]+)%s+struct")
|
|
|
|
if not struct_name then
|
|
-- Try to match if cursor is on struct keyword
|
|
struct_name = line:match("type%s+([%w_]+)%s+struct")
|
|
end
|
|
|
|
return struct_name
|
|
end
|
|
|
|
-- Generate interface from methods
|
|
local function generate_interface(struct_name, methods)
|
|
if #methods == 0 then
|
|
return nil, "No methods found for struct " .. struct_name
|
|
end
|
|
|
|
-- Create interface name (conventionally, I + StructName or StructName + er)
|
|
local interface_name = "I" .. struct_name
|
|
|
|
local lines = {
|
|
"type " .. interface_name .. " interface {",
|
|
}
|
|
|
|
for _, method in ipairs(methods) do
|
|
local method_without_bracket = method:gsub("{$", "")
|
|
local cleaned_method = method_without_bracket:gsub("%s+$", "")
|
|
table.insert(lines, "\t" .. cleaned_method)
|
|
end
|
|
|
|
table.insert(lines, "}")
|
|
|
|
return lines, nil
|
|
end
|
|
|
|
-- Main function to extract interface
|
|
function M.extract_interface()
|
|
local bufnr = vim.api.nvim_get_current_buf()
|
|
|
|
-- Check if we're in a Go file
|
|
local filetype = vim.bo[bufnr].filetype
|
|
if filetype ~= "go" then
|
|
vim.notify("This command only works in Go files", vim.log.levels.ERROR)
|
|
return
|
|
end
|
|
|
|
-- Get struct name under cursor
|
|
local struct_name = get_struct_name()
|
|
if not struct_name then
|
|
vim.notify("Cursor is not on a struct definition", vim.log.levels.ERROR)
|
|
return
|
|
end
|
|
|
|
-- Find all methods for this struct
|
|
local methods = find_struct_methods(struct_name, bufnr)
|
|
|
|
-- Generate interface
|
|
local interface_lines, err = generate_interface(struct_name, methods)
|
|
if err then
|
|
vim.notify(err, vim.log.levels.WARN)
|
|
return
|
|
end
|
|
|
|
-- Insert interface above the struct definition
|
|
local cursor_line = vim.api.nvim_win_get_cursor(0)[1]
|
|
vim.api.nvim_buf_set_lines(bufnr, cursor_line - 1, cursor_line - 1, false, interface_lines)
|
|
vim.api.nvim_buf_set_lines(bufnr, cursor_line, cursor_line, false, { "" }) -- Empty line
|
|
|
|
vim.notify("Interface extracted: " .. #methods .. " methods found", vim.log.levels.INFO)
|
|
end
|
|
|
|
-- Setup function for lazy.nvim
|
|
function M.setup()
|
|
-- Create command
|
|
vim.api.nvim_create_user_command("GoExtractInterface", M.extract_interface, {
|
|
desc = "Extract interface from Go struct under cursor",
|
|
})
|
|
|
|
-- Optional: Add keybinding
|
|
vim.keymap.set("n", "<leader>cei", M.extract_interface, {
|
|
desc = "Extract interface from struct",
|
|
silent = true,
|
|
})
|
|
end
|
|
|
|
return M
|