summaryrefslogtreecommitdiff
path: root/server-beta/src/searcher-old/getglobal.lua
blob: 1295d769221584ebb9c021f6a202a741095c773b (plain)
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
local guide    = require 'parser.guide'
local checkSMT = require 'searcher.setmetatable'

local m = {}

function m:eachDef(source, callback)
    -- _ENV
    local key = guide.getKeyName(source)
    self:eachField(source.node, key, function (info)
        if info.mode == 'set' then
            callback(info)
        end
    end)
    self:eachSpecial(function (name, src)
        if name == '_G' then
            local parent = src.parent
            if guide.getKeyName(parent) == key then
                callback {
                    source = parent,
                    uri    = self.uri,
                    mode   = 'set',
                }
            end
        elseif name == 'rawset' then
            local t, k = self:callArgOf(src.parent)
            if self:getSpecialName(t) == '_G'
            and guide.getKeyName(k) == key then
                callback {
                    source = src.parent,
                    uri    = self.uri,
                    mode   = 'set',
                }
            end
        end
    end)
end

function m:eachRef(source, callback)
    -- _ENV
    local key = guide.getKeyName(source)
    self:eachField(source.node, key, function (info)
        if info.mode == 'set' or info.mode == 'get' then
            callback(info)
        end
    end)
    self:eachSpecial(function (name, src)
        if name == '_G' then
            local parent = src.parent
            if guide.getKeyName(parent) == key then
                if parent.type:sub(1, 3) == 'set' then
                    callback {
                        source = parent,
                        uri    = self.uri,
                        mode   = 'set',
                    }
                else
                    callback {
                        source = parent,
                        uri    = self.uri,
                        mode   = 'get',
                    }
                end
            end
        elseif name == 'rawset' then
            local t, k = self:callArgOf(src.parent)
            if self:getSpecialName(t) == '_G'
            and guide.getKeyName(k) == key then
                callback {
                    source = src.parent,
                    uri    = self.uri,
                    mode   = 'set',
                }
            end
        elseif name == 'rawget' then
            local t, k = self:callArgOf(src.parent)
            if self:getSpecialName(t) == '_G'
            and guide.getKeyName(k) == key then
                callback {
                    source = src.parent,
                    uri    = self.uri,
                    mode   = 'set',
                }
            end
        end
    end)
end

function m:eachField(source, key, callback)
    local used = {}
    local found = false
    used[source] = true

    self:eachRef(source, function (info)
        local src = info.source
        used[src] = true
        local child, mode, value = info.searcher:childMode(src)
        if child then
            if key == guide.getKeyName(child) then
                callback {
                    source = child,
                    uri    = info.uri,
                    mode   = mode,
                }
            end
            if value then
                info.searcher:eachField(value, key, callback)
            end
            return
        end
        if src.type == 'getglobal' then
            local parent = src.parent
            child, mode, value = info.searcher:childMode(parent)
            if child then
                if key == guide.getKeyName(child) then
                    callback {
                        source = child,
                        uri    = info.uri,
                        mode   = mode,
                    }
                end
                if value then
                    info.searcher:eachField(value, key, callback)
                end
            end
        elseif src.type == 'setglobal' then
            info.searcher:eachField(src.value, key, callback)
        else
            info.searcher:eachField(src, key, callback)
        end
    end)

    checkSMT(self, key, used, found, callback)
end

function m:eachValue(source, callback)
    callback {
        source = source,
        uri    = self.uri,
    }
    self:eachDef(source, function (info)
        local src = info.source
        if src.value then
            callback {
                source = src.value,
                uri    = info.uri,
            }
        end
    end)
end

function m:getValue(source)
    if source.type == 'setglobal' then
        return source.value and self:getValue(source.value)
    end
end

return m