diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2022-10-11 21:08:12 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2022-10-11 21:08:12 +0800 |
commit | 896a1affdeed8304688611674df88140a5cc180e (patch) | |
tree | b9336e9c8d4ea52cf4b6f1aa54d341e1edad305f /script/vm | |
parent | e1912470260bac17e7efc565cb59719beb810d01 (diff) | |
download | lua-language-server-896a1affdeed8304688611674df88140a5cc180e.zip |
infer definitions and types across chain exp
resolve #1561
Diffstat (limited to 'script/vm')
-rw-r--r-- | script/vm/compiler.lua | 79 | ||||
-rw-r--r-- | script/vm/def.lua | 125 |
2 files changed, 80 insertions, 124 deletions
diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua index 05ad0634..61838775 100644 --- a/script/vm/compiler.lua +++ b/script/vm/compiler.lua @@ -1818,6 +1818,84 @@ local function compileByGlobal(source) end end +local nodeSwitch;nodeSwitch = util.switch() + : case 'field' + : case 'method' + : call(function (source, lastKey, pushResult) + return nodeSwitch(source.parent.type, source.parent, lastKey, pushResult) + end) + : case 'getfield' + : case 'setfield' + : case 'getmethod' + : case 'setmethod' + : case 'getindex' + : case 'setindex' + : call(function (source, lastKey, pushResult) + local parentNode = vm.compileNode(source.node) + local uri = guide.getUri(source) + local key = guide.getKeyName(source) + if type(key) ~= 'string' then + return + end + if lastKey then + key = key .. vm.ID_SPLITE .. lastKey + end + for pn in parentNode:eachObject() do + searchFieldSwitch(pn.type, uri, pn, key, false, pushResult) + end + return key, source.node + end) + : case 'tableindex' + : case 'tablefield' + : call(function (source, lastKey, pushResult) + if lastKey then + return + end + local key = guide.getKeyName(source) + if type(key) ~= 'string' then + return + end + local uri = guide.getUri(source) + local parentNode = vm.compileNode(source.node) + for pn in parentNode:eachObject() do + searchFieldSwitch(pn.type, uri, pn, key, false, pushResult) + end + end) + : case 'doc.see.field' + : call(function (source, lastKey, pushResult) + if lastKey then + return + end + local parentNode = vm.compileNode(source.parent.name) + local uri = guide.getUri(source) + for pn in parentNode:eachObject() do + searchFieldSwitch(pn.type, uri, pn, source[1], false, pushResult) + end + end) + +function vm.compileByNodeChain(source, pushResult) + local lastKey + local src = source + while true do + local key, node = nodeSwitch(src.type, src, lastKey, pushResult) + if not key then + break + end + src = node + lastKey = key + end +end + +---@param source vm.object +local function compileByParentNode(source) + if not vm.getNode(source):isEmpty() then + return + end + vm.compileByNodeChain(source, function (result) + vm.setNode(source, vm.compileNode(result)) + end) +end + ---@param source vm.object ---@return vm.node function vm.compileNode(source) @@ -1846,6 +1924,7 @@ function vm.compileNode(source) LOCK[source] = true compileByGlobal(source) compileByNode(source) + compileByParentNode(source) matchCall(source) LOCK[source] = nil diff --git a/script/vm/def.lua b/script/vm/def.lua index f557f221..7ce8ad7a 100644 --- a/script/vm/def.lua +++ b/script/vm/def.lua @@ -20,110 +20,6 @@ simpleSwitch = util.switch() end end) -local searchFieldSwitch = util.switch() - : case 'table' - : call(function (suri, obj, key, pushResult) - for _, field in ipairs(obj) do - if field.type == 'tablefield' - or field.type == 'tableindex' then - if guide.getKeyName(field) == key then - pushResult(field) - end - end - end - end) - : case 'global' - ---@param obj vm.global - ---@param key string - : call(function (suri, obj, key, pushResult) - if obj.cate == 'variable' then - local newGlobal = vm.getGlobal('variable', obj.name, key) - if newGlobal then - for _, set in ipairs(newGlobal:getSets(suri)) do - pushResult(set) - end - end - end - if obj.cate == 'type' then - vm.getClassFields(suri, obj, key, false, pushResult) - end - end) - : case 'local' - : call(function (suri, obj, key, pushResult) - local sources = vm.getLocalSourcesSets(obj, key) - if sources then - for _, src in ipairs(sources) do - pushResult(src) - end - end - end) - : case 'doc.type.table' - : call(function (suri, obj, key, pushResult) - for _, field in ipairs(obj.fields) do - local fieldKey = field.name - if fieldKey.type == 'doc.field.name' then - if fieldKey[1] == key then - pushResult(field) - end - end - end - end) - -local nodeSwitch;nodeSwitch = util.switch() - : case 'field' - : case 'method' - : call(function (source, lastKey, pushResult) - return nodeSwitch(source.parent.type, source.parent, lastKey, pushResult) - end) - : case 'getfield' - : case 'setfield' - : case 'getmethod' - : case 'setmethod' - : case 'getindex' - : case 'setindex' - : call(function (source, lastKey, pushResult) - local parentNode = vm.compileNode(source.node) - local uri = guide.getUri(source) - local key = guide.getKeyName(source) - if type(key) ~= 'string' then - return - end - if lastKey then - key = key .. vm.ID_SPLITE .. lastKey - end - for pn in parentNode:eachObject() do - searchFieldSwitch(pn.type, uri, pn, key, pushResult) - end - return key, source.node - end) - : case 'tableindex' - : case 'tablefield' - : call(function (source, lastKey, pushResult) - if lastKey then - return - end - local key = guide.getKeyName(source) - if type(key) ~= 'string' then - return - end - local uri = guide.getUri(source) - local parentNode = vm.compileNode(source.node) - for pn in parentNode:eachObject() do - searchFieldSwitch(pn.type, uri, pn, key, pushResult) - end - end) - : case 'doc.see.field' - : call(function (source, lastKey, pushResult) - if lastKey then - return - end - local parentNode = vm.compileNode(source.parent.name) - local uri = guide.getUri(source) - for pn in parentNode:eachObject() do - searchFieldSwitch(pn.type, uri, pn, source[1], pushResult) - end - end) - ---@param source parser.object ---@param pushResult fun(src: parser.object) local function searchBySimple(source, pushResult) @@ -142,25 +38,6 @@ local function searchByLocalID(source, pushResult) end end ----@param source parser.object ----@param pushResult fun(src: parser.object) -local function searchByParentNode(source, pushResult) - local lastKey - local src = source - while true do - local key, node = nodeSwitch(src.type, src, lastKey, pushResult) - if not key then - break - end - src = node - if lastKey then - lastKey = key .. vm.ID_SPLITE .. lastKey - else - lastKey = key - end - end -end - local function searchByNode(source, pushResult) local node = vm.compileNode(source) local suri = guide.getUri(source) @@ -200,7 +77,7 @@ function vm.getDefs(source) searchBySimple(source, pushResult) searchByLocalID(source, pushResult) - searchByParentNode(source, pushResult) + vm.compileByNodeChain(source, pushResult) searchByNode(source, pushResult) return results |