Skip to content

Commit

Permalink
Lua LSP recognizes conventional 'M' as the current module.
Browse files Browse the repository at this point in the history
Completions, signature help, etc. will work inside modules.
  • Loading branch information
orbitalquark committed Sep 19, 2024
1 parent 8ab330e commit 2e9e187
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 1 deletion.
29 changes: 28 additions & 1 deletion init_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -338,11 +338,38 @@ test('lua lsp should work for untitled buffers', function()

test.type('string.byte(')

lsp.stop()
test.assert_equal(auto_c_show.called, true)
test.assert_equal(call_tip_show.called, true)
end)

test('lua lsp should recognize M as the current module', function()
local _<close> = test.tmpfile('.lua', [[
--- @module name
local M = {}
--- Field.
M.field = ''
--- Func.
function M.func() end
]], true)
lsp.start()
buffer:document_end()

local auto_c_show = test.stub()
local _<close> = test.mock(buffer, 'auto_c_show', auto_c_show)
local call_tip_show = test.stub()
local _<close> = test.mock(view, 'call_tip_show', call_tip_show)

test.type('name.func(')

test.assert_equal(auto_c_show.called, true)
local completions = auto_c_show.args[3]
test.assert_contains(completions, 'field')
test.assert_contains(completions, 'func')
test.assert_equal(call_tip_show.called, true)
end)

test('lsp menu should allow manually starting and stopping an lsp server', function()
local _<close> = test.mock(lsp, 'server_commands', {cpp = 'clangd'})
local dir<close> = test.tmpdir(clangd_project)
Expand Down
22 changes: 22 additions & 0 deletions server.lua
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,24 @@ register('textDocument/didChange', function(params)
pl_dir.rmtree(tmpdir)
end)

--- Replaces the conventional 'M' in symbol *symbol* with the file's @module declaration,
-- if possible.
-- @param symbol Symbol name that starts with 'M'.
-- @param params LSP params for the completion/signatureHelp/etc. request.
-- @return substituted or original symbol
local function substitute_M(symbol, params)
local lines = files[params.textDocument.uri]
if not lines then return symbol end
for _, line in ipairs(lines) do
local module = line:match('^%s*%-%-%-?%s*@module%s([%w_.]+)')
if module then
log:debug('found module %s; using it instead of M', module)
return symbol:gsub('^M', module)
end
end
return symbol
end

--- Map of expression patterns to their types.
-- Used for type-hinting when showing autocompletions for variables. Expressions are expected
-- to match after the '=' sign of a statement.
Expand All @@ -293,6 +311,8 @@ register('textDocument/completion', function(params)
symbol, op, part)
if symbol == '' and part == '' then return json.null end -- nothing to complete
symbol, part = symbol:gsub('^_G%.?', ''), part ~= '_G' and part or ''
-- Replace conventional M with its @module declaration if possible.
if symbol == 'M' then symbol = substitute_M(symbol, params) end
-- Attempt to identify string type and file type symbols.
local assignment = '%f[%w_]' .. symbol:gsub('(%p)', '%%%1') .. '%s*=%s*(.*)$'
for i = line_num - 1, 1, -1 do
Expand Down Expand Up @@ -347,6 +367,7 @@ local function get_symbol(params)
local symbol_part_right = line:match('^[%w_]*', col_num)
local symbol_part_left = line:sub(1, col_num - 1):match('[%w_.:]*$')
local symbol = symbol_part_left .. symbol_part_right
if symbol:find('^M%.') then symbol = substitute_M(symbol, params) end
return symbol ~= '' and symbol or nil
end

Expand Down Expand Up @@ -431,6 +452,7 @@ register('textDocument/signatureHelp', function(params)
goto retry
end
local func = text:sub(1, s - 1):match('[%w_.:]+$')
if func and func:find('^M%.') then func = substitute_M(func, params) end
if not func then return json.null end

-- Get its signature(s).
Expand Down

0 comments on commit 2e9e187

Please sign in to comment.