diff options
author | sumneko <sumneko@hotmail.com> | 2022-03-12 03:58:08 +0800 |
---|---|---|
committer | sumneko <sumneko@hotmail.com> | 2022-03-12 03:58:08 +0800 |
commit | a4baf8a43b0b25414d8fe08cb898e150d420e705 (patch) | |
tree | 58d562463229b5a42659027e6d47bafab3005e8b | |
parent | 7baee6a3d54dc7cb94fb9db95d01244a17f126f6 (diff) | |
download | lua-language-server-a4baf8a43b0b25414d8fe08cb898e150d420e705.zip |
update
-rw-r--r-- | script/vm/compiler.lua | 71 | ||||
-rw-r--r-- | script/vm/value.lua | 33 | ||||
-rw-r--r-- | test/type_inference/init.lua | 23 |
3 files changed, 95 insertions, 32 deletions
diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua index 4427a66c..c46519fd 100644 --- a/script/vm/compiler.lua +++ b/script/vm/compiler.lua @@ -407,6 +407,48 @@ local function selectNode(source, list, index) return nodeMgr.setNode(source, result) end +local function setCallBackNode(source, call, callNode, fixIndex) + local valueMgr = require 'vm.value' + local myIndex + for i, arg in ipairs(call.args) do + if arg == source then + myIndex = i - fixIndex + break + end + end + local eventIndex = 1 + local eventArg = call.args[eventIndex + fixIndex] + if eventArg and eventArg.dummy then + eventIndex = 2 + eventArg = call.args[eventIndex + fixIndex] + end + local eventMap = valueMgr.getLiterals(eventArg) + for n in nodeMgr.eachNode(callNode) do + if n.type == 'function' then + local arg = n.args[myIndex] + for fn in nodeMgr.eachNode(m.compileNode(arg)) do + if fn.type == 'doc.type.function' then + nodeMgr.setNode(source, fn) + end + end + end + if n.type == 'doc.type.function' then + local event = m.compileNode(n.args[eventIndex]) + if not event + or not eventMap + or event.type ~= 'doc.type.enum' + or eventMap[event[1]] then + local arg = n.args[myIndex] + for fn in nodeMgr.eachNode(m.compileNode(arg)) do + if fn.type == 'doc.type.function' then + nodeMgr.setNode(source, fn) + end + end + end + end + end +end + local compilerMap = util.switch() : case 'nil' : case 'boolean' @@ -437,36 +479,13 @@ local compilerMap = util.switch() if source.parent.type == 'callargs' then local call = source.parent.parent local callNode = m.compileNode(call.node) - for n in nodeMgr.eachNode(callNode) do - if n.type == 'function' then - for index, arg in ipairs(n.args) do - if call.args[index] == source then - for fn in nodeMgr.eachNode(m.compileNode(arg)) do - if fn.type == 'doc.type.function' then - nodeMgr.setNode(source, fn) - end - end - end - end - end - end + setCallBackNode(source, call, callNode, 0) + if call.node.special == 'pcall' or call.node.special == 'xpcall' then local fixIndex = call.node.special == 'pcall' and 1 or 2 callNode = m.compileNode(call.args[1]) - for n in nodeMgr.eachNode(callNode) do - if n.type == 'function' then - for index, arg in ipairs(n.args) do - if call.args[index + fixIndex] == source then - for fn in nodeMgr.eachNode(m.compileNode(arg)) do - if fn.type == 'doc.type.function' then - nodeMgr.setNode(source, fn) - end - end - end - end - end - end + setCallBackNode(source, call, callNode, fixIndex) end end end) diff --git a/script/vm/value.lua b/script/vm/value.lua index 43c5d4bd..549cee02 100644 --- a/script/vm/value.lua +++ b/script/vm/value.lua @@ -191,4 +191,37 @@ function m.getBoolean(v) return result end +---@param v vm.node +---@return table<any, boolean>? +function m.getLiterals(v) + local map + local node = compiler.compileNode(v) + for n in nodeMgr.eachNode(node) do + local literal + if n.type == 'boolean' + or n.type == 'string' + or n.type == 'number' + or n.type == 'integer' then + literal = n[1] + end + if n.type == 'global' and n.cate == 'type' then + if n.name == 'true' then + literal = true + elseif n.name == 'false' then + literal = false + end + end + if n.type == 'doc.type.integer' then + literal = n[1] + end + if literal ~= nil then + if not map then + map = {} + end + map[literal] = true + end + end + return map +end + return m diff --git a/test/type_inference/init.lua b/test/type_inference/init.lua index e253cba5..7d3e3280 100644 --- a/test/type_inference/init.lua +++ b/test/type_inference/init.lua @@ -423,7 +423,7 @@ local <?x?> ]] TEST '"enum1"|"enum2"' [[ ----@type '"enum1"' | '"enum2"' +---@type 'enum1' | 'enum2' local <?x?> ]] @@ -544,7 +544,7 @@ print(t.<?a?>) ]] TEST '"aaa"|"bbb"' [[ ----@type table<string, '"aaa"'|'"bbb"'> +---@type table<string, 'aaa'|'bbb'> local t = {} print(t.<?a?>) @@ -1158,11 +1158,22 @@ end --f = function (<?x?>) end --]] +TEST 'fun(i: integer)' [[ +--- @class Emit +--- @field on fun(eventName: string, cb: function) +--- @field on fun(eventName: 'died', cb: fun(i: integer)) +--- @field on fun(eventName: 'won', cb: fun(s: string)) +local emit = {} + +emit.on("died", <?function?> (i) +end) +]] + TEST 'integer' [[ --- @class Emit --- @field on fun(eventName: string, cb: function) ---- @field on fun(eventName: '"died"', cb: fun(i: integer)) ---- @field on fun(eventName: '"won"', cb: fun(s: string)) +--- @field on fun(eventName: 'died', cb: fun(i: integer)) +--- @field on fun(eventName: 'won', cb: fun(s: string)) local emit = {} emit.on("died", function (<?i?>) @@ -1172,8 +1183,8 @@ end) TEST 'integer' [[ --- @class Emit --- @field on fun(self: Emit, eventName: string, cb: function) ---- @field on fun(self: Emit, eventName: '"died"', cb: fun(i: integer)) ---- @field on fun(self: Emit, eventName: '"won"', cb: fun(s: string)) +--- @field on fun(self: Emit, eventName: 'died', cb: fun(i: integer)) +--- @field on fun(self: Emit, eventName: 'won', cb: fun(s: string)) local emit = {} emit:on("died", function (<?i?>) |