summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2018-12-21 16:50:01 +0800
committer最萌小汐 <sumneko@hotmail.com>2018-12-21 16:50:01 +0800
commit3c5ff2671305041d03cde8dafb05d4aed0cc0a65 (patch)
tree0f058a92500c7abef99fab007dc30d80107795b6
parentbc0ab7b1fa924076a549cdcaaf3e90a6ef67600f (diff)
downloadlua-language-server-3c5ff2671305041d03cde8dafb05d4aed0cc0a65.zip
找当前参数
-rw-r--r--server/src/matcher/init.lua1
-rw-r--r--server/src/matcher/signature.lua66
-rw-r--r--server/src/method/init.lua1
-rw-r--r--server/src/method/initialize.lua4
-rw-r--r--server/src/method/textDocument/signatureHelp.lua48
-rw-r--r--server/test/main.lua1
-rw-r--r--server/test/signature/init.lua35
7 files changed, 156 insertions, 0 deletions
diff --git a/server/src/matcher/init.lua b/server/src/matcher/init.lua
index 27adbbea..29239370 100644
--- a/server/src/matcher/init.lua
+++ b/server/src/matcher/init.lua
@@ -8,6 +8,7 @@ local api = {
findResult = require 'matcher.find_result',
findLib = require 'matcher.find_lib',
completion = require 'matcher.completion',
+ signature = require 'matcher.signature',
vm = require 'matcher.vm',
}
diff --git a/server/src/matcher/signature.lua b/server/src/matcher/signature.lua
new file mode 100644
index 00000000..97b8fc00
--- /dev/null
+++ b/server/src/matcher/signature.lua
@@ -0,0 +1,66 @@
+local hover = require 'matcher.hover'
+
+local function isContainPos(obj, pos)
+ if obj.start <= pos and obj.finish + 1 >= pos then
+ return true
+ end
+ return false
+end
+
+local function findArgCount(args, pos)
+ for i, arg in ipairs(args) do
+ if isContainPos(arg, pos) then
+ return i
+ end
+ end
+ return #args + 1
+end
+
+-- 找出范围包含pos的,且有dirty标记的call
+local function findDirtyCall(vm, pos)
+ local results = {}
+ for _, call in ipairs(vm.results.calls) do
+ if call.args.dirty and isContainPos(call.args, pos) then
+ local n = findArgCount(call.args, pos)
+ results[#results+1] = {
+ func = call.func,
+ var = vm.results.sources[call.lastObj],
+ source = call.lastObj,
+ select = n,
+ args = call.args,
+ }
+ end
+ end
+ -- 可能处于 'func1(func2(' 的嵌套中,因此距离越远的函数层级越低
+ table.sort(results, function (a, b)
+ return a.args.start < b.args.start
+ end)
+ return results
+end
+
+local function parseCall(call)
+ local results = hover(call.var, call.source, nil, call.select)
+ return results[1], results[2]
+end
+
+return function (vm, pos)
+ local calls = findDirtyCall(vm, pos)
+ if #calls == 0 then
+ return nil
+ end
+
+ local results = {}
+ for i, call in ipairs(calls) do
+ local label, description = parseCall(call)
+ results[i] = {
+ label = label,
+ description = description,
+ arg = {
+ label = 'a',
+ description = '参数说明',
+ }
+ }
+ end
+
+ return results
+end
diff --git a/server/src/method/init.lua b/server/src/method/init.lua
index 22c58289..ea7fa05a 100644
--- a/server/src/method/init.lua
+++ b/server/src/method/init.lua
@@ -18,6 +18,7 @@ init 'textDocument/implementation'
init 'textDocument/publishDiagnostics'
init 'textDocument/rename'
init 'textDocument/references'
+init 'textDocument/signatureHelp'
init 'workspace/didChangeWatchedFiles'
init 'workspace/didChangeWorkspaceFolders'
diff --git a/server/src/method/initialize.lua b/server/src/method/initialize.lua
index 05a1bb49..4bc3ff2e 100644
--- a/server/src/method/initialize.lua
+++ b/server/src/method/initialize.lua
@@ -12,6 +12,10 @@ return function (lsp)
referencesProvider = true,
-- 支持“重命名”
renameProvider = true,
+ -- 支持“签名帮助”
+ signatureHelpProvider = {
+ triggerCharacters = { '(', ',' },
+ },
-- 文本同步方式
textDocumentSync = {
-- 打开关闭文本时通知
diff --git a/server/src/method/textDocument/signatureHelp.lua b/server/src/method/textDocument/signatureHelp.lua
new file mode 100644
index 00000000..0fb7fd10
--- /dev/null
+++ b/server/src/method/textDocument/signatureHelp.lua
@@ -0,0 +1,48 @@
+local matcher = require 'matcher'
+
+return function (lsp, params)
+ local uri = params.textDocument.uri
+ local vm, lines = lsp:loadVM(uri)
+ if not vm then
+ return {}
+ end
+ -- lua是从1开始的,因此都要+1
+ local position = lines:position(params.position.line + 1, params.position.character + 1)
+ do return end
+ return {
+ activeSignature = 0,
+ activeParameter = 1,
+ signatures = {
+ {
+ label = 'xxxx(a, b, c)',
+ documentation = {
+ kind = 'markdown',
+ value = '函数说明',
+ },
+ parameters = {
+ {
+ label = 'a',
+ documentation = {
+ kind = 'markdown',
+ value = '参数a说明',
+ },
+ },
+ {
+ label = 'b',
+ documentation = {
+ kind = 'markdown',
+ value = '参数b说明',
+ },
+ },
+ {
+ label = 'c',
+ documentation = {
+ kind = 'markdown',
+ value = '参数c说明',
+ },
+ },
+ },
+ },
+ }
+ }
+end
diff --git a/server/test/main.lua b/server/test/main.lua
index 2739a650..da005d51 100644
--- a/server/test/main.lua
+++ b/server/test/main.lua
@@ -32,6 +32,7 @@ local function main()
test 'find_lib'
test 'hover'
test 'completion'
+ test 'signature'
print('测试完成')
end
diff --git a/server/test/signature/init.lua b/server/test/signature/init.lua
new file mode 100644
index 00000000..620aab4b
--- /dev/null
+++ b/server/test/signature/init.lua
@@ -0,0 +1,35 @@
+local parser = require 'parser'
+local matcher = require 'matcher'
+
+rawset(_G, 'TEST', true)
+
+function TEST(script)
+ return function (expect)
+ local pos = script:find('@', 1, true)
+ local new_script = script:gsub('@', '')
+ local ast = parser:ast(new_script)
+ local vm = matcher.vm(ast)
+ assert(vm)
+ local results = matcher.signature(vm, pos)
+ assert(results)
+ local result = results[#results]
+
+ local label = result.label:gsub('^[\r\n]*(.-)[\r\n]*$', '%1'):gsub('\r\n', '\n')
+ expect.label = expect.label:gsub('^[\r\n]*(.-)[\r\n]*$', '%1'):gsub('\r\n', '\n')
+ local arg = result.arg.label
+
+ assert(expect.label == label)
+ assert(expect.arg == arg)
+ end
+end
+
+TEST [[
+local function x(a, b)
+end
+
+x(@
+]]
+{
+ label = "function x(a: any, b: any)",
+ arg = 'a: any'
+}