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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
local guide = require 'parser.guide'
local vm = require 'vm.vm'
local function ofTabel(value, callback)
for _, field in ipairs(value) do
if field.type == 'tablefield'
or field.type == 'tableindex' then
callback {
source = field,
key = guide.getKeyName(field),
value = field.value,
mode = 'set',
}
end
end
end
local function ofENV(source, callback)
if source.type == 'getlocal' then
local parent = source.parent
if parent.type == 'getfield'
or parent.type == 'getmethod'
or parent.type == 'getindex' then
callback {
source = parent,
key = guide.getKeyName(parent),
mode = 'get',
}
end
elseif source.type == 'getglobal' then
callback {
source = source,
key = guide.getKeyName(source),
mode = 'get',
}
elseif source.type == 'setglobal' then
callback {
source = source,
key = guide.getKeyName(source),
mode = 'set',
value = source.value,
}
end
end
local function ofSpecialArg(source, callback)
local args = source.parent
local call = args.parent
local func = call.node
local name = func.special
if name == 'rawset' then
if args[1] == source and args[2] then
callback {
source = call,
key = guide.getKeyName(args[2]),
value = args[3],
mode = 'set',
}
end
elseif name == 'rawget' then
if args[1] == source and args[2] then
callback {
source = call,
key = guide.getKeyName(args[2]),
mode = 'get',
}
end
elseif name == 'setmetatable' then
if args[1] == source and args[2] then
vm.eachField(args[2], function (info)
if info.key == 's|__index' and info.value then
vm.eachField(info.value, callback)
end
end)
end
end
end
local function ofVar(source, callback)
local parent = source.parent
if not parent then
return
end
if parent.type == 'getfield'
or parent.type == 'getmethod'
or parent.type == 'getindex' then
callback {
source = parent,
key = guide.getKeyName(parent),
mode = 'get',
}
return
end
if parent.type == 'setfield'
or parent.type == 'setmethod'
or parent.type == 'setindex' then
callback {
source = parent,
key = guide.getKeyName(parent),
value = parent.value,
mode = 'set',
}
return
end
if parent.type == 'callargs' then
ofSpecialArg(source, callback)
end
end
local function eachField(source, callback)
vm.eachRef(source, function (info)
local src = info.source
if src.tag == '_ENV' then
if src.ref then
for _, ref in ipairs(src.ref) do
ofENV(ref, callback)
end
end
elseif src.type == 'getlocal'
or src.type == 'getglobal'
or src.type == 'getfield'
or src.type == 'getmethod'
or src.type == 'getindex' then
ofVar(src, callback)
elseif src.type == 'table' then
ofTabel(src, callback)
end
end)
end
--- 获取所有的field
function vm.eachField(source, callback)
local cache = vm.cache.eachField[source]
if cache then
for i = 1, #cache do
local res = callback(cache[i])
if res ~= nil then
return res
end
end
return
end
local unlock = vm.lock('eachField', source)
if not unlock then
return
end
cache = {}
vm.cache.eachField[source] = cache
local mark = {}
eachField(source, function (info)
local src = info.source
if mark[src] then
return
end
mark[src] = true
cache[#cache+1] = info
end)
unlock()
vm.eachRef(source, function (info)
local src = info.source
vm.cache.eachField[src] = cache
end)
for i = 1, #cache do
local res = callback(cache[i])
if res ~= nil then
return res
end
end
end
|