summaryrefslogtreecommitdiff
path: root/server-beta/src/searcher/init.lua
blob: ea9d10ed368c8f394fd9d759a6fb7390bcb7ac46 (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
local guide    = require 'parser.guide'
local files    = require 'files'
local util     = require 'utility'
local getValue = require 'searcher.getValue'
local getField = require 'searcher.getField'
local eachRef  = require 'searcher.eachRef'
local eachField = require 'searcher.eachField'

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 mt = {}
mt.__index = mt
mt.__name = 'searcher'

function mt:lock(tp, source)
    if self.locked[tp][source] then
        return nil
    end
    self.locked[tp][source] = true
    return util.defer(function ()
        self.locked[tp][source] = nil
    end)
end

--- 获取关联的值
---@param source table
---@return value table
function mt:getValue(source)
    local lock <close> = self:lock('getValue', source)
    if not lock then
        return nil
    end
    return getValue(self, source)
end

--- 获取关联的field
---@param source table
---@return table field
function mt:getField(source)
    return getField(self, source)
end

--- 获取所有的引用(不递归)
function mt:eachRef(source, callback)
    local lock <close> = self:lock('eachRef', source)
    if not lock then
        return
    end
    local cache = self.cache.eachRef[source]
    if cache then
        for i = 1, #cache do
            callback(cache[i])
        end
        return
    end
    cache = {}
    self.cache.eachRef[source] = cache
    eachRef(self, source, function (info)
        cache[#cache+1] = info
        callback(info)
    end)
end

--- 获取所有的field(不递归)
function mt:eachField(source, callback)
    local lock <close> = self:lock('eachField', source)
    if not lock then
        return
    end
    local cache = self.cache.eachField[source]
    if cache then
        for i = 1, #cache do
            callback(cache[i])
        end
        return
    end
    cache = {}
    self.cache.eachField[source] = cache
    eachField(self, source, function (info)
        cache[#cache+1] = info
        callback(info)
    end)
end

---@class engineer
local m = {}

--- 新建搜索器
---@param uri string
---@return searcher
function m.create(uri)
    local ast = files.getAst(uri)
    local searcher = setmetatable({
        ast  = ast.ast,
        uri  = uri,
        cache = {
            eachRef   = {},
            eachField = {},
        },
        locked = {
            getValue  = {},
            eachRef   = {},
            eachField = {},
        }
    }, mt)
    return searcher
end

return m