summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2019-06-29 15:27:38 +0800
committer最萌小汐 <sumneko@hotmail.com>2019-06-29 15:27:38 +0800
commitf0bfb047bfb81b6f11400939ad736b7267e08938 (patch)
tree2b4d706f82485164363987bc9740d0ebd92787f8 /server
parent4586d62c06751d99199044375393dc1595375491 (diff)
downloadlua-language-server-f0bfb047bfb81b6f11400939ad736b7267e08938.zip
emmyfunction 支持多返回值
Diffstat (limited to 'server')
-rw-r--r--server/meta/Lua 5.4/basic.lua62
-rw-r--r--server/meta/Lua 5.4/meta.lua17
-rw-r--r--server/src/core/hover/emmy_function.lua11
-rw-r--r--server/src/emmy/funcType.lua9
-rw-r--r--server/src/parser/ast.lua14
-rw-r--r--server/src/parser/grammar.lua11
-rw-r--r--server/src/vm/emmy.lua38
7 files changed, 121 insertions, 41 deletions
diff --git a/server/meta/Lua 5.4/basic.lua b/server/meta/Lua 5.4/basic.lua
index dcc3d580..7fa412de 100644
--- a/server/meta/Lua 5.4/basic.lua
+++ b/server/meta/Lua 5.4/basic.lua
@@ -8,17 +8,6 @@ arg = {}
---@return any
function assert(v, message) end
----@alias GCOption string
----| > '"collect"' # 做一次完整的垃圾收集循环。
----| '"stop"' # 停止垃圾收集器的运行。
----| '"restart"' # 重启垃圾收集器的自动运行。
----| '"count"' # 以 K 字节数为单位返回 Lua 使用的总内存数。
----| '"step"' # 单步运行垃圾收集器。
----| '"setpause"' # 设置收集器的 `间歇率`。
----| '"setstepmul"' # 设置收集器的 `步进倍率`。
----| '"incremental"' # 改变收集器模式为增量模式。
----| '"generational"' # 改变收集器模式为分代模式。
----| '"isrunning"' # 返回表示收集器是否在工作的布尔值。
---@overload fun()
---@overload fun(opt:GCOption):any
---@param opt GCOption {optional = 'after'}
@@ -27,14 +16,64 @@ function assert(v, message) end
function collectgarbage(opt, arg) end
--- 打开该名字的文件,并执行文件中的 Lua 代码块。
+---@overload fun():any
---@param filename string {optional = 'self', special = 'dofile:1'}
---@return any
function dofile(filename) end
+--- 中止上一次保护函数调用,将错误对象 `message` 返回。
+---@overload fun(message:any)
+---@param message any
+---@param level integer {optional = 'self'}
+function error(message, level) end
+
--- 内部储存有全局环境。
_G = {}
+--- 返回该对象的元表。
+---@param object any
+---@return table {name = 'metatable'}
+function getmetatable(object) end
+
+--- 能迭代表 `t` 中序列的键值对。
+---|```lua
+---|for i, v in ipairs(t) do
+---| -- body
+---|end
+---|```
+---@param t table
+---@return {name = 'iterator'}
+---@return table {name = 't'}
+---@return integer {name = 'i'}
+function ipairs(t)
+ --- 返回该键的下一个键及其关联的值。
+ ---@overload fun(t:table):integer,any
+ ---@param t table
+ ---@param index any {optional = 'self'}
+ ---@return integer {name = 'index'}
+ ---@return any {name = 'value'}
+ local function iterator(t, index) end
+
+ return iterator, t, nil
+end
+
+--- 加载一个代码块。
+---@overload fun():function,string
+---@overload fun(chunk:string|function):function,string
+---@overload fun(chunk:string|function, chunkname:string):function,string
+---@overload fun(chunk:string|function, chunkname:string, mode:loadOption):function,string
+---@param chunk string|function
+---@param chunkname string {optional = 'after'}
+---@param mode loadOption {optional = 'after'}
+---@param env table {optional = 'self'}
+---@return {name = 'init'}
+---@return string {name = 'errMessage', optional = 'self'}
+function load(chunk, chunkname, mode, env)
+ return function (...) end
+end
+
--- 返回该键的下一个键及其关联的值。
+---@overload fun(t:table):any, any
---@param t table
---@param index any {optional = 'self'}
---@return any {name = 'key'}
@@ -53,6 +92,7 @@ function next(t, index) end
---@return any {name = 'key'}
function pairs(t)
--- 返回该键的下一个键及其关联的值。
+ ---@overload fun(t:table):any, any
---@param t table
---@param index any {optional = 'self'}
---@return any {name = 'key'}
diff --git a/server/meta/Lua 5.4/meta.lua b/server/meta/Lua 5.4/meta.lua
index efa4dd08..4fe28af2 100644
--- a/server/meta/Lua 5.4/meta.lua
+++ b/server/meta/Lua 5.4/meta.lua
@@ -8,3 +8,20 @@
---@class nil any
---@class userdata any
---@class thread any
+
+---@alias GCOption string
+---| > '"collect"' # 做一次完整的垃圾收集循环。
+---| '"stop"' # 停止垃圾收集器的运行。
+---| '"restart"' # 重启垃圾收集器的自动运行。
+---| '"count"' # 以 K 字节数为单位返回 Lua 使用的总内存数。
+---| '"step"' # 单步运行垃圾收集器。
+---| '"setpause"' # 设置收集器的 `间歇率`。
+---| '"setstepmul"' # 设置收集器的 `步进倍率`。
+---| '"incremental"' # 改变收集器模式为增量模式。
+---| '"generational"' # 改变收集器模式为分代模式。
+---| '"isrunning"' # 返回表示收集器是否在工作的布尔值。
+
+---@alias loadOption string
+---| "'b'" # 只能是二进制代码块。
+---| "'t'" # 只能是文本代码块。
+---| > "'bt'" # 可以是二进制也可以是文本。
diff --git a/server/src/core/hover/emmy_function.lua b/server/src/core/hover/emmy_function.lua
index 313b5276..4dd89107 100644
--- a/server/src/core/hover/emmy_function.lua
+++ b/server/src/core/hover/emmy_function.lua
@@ -41,11 +41,14 @@ local function buildEmmyArgs(emmy, object, select)
end
local function buildEmmyReturns(emmy)
- local rtn = emmy:getReturn()
- if rtn then
- return '\n -> ' .. rtn:getType()
- else
+ local rtns = {}
+ emmy:eachReturn(function (rtn)
+ rtns[#rtns+1] = rtn:getType()
+ end)
+ if #rtns == 0 then
return '\n -> ' .. 'any'
+ else
+ return '\n -> ' .. table.concat(rtns, ', ')
end
end
diff --git a/server/src/emmy/funcType.lua b/server/src/emmy/funcType.lua
index f467f763..2c073fe2 100644
--- a/server/src/emmy/funcType.lua
+++ b/server/src/emmy/funcType.lua
@@ -30,7 +30,7 @@ function mt:addParam(name, type)
end
function mt:addReturn(type)
- self._return = type
+ self._returns[#self._returns+1] = type
end
function mt:eachParam(callback)
@@ -39,8 +39,10 @@ function mt:eachParam(callback)
end
end
-function mt:getReturn()
- return self._return
+function mt:eachReturn(callback)
+ for _, rtn in ipairs(self._returns) do
+ callback(rtn)
+ end
end
function mt:bindFunction(func)
@@ -55,6 +57,7 @@ return function (manager, source)
local self = setmetatable({
source = source.id,
_params = {},
+ _returns = {},
_manager = manager,
}, mt)
return self
diff --git a/server/src/parser/ast.lua b/server/src/parser/ast.lua
index b9cc9b47..f2486fd6 100644
--- a/server/src/parser/ast.lua
+++ b/server/src/parser/ast.lua
@@ -1213,16 +1213,22 @@ local Defs = {
[2] = valueType,
}
end,
- EmmyFunctionType = function (start, ...)
+ EmmyFunctionType = function (start, args, returns, finish)
local result = {
start = start,
+ finish = finish - 1,
type = 'emmyFunctionType',
- ...
+ args = args,
+ returns = returns,
}
- result.finish = result[#result] - 1
- result[#result] = nil
return result
end,
+ EmmyFunctionRtns = function (...)
+ return {...}
+ end,
+ EmmyFunctionArgs = function (...)
+ return {...}
+ end,
EmmyAlias = function (name, emmyName, ...)
return {
type = 'emmyAlias',
diff --git a/server/src/parser/grammar.lua b/server/src/parser/grammar.lua
index e0db8988..c20f5b32 100644
--- a/server/src/parser/grammar.lua
+++ b/server/src/parser/grammar.lua
@@ -593,10 +593,15 @@ EmmyArrayType <- (MustEmmyName '[]')
EmmyTableType <- ({} 'table' Cut '<' %s* EmmyType %s* ',' %s* EmmyType %s* '>' {})
-> EmmyTableType
-EmmyFunctionType<- ({} 'fun' Cut %s* EmmyFunctionArgs? %s* EmmyFunctionRtn? {})
+EmmyFunctionType<- ({} 'fun' Cut %s* EmmyFunctionArgs %s* EmmyFunctionRtns {})
-> EmmyFunctionType
-EmmyFunctionArgs<- '(' %s* EmmyFunctionArg %s* (',' %s* EmmyFunctionArg %s*)* ')'
-EmmyFunctionRtn <- ':' %s* EmmyType
+EmmyFunctionArgs<- ('(' %s* EmmyFunctionArg %s* (',' %s* EmmyFunctionArg %s*)* ')')
+ -> EmmyFunctionArgs
+ / '(' %nil ')'?
+ / %nil
+EmmyFunctionRtns<- (':' %s* EmmyType (%s* ',' %s* EmmyType)*)
+ -> EmmyFunctionRtns
+ / %nil
EmmyFunctionArg <- MustEmmyName %s* ':' %s* EmmyType
EmmySee <- {} MustEmmyName %s* '#' %s* MustEmmyName {}
diff --git a/server/src/vm/emmy.lua b/server/src/vm/emmy.lua
index 8625442b..5a15d3b0 100644
--- a/server/src/vm/emmy.lua
+++ b/server/src/vm/emmy.lua
@@ -299,23 +299,29 @@ function mt:buildEmmyFunctionType(source)
local funcObj = emmyMgr:addFunctionType(source)
---@type emmyFunction
local func = functionMgr.create(source)
- for i = 1, #source // 2 do
- local nameSource = source[i*2-1]
- local typeSource = source[i*2]
- local paramType = self:buildEmmyAnyType(typeSource)
- funcObj:addParam(nameSource[1], paramType)
- local value = self:createValue(paramType:getType(), typeSource)
- value:setEmmy(paramType)
- self:instantSource(nameSource)
- func:addArg(nameSource[1], nameSource, value)
+ local args = source.args
+ if args then
+ for i = 1, #args // 2 do
+ local nameSource = args[i*2-1]
+ local typeSource = args[i*2]
+ local paramType = self:buildEmmyAnyType(typeSource)
+ funcObj:addParam(nameSource[1], paramType)
+ local value = self:createValue(paramType:getType(), typeSource)
+ value:setEmmy(paramType)
+ self:instantSource(nameSource)
+ func:addArg(nameSource[1], nameSource, value)
+ end
end
- local returnSource = source[#source]
- if returnSource then
- local returnType = self:buildEmmyAnyType(returnSource)
- funcObj:addReturn(returnType)
- local value = self:createValue(returnType:getType(), returnSource)
- value:setEmmy(returnType)
- func:setReturn(1, value)
+ local returns = source.returns
+ if returns then
+ for i = 1, #returns do
+ local returnSource = returns[i]
+ local returnType = self:buildEmmyAnyType(returnSource)
+ funcObj:addReturn(returnType)
+ local value = self:createValue(returnType:getType(), returnSource)
+ value:setEmmy(returnType)
+ func:setReturn(i, value)
+ end
end
funcObj:bindFunction(func)
return funcObj