summaryrefslogtreecommitdiff
path: root/script-beta/parser/guide.lua
diff options
context:
space:
mode:
Diffstat (limited to 'script-beta/parser/guide.lua')
-rw-r--r--script-beta/parser/guide.lua228
1 files changed, 120 insertions, 108 deletions
diff --git a/script-beta/parser/guide.lua b/script-beta/parser/guide.lua
index a4a7291a..db3696ba 100644
--- a/script-beta/parser/guide.lua
+++ b/script-beta/parser/guide.lua
@@ -927,48 +927,6 @@ local function stepRefOfLabel(label, mode)
return results
end
-local function getRefsByName(refs, name)
- if not refs then
- return nil
- end
- if #refs <= 100 then
- return refs
- else
- if not refs.cache then
- local cache = {}
- refs.cache = cache
- for i = 1, #refs do
- local ref = refs[i]
- local key = m.getSimpleName(ref)
- if not cache[key] then
- cache[key] = {}
- end
- cache[key][#cache[key]+1] = ref
- end
- end
- return refs.cache[name]
- end
-end
-
-local function stepRefOfGlobal(obj, mode)
- local results = {}
- local name = m.getKeyName(obj)
- local refs = getRefsByName(obj.node and obj.node.ref, name) or {}
- for i = 1, #refs do
- local ref = refs[i]
- if m.getKeyName(ref) == name then
- if mode == 'def' then
- if obj == 'setglobal' then
- results[#results+1] = ref
- end
- else
- results[#results+1] = ref
- end
- end
- end
- return results
-end
-
local function stepRefOfDocType(status, obj, mode)
local results = {}
if obj.type == 'doc.class.name'
@@ -1011,10 +969,6 @@ function m.getStepRef(status, obj, mode)
if obj.type == 'goto' then
return stepRefOfLabel(obj.node, mode)
end
- if obj.type == 'getglobal'
- or obj.type == 'setglobal' then
- return stepRefOfGlobal(obj, mode)
- end
if obj.type == 'library' then
return { obj }
end
@@ -1076,27 +1030,47 @@ local function convertSimpleList(list)
local simple = {}
for i = #list, 1, -1 do
local c = list[i]
- if c.special == '_G'
- and c.type ~= 'getglobal'
- and c.type ~= 'setglobal' then
- simple.global = list[i+1] or c
- else
- simple[#simple+1] = m.getSimpleName(c)
- end
- if c.type == 'getglobal'
- or c.type == 'setglobal' then
- simple.global = c
- end
- if #simple <= 1 then
- if simple.global then
- simple.first = m.getENV(c, c.start)
- elseif c.type == 'setlocal'
- or c.type == 'getlocal' then
- simple.first = c.node
+ if c.type == 'getglobal'
+ or c.type == 'setglobal' then
+ if c.special == '_G' then
+ simple.mode = 'global'
+ goto CONTINUE
+ end
+ local loc = c.node
+ if loc.special == '_G' then
+ simple.mode = 'global'
+ if not simple.node then
+ simple.node = c
+ end
else
- simple.first = c
+ simple.mode = 'local'
+ simple[#simple+1] = m.getSimpleName(loc)
+ if not simple.node then
+ simple.node = loc
+ end
+ end
+ elseif c.type == 'getlocal'
+ or c.type == 'setlocal' then
+ if c.special == '_G' then
+ simple.mode = 'global'
+ goto CONTINUE
+ end
+ simple.mode = 'local'
+ if not simple.node then
+ simple.node = c.node
+ end
+ elseif c.type == 'local' then
+ simple.mode = 'local'
+ if not simple.node then
+ simple.node = c
+ end
+ else
+ if not simple.node then
+ simple.node = c
end
end
+ simple[#simple+1] = m.getSimpleName(c)
+ ::CONTINUE::
end
return simple
end
@@ -1221,6 +1195,12 @@ function m.isGlobal(source)
return true
end
end
+ if source.type == 'field' then
+ local node = source.parent.node
+ if node and node.special == '_G' then
+ return true
+ end
+ end
return false
end
@@ -1685,21 +1665,68 @@ function m.checkSameSimpleInCall(status, ref, start, queue, mode)
end
end
-function m.checkSameSimpleInGlobal(status, name, start, queue)
- if not name then
+local function searchRawset(ref, results)
+ if m.getKeyName(ref) ~= 's|rawset' then
+ return
+ end
+ local call = ref.parent
+ if call.type ~= 'call' or call.node ~= ref then
+ return
+ end
+ if not call.args then
+ return
+ end
+ local arg1 = call.args[1]
+ if arg1.special ~= '_G' then
+ -- 不会吧不会吧,不会真的有人写成 `rawset(_G._G._G, 'xxx', value)` 吧
return
end
- if not status.interface.global then
+ results[#results+1] = call
+end
+
+local function searchG(ref, results)
+ while ref and m.getKeyName(ref) == 's|_G' do
+ results[#results+1] = ref
+ ref = ref.next
+ end
+ if ref then
+ results[#results+1] = ref
+ searchRawset(ref, results)
+ end
+end
+
+local function searchEnvRef(ref, results)
+ if ref.type == 'setglobal'
+ or ref.type == 'getglobal' then
+ results[#results+1] = ref
+ searchG(ref, results)
+ elseif ref.type == 'getlocal' then
+ results[#results+1] = ref.next
+ searchG(ref.next, results)
+ end
+end
+
+function m.findGlobals(ast)
+ local results = {}
+ local env = m.getENV(ast)
+ if env.ref then
+ for _, ref in ipairs(env.ref) do
+ searchEnvRef(ref, results)
+ end
+ end
+ return results
+end
+
+function m.checkSameSimpleInGlobal(status, name, source, start, queue)
+ if not name then
return
end
- --if not status.cache.globalMark then
- -- status.cache.globalMark = {}
- --end
- --if status.cache.globalMark[name] then
- -- return
- --end
- --status.cache.globalMark[name] = true
- local objs = status.interface.global(name)
+ local objs
+ if status.interface.global then
+ objs = status.interface.global(name)
+ else
+ objs = m.findGlobals(m.getRoot(source))
+ end
if objs then
for _, obj in ipairs(objs) do
queue[#queue+1] = {
@@ -1900,7 +1927,7 @@ function m.pushResult(status, mode, ref, simple)
results[#results+1] = ref
end
if ref.parent and ref.parent.type == 'return' then
- if m.getParentFunction(ref) ~= m.getParentFunction(simple.first) then
+ if m.getParentFunction(ref) ~= m.getParentFunction(simple.node) then
results[#results+1] = ref
end
end
@@ -1973,7 +2000,7 @@ function m.pushResult(status, mode, ref, simple)
end
end
-function m.checkSameSimple(status, simple, data, mode, results, queue)
+function m.checkSameSimple(status, simple, data, mode, queue)
local ref = data.obj
local start = data.start
local force = data.force
@@ -2030,44 +2057,28 @@ function m.checkSameSimple(status, simple, data, mode, results, queue)
end
function m.searchSameFields(status, simple, mode)
- local first = simple.first
- if not first then
- return
- end
- local refs = getRefsByName(first.ref, m.getSimpleName(simple.global or first)) or {}
local queue = {}
- for i = 1, #refs do
- queue[i] = {
- obj = refs[i],
+ if simple.mode == 'global' then
+ -- 全局变量开头
+ m.checkSameSimpleInGlobal(status, simple[1], simple.node, 1, queue)
+ elseif simple.mode == 'local' then
+ -- 局部变量开头
+ queue[1] = {
+ obj = simple.node,
start = 1,
}
- end
- -- 对初始对象进行预处理
- if simple.global then
- for i = 1, #queue do
- local data = queue[i]
- local obj = data.obj
- local nxt = m.getNextRef(obj)
- if nxt and obj.special == '_G' then
- data.obj = nxt
- end
- end
- if first then
- if first.tag == '_ENV' then
- -- 检查全局变量的分支情况,需要业务层传入 interface.global
- m.checkSameSimpleInGlobal(status, simple[1], 1, queue)
- else
- simple.global = nil
- tableInsert(simple, 1, 'l|_ENV')
+ local refs = simple.node.ref
+ if refs then
+ for i = 1, #refs do
queue[#queue+1] = {
- obj = first,
+ obj = refs[i],
start = 1,
}
end
end
else
- queue[#queue+1] = {
- obj = first,
+ queue[1] = {
+ obj = simple.node,
start = 1,
}
end
@@ -2081,7 +2092,7 @@ function m.searchSameFields(status, simple, mode)
status.lock[data.obj] = true
max = max + 1
status.cache.count = status.cache.count + 1
- m.checkSameSimple(status, simple, data, mode, status.results, queue)
+ m.checkSameSimple(status, simple, data, mode, queue)
if max >= 10000 then
logWarn('Queue too large!')
break
@@ -2193,7 +2204,8 @@ function m.searchRefsAsFunctionSet(status, obj, mode)
end
function m.searchRefsAsFunction(status, obj, mode)
- if obj.type ~= 'function' then
+ if obj.type ~= 'function'
+ and obj.type ~= 'table' then
return
end
m.searchRefsAsFunctionSet(status, obj, mode)