summaryrefslogtreecommitdiff
path: root/script-beta/vm/guideInterface.lua
blob: 2bca395bbde877bad4e1cd66463e8d8c42b8969a (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
local vm      = require 'vm.vm'
local files   = require 'files'
local ws      = require 'workspace'
local guide   = require 'parser.guide'
local await   = require 'await'
local library = require 'library'

local m = {}

function m.searchFileReturn(results, ast, index)
    local returns = ast.returns
    if not returns then
        return
    end
    for _, ret in ipairs(returns) do
        local exp = ret[index]
        if exp then
            vm.mergeResults(results, { exp })
        end
    end
end

function m.require(args, index)
    local reqName = args[1] and args[1][1]
    if not reqName then
        return nil
    end
    local results = {}
    local myUri = guide.getRoot(args[1]).uri
    local uris = ws.findUrisByRequirePath(reqName, true)
    for _, uri in ipairs(uris) do
        if not files.eq(myUri, uri) then
            local ast = files.getAst(uri)
            if ast then
                m.searchFileReturn(results, ast.ast, index)
            end
        end
    end

    local lib = library.library[reqName]
    results[#results+1] = lib

    return results
end

function m.dofile(args, index)
    local reqName = args[1] and args[1][1]
    if not reqName then
        return
    end
    local results = {}
    local myUri = guide.getRoot(args[1]).uri
    local uris = ws.findUrisByFilePath(reqName, true)
    for _, uri in ipairs(uris) do
        if not files.eq(myUri, uri) then
            local ast = files.getAst(uri)
            if ast then
                m.searchFileReturn(results, ast.ast, index)
            end
        end
    end
    return results
end

vm.interface = {}

-- 向前寻找引用的层数限制,一般情况下都为0
-- 在自动完成/漂浮提示等情况时设置为5(需要清空缓存)
-- 在查找引用时设置为10(需要清空缓存)
vm.interface.searchLevel = 0

function vm.interface.call(func, args, index)
    if func.special == 'require' and index == 1 then
        await.delay()
        return m.require(args, index)
    end
    if func.special == 'dofile' then
        await.delay()
        return m.dofile(args, index)
    end
end

function vm.interface.global(name)
    await.delay()
    return vm.getGlobals(name)
end

function vm.interface.link(uri)
    await.delay()
    return vm.getLinksTo(uri)
end

function vm.interface.index(obj)
    if obj.type == 'library' then
        return obj.fields
    end

    local tp = obj.type
    if tp == 'getglobal' and obj.node.special == '_G' then
        local lib = library.global[obj[1]]
        if not lib then
            return nil
        end
        tp = lib.value.type
    end
    local lib = library.object[tp]
    if lib then
        return lib.fields
    end

    return nil
end

function vm.interface.cache(source, mode)
    await.delay()
    local cache = vm.getCache('cache')
    if not cache[mode] then
        cache[mode] = {}
    end
    local sourceCache = cache[mode][source]
    if sourceCache then
        return sourceCache
    end
    sourceCache = {}
    cache[mode][source] = sourceCache
    return nil, function (results)
        for i = 1, #results do
            sourceCache[i] = results[i]
        end
    end
end

function vm.setSearchLevel(n)
    -- 只有在搜索等级由低变高时,才需要清空缓存
    if n > vm.interface.searchLevel then
        --vm.flushCache()
    end
    vm.interface.searchLevel = n
end