summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/src/core/completion.lua73
-rw-r--r--server/src/core/diagnostics.lua2
-rw-r--r--server/src/vm/function.lua14
-rw-r--r--server/src/vm/value.lua8
-rw-r--r--server/src/vm/vm.lua36
-rw-r--r--server/test/completion/init.lua40
6 files changed, 143 insertions, 30 deletions
diff --git a/server/src/core/completion.lua b/server/src/core/completion.lua
index f2d2dceb..ede33524 100644
--- a/server/src/core/completion.lua
+++ b/server/src/core/completion.lua
@@ -246,7 +246,7 @@ end
local function searchCloseGlobal(vm, source, word, callback)
local loc = source:bindLocal()
local close = loc:close()
- -- 因为闭包的关系落在局部变量finish到close范围内的source一定能访问到该局部变量
+ -- 因为闭包的关系落在局部变量finish到close范围内的全局变量一定能访问到该局部变量
for _, src in ipairs(vm.sources) do
if src:get 'global'
and src.start >= source.finish
@@ -296,11 +296,19 @@ local function searchAsLocal(vm, source, word, callback)
end
end
+local function searchAsArg(vm, source, word, callback)
+ searchCloseGlobal(vm, source, word, callback)
+end
+
local function searchSource(vm, source, word, callback)
if source:get 'table index' then
searchAsIndex(vm, source, word, callback)
return
end
+ if source:get 'arg' then
+ searchAsArg(vm, source, word, callback)
+ return
+ end
if source:get 'global' then
searchAsGlobal(vm, source, word, callback)
return
@@ -319,6 +327,68 @@ local function searchSource(vm, source, word, callback)
end
end
+local function searchCallArg(vm, source, word, callback, pos)
+ local results = {}
+ for _, src in ipairs(vm.sources) do
+ if src.type == 'call'
+ and src.start <= pos
+ and src.finish >= pos
+ then
+ results[#results+1] = src
+ end
+ end
+ if #results == 0 then
+ return nil
+ end
+ -- 可能处于 'func1(func2(' 的嵌套中,将最近的call放到最前面
+ table.sort(results, function (a, b)
+ return a.start > b.start
+ end)
+ local call = results[1]
+ local func, args = call:bindCall()
+
+ local lib = func:getLib()
+ if not lib then
+ return
+ end
+
+ local select = 1
+ for i, arg in ipairs(args) do
+ if arg.start <= pos and arg.finish >= pos then
+ select = i
+ break
+ end
+ end
+
+ -- 根据参数位置找枚举值
+ if lib.args and lib.enums then
+ local arg = lib.args[select]
+ local name = arg and arg.name
+ for _, enum in ipairs(lib.enums) do
+ if enum.name == name and enum.enum then
+ if matchKey(word, enum.enum) then
+ local label, textEdit
+ if source.type ~= arg.type then
+ label = ('%q'):format(enum.enum)
+ end
+ if source.type ~= 'call' then
+ textEdit = {
+ start = source.start,
+ finish = source.finish,
+ newText = ('%q'):format(enum.enum),
+ }
+ end
+ callback(enum.enum, nil, CompletionItemKind.EnumMember, {
+ label = label,
+ documentation = enum.description,
+ textEdit = textEdit,
+ })
+ end
+ end
+ end
+ end
+end
+
local function searchAllWords(vm, source, word, callback)
if word == '' then
return
@@ -365,6 +435,7 @@ return function (vm, pos, word)
return nil
end
local callback, list = makeList(source, word)
+ searchCallArg(vm, source, word, callback, pos)
searchSource(vm, source, word, callback)
searchAllWords(vm, source, word, callback)
diff --git a/server/src/core/diagnostics.lua b/server/src/core/diagnostics.lua
index eb4ca403..f052d7d2 100644
--- a/server/src/core/diagnostics.lua
+++ b/server/src/core/diagnostics.lua
@@ -220,7 +220,7 @@ function mt:searchRedundantParameters(callback)
local passed = #args
for i = max + 1, passed do
local extra = args[i]
- callback(extra.source.start, extra.source.finish, max, passed)
+ callback(extra.start, extra.finish, max, passed)
end
end)
end
diff --git a/server/src/vm/function.lua b/server/src/vm/function.lua
index d5f67e25..700f1a19 100644
--- a/server/src/vm/function.lua
+++ b/server/src/vm/function.lua
@@ -138,7 +138,7 @@ function mt:hasRuned()
return self._runed > 0
end
-function mt:run()
+function mt:run(vm)
self._runed = self._runed + 1
if not self.source then
return
@@ -160,7 +160,7 @@ function mt:run()
end
-- 显性声明的参数
- self:createArgs()
+ self:createArgs(vm)
end
function mt:setArgs(values)
@@ -172,7 +172,9 @@ function mt:setArgs(values)
end
end
-function mt:createArg(arg, values)
+function mt:createArg(vm, arg, values)
+ vm:instantSource(arg)
+ arg:set('arg', true)
if arg.type == 'name' then
local value = table.remove(values, 1) or createValue('nil', arg)
local loc = createLocal(arg[1], arg, value)
@@ -201,7 +203,7 @@ function mt:hasDots()
return self._dots ~= nil
end
-function mt:createArgs()
+function mt:createArgs(vm)
if not self.source then
return
end
@@ -215,10 +217,10 @@ function mt:createArgs()
end
if args.type == 'list' then
for _, arg in ipairs(args) do
- self:createArg(arg, values)
+ self:createArg(vm, arg, values)
end
else
- self:createArg(args, values)
+ self:createArg(vm, args, values)
end
end
diff --git a/server/src/vm/value.lua b/server/src/vm/value.lua
index 7513ebd1..d47d6c15 100644
--- a/server/src/vm/value.lua
+++ b/server/src/vm/value.lua
@@ -13,14 +13,6 @@ local mt = {}
mt.__index = mt
mt.type = 'value'
-function mt:setValue(value)
- self._value = value
-end
-
-function mt:getValue()
- return self._value
-end
-
function mt:setType(tp, rate)
if type(tp) == 'table' then
for _, ctp in ipairs(tp) do
diff --git a/server/src/vm/vm.lua b/server/src/vm/vm.lua
index 0b994011..41015923 100644
--- a/server/src/vm/vm.lua
+++ b/server/src/vm/vm.lua
@@ -87,7 +87,7 @@ function mt:buildTable(source)
end
function mt:runFunction(func)
- func:run()
+ func:run(self)
if not func.source then
return
@@ -391,42 +391,49 @@ function mt:getIndex(source)
end
function mt:unpackList(list)
- local res = createMulti()
+ local values = createMulti()
+ local exps = createMulti()
if not list then
- return res
+ return values
end
if list.type == 'list' or list.type == 'call' or list.type == 'return' then
for i, exp in ipairs(list) do
+ self:instantSource(exp)
+ exps:push(exp)
if exp.type == '...' then
- res:merge(self:loadDots())
+ values:merge(self:loadDots())
break
end
local value = self:getExp(exp)
if value.type == 'multi' then
if i == #list then
value:eachValue(function (_, v)
- res:push(v)
+ values:push(v)
end)
else
- res:push(self:getFirstInMulti(value))
+ values:push(self:getFirstInMulti(value))
end
else
- res:push(value)
+ values:push(value)
end
end
elseif list.type == '...' then
- res:merge(self:loadDots())
+ self:instantSource(list)
+ exps:push(list)
+ values:merge(self:loadDots())
else
+ self:instantSource(list)
+ exps:push(list)
local value = self:getExp(list)
if value.type == 'multi' then
value:eachValue(function (_, v)
- res:push(v)
+ values:push(v)
end)
else
- res:push(value)
+ values:push(value)
end
end
- return res
+ return values, exps
end
function mt:getFirstInMulti(multi)
@@ -456,14 +463,15 @@ function mt:getSimple(simple, max)
value = self:getFirstInMulti(value) or createValue('nil')
if source.type == 'call' then
- local args = self:unpackList(source)
+ local values, args = self:unpackList(source)
local func = value
if object then
- table.insert(args, 1, object)
+ table.insert(values, 1, object)
+ table.insert(args, 1, simple[i-1])
end
object = nil
source:bindCall(func, args)
- value = self:call(func, args, source) or createValue('any')
+ value = self:call(func, values, source) or createValue('any')
elseif source.type == 'index' then
source:set('parent', value)
local child = source[1]
diff --git a/server/test/completion/init.lua b/server/test/completion/init.lua
index 2dba35bc..55a71b53 100644
--- a/server/test/completion/init.lua
+++ b/server/test/completion/init.lua
@@ -405,41 +405,81 @@ collectgarbage('@')
label = 'collect',
kind = CompletionItemKind.EnumMember,
documentation = EXISTS,
+ textEdit = {
+ start = 16,
+ finish = 18,
+ newText = '"collect"',
+ },
},
{
label = 'stop',
kind = CompletionItemKind.EnumMember,
documentation = EXISTS,
+ textEdit = {
+ start = 16,
+ finish = 18,
+ newText = '"stop"',
+ },
},
{
label = 'restart',
kind = CompletionItemKind.EnumMember,
documentation = EXISTS,
+ textEdit = {
+ start = 16,
+ finish = 18,
+ newText = '"restart"',
+ },
},
{
label = 'count',
kind = CompletionItemKind.EnumMember,
documentation = EXISTS,
+ textEdit = {
+ start = 16,
+ finish = 18,
+ newText = '"count"',
+ },
},
{
label = 'step',
kind = CompletionItemKind.EnumMember,
documentation = EXISTS,
+ textEdit = {
+ start = 16,
+ finish = 18,
+ newText = '"step"',
+ },
},
{
label = 'setpause',
kind = CompletionItemKind.EnumMember,
documentation = EXISTS,
+ textEdit = {
+ start = 16,
+ finish = 18,
+ newText = '"setpause"',
+ },
},
{
label = 'setstepmul',
kind = CompletionItemKind.EnumMember,
documentation = EXISTS,
+ textEdit = {
+ start = 16,
+ finish = 18,
+ newText = '"setstepmul"',
+ },
},
{
label = 'isrunning',
kind = CompletionItemKind.EnumMember,
documentation = EXISTS,
+ textEdit = {
+ start = 16,
+ finish = 18,
+ newText = '"isrunning"',
+ },
},
}