1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
local guide = require 'parser.guide'
local vm = require 'vm.vm'
local files = require 'files'
local library = require 'library'
local util = require 'utility'
local config = require 'config'
local function searchRawset(ref, results)
if guide.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
results[#results+1] = call
end
local function searchG(ref, results)
while ref and guide.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
local function getGlobalsOfFile(uri)
local globals = {}
local ast = files.getAst(uri)
if not ast then
return globals
end
local results = {}
local env = guide.getENV(ast.ast)
if env.ref then
for _, ref in ipairs(env.ref) do
searchEnvRef(ref, results)
end
end
local mark = {}
for _, res in ipairs(results) do
if mark[res] then
goto CONTINUE
end
mark[res] = true
local name = guide.getSimpleName(res)
if name then
if not globals[name] then
globals[name] = {}
end
globals[name][#globals[name]+1] = res
end
::CONTINUE::
end
return globals
end
local function insertLibrary(results, name)
if name:sub(1, 2) == 's|' then
local libname = name:sub(3)
results[#results+1] = library.global[libname]
local asName = config.config.runtime.special[libname]
results[#results+1] = library.global[asName]
end
end
local function getGlobals(name)
local results = {}
for uri in files.eachFile() do
local cache = files.getCache(uri)
cache.globals = cache.globals or getGlobalsOfFile(uri)
if name == '*' then
for _, sources in util.sortPairs(cache.globals) do
for _, source in ipairs(sources) do
results[#results+1] = source
end
end
else
if cache.globals[name] then
for _, source in ipairs(cache.globals[name]) do
results[#results+1] = source
end
end
end
end
insertLibrary(results, name)
return results
end
function vm.getGlobals(name)
local cache = vm.getCache('getGlobals')[name]
if cache ~= nil then
return cache
end
cache = getGlobals(name)
vm.getCache('getGlobals')[name] = cache
return cache
end
function vm.getGlobalSets(name)
local cache = vm.getCache('getGlobalSets')[name]
if cache ~= nil then
return cache
end
cache = {}
local refs = getGlobals(name)
for _, source in ipairs(refs) do
if vm.isSet(source) then
cache[#cache+1] = source
end
end
vm.getCache('getGlobalSets')[name] = cache
return cache
end
|