summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/libs/@lua/basic.lni3
-rw-r--r--server/src/vm/pcall.lua50
-rw-r--r--server/src/vm/vm.lua5
-rw-r--r--server/test/hover/init.lua40
4 files changed, 98 insertions, 0 deletions
diff --git a/server/libs/@lua/basic.lni b/server/libs/@lua/basic.lni
index 85d5d6da..333e44cd 100644
--- a/server/libs/@lua/basic.lni
+++ b/server/libs/@lua/basic.lni
@@ -346,6 +346,7 @@ type = 'table'
type = 'nil'
[pcall]
+special = pcall
[[.args]]
name = 'f'
type = 'function'
@@ -522,6 +523,7 @@ type = 'boolean'
optional = 'after'
[xpcall]
+special = xpcall
[[.args]]
name = 'f'
type = 'function'
@@ -544,6 +546,7 @@ type = '...'
['xpcall Lua 5.1']
name = 'xpcall'
version = 'Lua 5.1'
+special = xpcall
[[.args]]
name = 'f'
type = 'function'
diff --git a/server/src/vm/pcall.lua b/server/src/vm/pcall.lua
new file mode 100644
index 00000000..e5d1e26f
--- /dev/null
+++ b/server/src/vm/pcall.lua
@@ -0,0 +1,50 @@
+local mt = require 'vm.manager'
+local multi = require 'vm.multi'
+
+function mt:callPcall(func, values, source)
+ local funcValue = values:first()
+ if not funcValue then
+ return
+ end
+ local realFunc = funcValue:getFunction()
+ if not realFunc then
+ return
+ end
+ local argList = multi()
+ values:eachValue(function (i, v)
+ if i >= 2 then
+ argList:push(v)
+ end
+ end)
+ self:call(funcValue, argList, source)
+ if realFunc ~= func then
+ func:setReturn(1, self:createValue('boolean', source))
+ realFunc:getReturn():eachValue(function (i, v)
+ func:setReturn(i + 1, v)
+ end)
+ end
+end
+
+function mt:callXpcall(func, values, source)
+ local funcValue = values:first()
+ if not funcValue then
+ return
+ end
+ local realFunc = funcValue:getFunction()
+ if not realFunc then
+ return
+ end
+ local argList = multi()
+ values:eachValue(function (i, v)
+ if i >= 3 then
+ argList:push(v)
+ end
+ end)
+ self:call(funcValue, argList, source)
+ if realFunc ~= func then
+ func:setReturn(1, self:createValue('boolean', source))
+ realFunc:getReturn():eachValue(function (i, v)
+ func:setReturn(i + 1, v)
+ end)
+ end
+end
diff --git a/server/src/vm/vm.lua b/server/src/vm/vm.lua
index aafe7a10..5091a1bc 100644
--- a/server/src/vm/vm.lua
+++ b/server/src/vm/vm.lua
@@ -12,6 +12,7 @@ local mt = require 'vm.manager'
require 'vm.module'
require 'vm.raw'
+require 'vm.pcall'
-- TODO source测试
--rawset(_G, 'CachedSource', setmetatable({}, { __mode = 'kv' }))
@@ -282,6 +283,10 @@ function mt:callLibrary(func, values, source, lib)
self:callRawSet(func, values, source)
elseif lib.special == 'rawget' then
self:callRawGet(func, values, source)
+ elseif lib.special == 'pcall' then
+ self:callPcall(func, values, source)
+ elseif lib.special == 'xpcall' then
+ self:callXpcall(func, values, source)
end
else
-- 如果lib的参数中有function,则立即执行function
diff --git a/server/test/hover/init.lua b/server/test/hover/init.lua
index b144fd72..3d82777d 100644
--- a/server/test/hover/init.lua
+++ b/server/test/hover/init.lua
@@ -401,3 +401,43 @@ local sssss<utf8>: {
offset: function,
}
]]
+
+TEST[[
+function a(v)
+ print(<?v?>)
+end
+a(1)
+]]
+[[
+local v: number = 1
+]]
+
+TEST[[
+function a(v)
+ print(<?v?>)
+end
+pcall(a, 1)
+]]
+[[
+local v: number = 1
+]]
+
+TEST[[
+function a(v)
+ print(<?v?>)
+end
+xpcall(a, log.error, 1)
+]]
+[[
+local v: number = 1
+]]
+
+TEST[[
+function a(v)
+ return 'a'
+end
+local _, <?r?> = pcall(a, 1)
+]]
+[[
+local r: string = "a"
+]]