summaryrefslogtreecommitdiff
path: root/server-beta/src/searcher/searcher.lua
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2019-11-04 10:27:28 +0800
committer最萌小汐 <sumneko@hotmail.com>2019-11-04 10:27:28 +0800
commita9af7f7bc869466da14ef2c4b7fb07ed589f7a09 (patch)
tree9779f0b94013c3b3a15f1ce32701e2585cea7472 /server-beta/src/searcher/searcher.lua
parent196bad7bbd13c5423035881341a15847fad5227d (diff)
downloadlua-language-server-a9af7f7bc869466da14ef2c4b7fb07ed589f7a09.zip
整理代码
Diffstat (limited to 'server-beta/src/searcher/searcher.lua')
-rw-r--r--server-beta/src/searcher/searcher.lua119
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