diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2021-08-04 19:51:05 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2021-08-04 19:51:05 +0800 |
commit | 6813f8ae58c3453d8cb0923360b1d4be532a45c6 (patch) | |
tree | f973f3256988e0ccff9a32f5957a9bae5c78bc87 | |
parent | 0e79406678f54e1ffc8ee9d09810fba8f8124815 (diff) | |
download | lua-language-server-6813f8ae58c3453d8cb0923360b1d4be532a45c6.zip |
improve
-rw-r--r-- | script/core/searcher.lua | 198 | ||||
-rw-r--r-- | test.lua | 2 |
2 files changed, 123 insertions, 77 deletions
diff --git a/script/core/searcher.lua b/script/core/searcher.lua index 470490ac..9ac8f0a8 100644 --- a/script/core/searcher.lua +++ b/script/core/searcher.lua @@ -13,7 +13,6 @@ local TEST = TEST local log = log local select = select local tostring = tostring -local ipairs = ipairs local next = next local error = error local type = type @@ -23,6 +22,31 @@ local ssub = string.sub local sfind = string.find local sformat = string.format +local getUri = guide.getUri +local getRoot = guide.getRoot + +local getNoders = noder.getNoders +local getID = noder.getID +local getLastID = noder.getLastID +local removeID = noder.removeID +local getNodersByUri = noder.getNodersByUri +local getFirstID = noder.getFirstID +local getHeadID = noder.getHeadID +local eachForward = noder.eachForward +local getUriAndID = noder.getUriAndID +local eachBackward = noder.eachBackward +local eachSource = noder.eachSource +local compileNodes = noder.compileNodes + +local SPLIT_CHAR = noder.SPLIT_CHAR +local RETURN_INDEX = noder.RETURN_INDEX +local TABLE_KEY = noder.TABLE_KEY +local STRING_CHAR = noder.STRING_CHAR +local STRING_FIELD = noder.STRING_FIELD +local WEAK_TABLE_KEY = noder.WEAK_TABLE_KEY +local ANY_FIELD = noder.ANY_FIELD +local WEAK_ANY_FIELD = noder.WEAK_ANY_FIELD + _ENV = nil local ignoredSources = { @@ -138,7 +162,7 @@ local pushRefResultsMap = util.switch() ---@param mode guide.searchmode ---@param source parser.guide.object ---@param force boolean -function m.pushResult(status, mode, source, force) +local function pushResult(status, mode, source, force) if not source then return end @@ -169,7 +193,7 @@ function m.pushResult(status, mode, source, force) local parent = source.parent if parent.type == 'return' then - if noder.getID(source) ~= status.id then + if getID(source) ~= status.id then results[#results+1] = source return end @@ -183,7 +207,7 @@ function m.getUri(obj) if obj.uri then return obj.uri end - local root = guide.getRoot(obj) + local root = getRoot(obj) if root then return root.uri end @@ -279,9 +303,11 @@ local function checkCache(status, uri, expect, mode) fileCache = {} cache[uri] = fileCache end - if fileCache[expect] then - for _, res in ipairs(fileCache[expect]) do - m.pushResult(status, mode, res, true) + local results = fileCache[expect] + if results then + for i = 1, #results do + local res = results[i] + pushResult(status, mode, res, true) end return true end @@ -325,7 +351,7 @@ local function checkSLock(status, slock, id, field) cmark[field or ''] = true local right = '' while field and field ~= '' do - local lastID = noder.getLastID(field) + local lastID = getLastID(field) if not lastID then break end @@ -342,7 +368,7 @@ local function isCallID(field) if not field then return false end - if ssub(field, 1, 2) == noder.RETURN_INDEX then + if ssub(field, 1, 2) == RETURN_INDEX then return true end return false @@ -357,11 +383,13 @@ local genercCache = { local function flushGeneric() --清除来自泛型的临时对象 for _, closure in next, genercCache.closureCache do - local noders = noder.getNoders(closure) - noder.removeID(noders, noder.getID(closure)) + local noders = getNoders(closure) + removeID(noders, getID(closure)) if closure then - for _, value in ipairs(closure.values) do - noder.removeID(noders, noder.getID(value)) + local values = closure.values + for i = 1, #values do + local value = values[i] + removeID(noders, getID(value)) end end end @@ -377,7 +405,7 @@ files.watch(function (ev) end) local nodersMapMT = {__index = function (self, uri) - local noders = noder.getNodersByUri(uri) + local noders = getNodersByUri(uri) self[uri] = noders return noders end} @@ -414,7 +442,7 @@ function m.searchRefsByID(status, furi, expect, mode) end ids[id] = true end - local firstID = noder.getFirstID(id) + local firstID = getFirstID(id) if ignoredIDs[firstID] and (field or firstID ~= id) then return end @@ -441,7 +469,7 @@ function m.searchRefsByID(status, furi, expect, mode) local rightID while true do - local firstID = noder.getHeadID(rightID or id) + local firstID = getHeadID(rightID or id) if not firstID or firstID == id then return end @@ -503,13 +531,15 @@ function m.searchRefsByID(status, furi, expect, mode) return end - if call.args then - for _, arg in ipairs(call.args) do + local args = call.args + if args then + for i = 1, #args do + local arg = args[i] genericCallArgs[arg] = true end end - local cacheID = uri .. noder.getID(source) .. noder.getID(call) + local cacheID = uri .. getID(source) .. getID(call) local closure = closureCache[cacheID] if closure == false then genercCache.mark[call] = false @@ -523,7 +553,7 @@ function m.searchRefsByID(status, furi, expect, mode) return end end - id = noder.getID(closure) + id = getID(closure) genercCache.mark[call] = id searchID(uri, id, field) end @@ -642,15 +672,15 @@ function m.searchRefsByID(status, furi, expect, mode) end local function checkForward(uri, id, field) - for forwardID, info in noder.eachForward(nodersMap[uri], id) do + for forwardID, info in eachForward(nodersMap[uri], id) do if info and not checkInfoBeforeForward(uri, forwardID, field, info) then goto CONTINUE end if not checkInfoFilter(forwardID, field, info) then goto CONTINUE end - local targetUri, targetID = noder.getUriAndID(forwardID) - if targetUri and not files.eq(targetUri, uri) then + local targetUri, targetID = getUriAndID(forwardID) + if targetUri and targetUri ~= uri then crossSearch(status, targetUri, targetID .. (field or ''), mode, uri) else searchID(uri, targetID or forwardID, field) @@ -697,15 +727,15 @@ function m.searchRefsByID(status, furi, expect, mode) if mode ~= 'ref' and mode ~= 'field' and mode ~= 'allref' and not field then return end - for backwardID, info in noder.eachBackward(nodersMap[uri], id) do + for backwardID, info in eachBackward(nodersMap[uri], id) do if info and not checkInfoBeforeBackward(uri, backwardID, field, info) then goto CONTINUE end if not checkInfoFilter(backwardID, field, info) then goto CONTINUE end - local targetUri, targetID = noder.getUriAndID(backwardID) - if targetUri and not files.eq(targetUri, uri) then + local targetUri, targetID = getUriAndID(backwardID) + if targetUri and targetUri ~= uri then crossSearch(status, targetUri, targetID .. (field or ''), mode, uri) else searchID(uri, targetID or backwardID, field) @@ -736,8 +766,9 @@ function m.searchRefsByID(status, furi, expect, mode) local tid = 'mainreturn' .. (field or '') local uris = ws.findUrisByRequirePath(requireName) footprint(status, 'require:', requireName) - for _, ruri in ipairs(uris) do - if not files.eq(uri, ruri) then + for i = 1, #uris do + local ruri = uris[i] + if uri ~= ruri then crossSearch(status, ruri, tid, mode, uri) end end @@ -758,7 +789,7 @@ function m.searchRefsByID(status, furi, expect, mode) or mode == 'field' or field then for _, guri in collector.each('def:' .. id) do - if files.eq(uri, guri) then + if uri == guri then goto CONTINUE end crossSearch(status, guri, tid, mode, uri) @@ -772,7 +803,7 @@ function m.searchRefsByID(status, furi, expect, mode) if mode == 'def' or mode == 'alldef' or mode == 'field' then goto CONTINUE end - if files.eq(uri, guri) then + if uri == guri then goto CONTINUE end crossSearch(status, guri, tid, mode, uri) @@ -795,7 +826,7 @@ function m.searchRefsByID(status, furi, expect, mode) sid = 'def:' .. sid end for _, guri in collector.each(sid) do - if not files.eq(uri, guri) then + if uri ~= guri then crossSearch(status, guri, tid, mode, uri) end end @@ -806,10 +837,11 @@ function m.searchRefsByID(status, furi, expect, mode) return end local calls = vm.getLinksTo(uri) - for _, call in ipairs(calls) do - local curi = guide.getUri(call) - local cid = noder.getID(call) .. (field or '') - if not files.eq(curi, uri) then + for i = 1, #calls do + local call = calls[i] + local curi = getUri(call) + local cid = getID(call) .. (field or '') + if curi ~= uri then crossSearch(status, curi, cid, mode, uri) end end @@ -845,9 +877,9 @@ function m.searchRefsByID(status, furi, expect, mode) callStack[#callStack+1] = call if field == nil and not ignoredSources[id] then - for source in noder.eachSource(noders, id) do + for source in eachSource(noders, id) do local force = genericCallArgs[source] - m.pushResult(status, mode, source, force) + pushResult(status, mode, source, force) end end @@ -887,31 +919,31 @@ function m.searchRefsByID(status, furi, expect, mode) if mode == 'ref' or mode == 'allref' then return end - local lastID = noder.getLastID(id) + local lastID = getLastID(id) if not lastID then return end local originField = ssub(id, #lastID + 1) - if originField == noder.TABLE_KEY - or originField == noder.WEAK_TABLE_KEY then + if originField == TABLE_KEY + or originField == WEAK_TABLE_KEY then return end - local anyFieldID = lastID .. noder.ANY_FIELD + local anyFieldID = lastID .. ANY_FIELD searchNode(uri, anyFieldID, field) end local function searchWeak(uri, id, field) - local lastID = noder.getLastID(id) + local lastID = getLastID(id) if not lastID then return end local originField = ssub(id, #lastID + 1) - if originField == noder.WEAK_TABLE_KEY then - local newID = lastID .. noder.TABLE_KEY + if originField == WEAK_TABLE_KEY then + local newID = lastID .. TABLE_KEY searchNode(uri, newID, field) end - if originField == noder.WEAK_ANY_FIELD then - local newID = lastID .. noder.ANY_FIELD + if originField == WEAK_ANY_FIELD then + local newID = lastID .. ANY_FIELD searchNode(uri, newID, field) end end @@ -958,44 +990,56 @@ local function prepareSearch(source) if not source then return end - local root = guide.getRoot(source) + local root = getRoot(source) if not root then return end - noder.compileNodes(root) - local uri = guide.getUri(source) - local id = noder.getID(source) + compileNodes(root) + local uri = getUri(source) + local id = getID(source) return uri, id end +local fieldNextTypeMap = util.switch() + : case 'getmethod' + : case 'setmethod' + : case 'getfield' + : case 'setfield' + : case 'getindex' + : case 'setindex' + : call(pushResult) + : getMap() + local function getField(status, source, mode) if source.type == 'table' then - for _, field in ipairs(source) do - m.pushResult(status, mode, field) + for i = 1, #source do + local field = source[i] + pushResult(status, mode, field) end return end if source.type == 'doc.type.ltable' then - for _, field in ipairs(source.fields) do - m.pushResult(status, mode, field) + local fields = source.fields + for i = 1, #fields do + local field = fields[i] + pushResult(status, mode, field) end end if source.type == 'doc.class.name' then - local class = source.parent - for _, field in ipairs(class.fields) do - m.pushResult(status, mode, field.field) + local class = source.parent + local fields = class.fields + for i = 1, #fields do + local field = fields[i] + pushResult(status, mode, field.field) end return end local field = source.next if field then - if field.type == 'getmethod' - or field.type == 'setmethod' - or field.type == 'getfield' - or field.type == 'setfield' - or field.type == 'getindex' - or field.type == 'setindex' then - m.pushResult(status, mode, field) + local ftype = field.type + local pushResultOrNil = fieldNextTypeMap[ftype] + if pushResultOrNil then + pushResultOrNil(status, mode, field) end return end @@ -1007,18 +1051,18 @@ local function searchAllGlobalByUri(status, mode, uri, fullID) return end local root = ast.ast - noder.compileNodes(root) - local noders = noder.getNoders(root) + compileNodes(root) + local noders = getNoders(root) if fullID then - for source in noder.eachSource(noders, fullID) do - m.pushResult(status, mode, source) + for source in eachSource(noders, fullID) do + pushResult(status, mode, source) end else for id in next, noders.source do if ssub(id, 1, 2) == 'g:' - and not sfind(id, noder.SPLIT_CHAR) then - for source in noder.eachSource(noders, id) do - m.pushResult(status, mode, source) + and not sfind(id, SPLIT_CHAR) then + for source in eachSource(noders, id) do + pushResult(status, mode, source) end end end @@ -1042,7 +1086,7 @@ function m.findGlobals(uri, mode, name) if name then local fullID if type(name) == 'string' then - fullID = sformat('%s%s%s', 'g:', noder.STRING_CHAR, name) + fullID = sformat('%s%s%s', 'g:', STRING_CHAR, name) else fullID = sformat('%s%s%s', 'g:', '', name) end @@ -1105,7 +1149,9 @@ function m.searchFields(status, source, mode, field) end local newStatus = m.status('field') m.searchRefsByID(newStatus, uri, id, 'field') - for _, def in ipairs(newStatus.results) do + local results = newStatus.results + for i = 1, #results do + local def = results[i] getField(status, def, mode) end makeCache() @@ -1114,7 +1160,7 @@ function m.searchFields(status, source, mode, field) if source.special == '_G' then local fullID if type(field) == 'string' then - fullID = sformat('%s%s%s', 'g:', noder.STRING_CHAR, field) + fullID = sformat('%s%s%s', 'g:', STRING_CHAR, field) else fullID = sformat('%s%s%s', 'g:', '', field) end @@ -1127,9 +1173,9 @@ function m.searchFields(status, source, mode, field) else local fullID if type(field) == 'string' then - fullID = sformat('%s%s%s', id, noder.STRING_FIELD, field) + fullID = sformat('%s%s%s', id, STRING_FIELD, field) else - fullID = sformat('%s%s%s', id, noder.SPLIT_CHAR, field) + fullID = sformat('%s%s%s', id, SPLIT_CHAR, field) end local cahced, makeCache = checkCache(status, uri, fullID, mode) if cahced then @@ -91,7 +91,7 @@ local function main() --config.Lua.intelliSense.searchDepth = 5 --loadDocMetas() - test 'full';do return end + --test 'full';do return end require 'bee.platform'.OS = 'Windows' testAll() |