diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2019-11-04 10:27:28 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2019-11-04 10:27:28 +0800 |
commit | a9af7f7bc869466da14ef2c4b7fb07ed589f7a09 (patch) | |
tree | 9779f0b94013c3b3a15f1ce32701e2585cea7472 /server-beta/src/searcher/searcher.lua | |
parent | 196bad7bbd13c5423035881341a15847fad5227d (diff) | |
download | lua-language-server-a9af7f7bc869466da14ef2c4b7fb07ed589f7a09.zip |
整理代码
Diffstat (limited to 'server-beta/src/searcher/searcher.lua')
-rw-r--r-- | server-beta/src/searcher/searcher.lua | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/server-beta/src/searcher/searcher.lua b/server-beta/src/searcher/searcher.lua new file mode 100644 index 00000000..7fdcd39d --- /dev/null +++ b/server-beta/src/searcher/searcher.lua @@ -0,0 +1,119 @@ +local guide = require 'parser.guide' +local util = require 'utility' + +local setmetatable = setmetatable +local assert = assert + +_ENV = nil + +local specials = { + ['_G'] = true, + ['rawset'] = true, + ['rawget'] = true, + ['setmetatable'] = true, + ['require'] = true, + ['dofile'] = true, + ['loadfile'] = true, +} + +---@class searcher +local m = {} + +function m.lock(tp, source) + if m.locked[tp][source] then + return nil + end + m.locked[tp][source] = true + return util.defer(function () + m.locked[tp][source] = nil + end) +end + +--- 获取特殊对象的名字 +function m.getSpecialName(source) + local spName = m.cache.specialName[source] + if spName ~= nil then + if spName then + return spName + end + return nil + end + local function getName(src) + if src.type == 'getglobal' then + local node = src.node + if node.tag ~= '_ENV' then + return nil + end + local name = guide.getKeyName(src) + if name:sub(1, 2) ~= 's|' then + return nil + end + spName = name:sub(3) + if not specials[spName] then + spName = nil + end + elseif src.type == 'local' then + if src.tag == '_ENV' then + spName = '_G' + end + elseif src.type == 'getlocal' then + local loc = src.loc + if loc.tag == '_ENV' then + spName = '_G' + end + end + end + getName(source) + if not spName then + m.eachRef(source, function (info) + getName(info.source) + end) + end + m.cache.specialName[source] = spName or false + return spName +end + +--- 遍历特殊对象 +---@param callback fun(name:string, source:table) +function m.eachSpecial(callback) + local cache = m.cache.specials + if cache then + for i = 1, #cache do + callback(cache[i][1], cache[i][2]) + end + return + end + cache = {} + m.cache.specials = cache + guide.eachSource(m.ast, function (source) + if source.type == 'getlocal' + or source.type == 'getglobal' + or source.type == 'local' + or source.type == 'field' + or source.type == 'string' then + local name = m.getSpecialName(source) + if name then + cache[#cache+1] = { name, source } + end + end + end) + for i = 1, #cache do + callback(cache[i][1], cache[i][2]) + end +end + +--- 刷新缓存 +function m.refreshCache() + m.cache = { + eachRef = {}, + eachField = {}, + specialName = {}, + specials = nil, + } + m.locked = { + eachRef = {}, + eachField = {}, + } +end + +return m |