summaryrefslogtreecommitdiff
path: root/script-beta/core/definition.lua
blob: 02383ee6549223eccc9cd1c2e49a5107c18bbc59 (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
local guide     = require 'parser.guide'
local workspace = require 'workspace'
local files     = require 'files'
local vm        = require 'vm'

local accept = {
    ['local']       = true,
    ['setlocal']    = true,
    ['getlocal']    = true,
    ['label']       = true,
    ['goto']        = true,
    ['field']       = true,
    ['method']      = true,
    ['setindex']    = true,
    ['getindex']    = true,
    ['tableindex']  = true,
    ['setglobal']   = true,
    ['getglobal']   = true,
}

local function findSource(ast, offset)
    local len = 999
    local result
    guide.eachSourceContain(ast.ast, offset, function (source)
        if source.finish - source.start < len and accept[source.type] then
            result = source
            len = source.finish - source.start
        end
    end)
    return result
end

local function checkRequire(source, offset)
    if source.type ~= 'call' then
        return nil
    end
    local func = source.node
    local pathSource = source.args and source.args[1]
    if not pathSource then
        return nil
    end
    if not guide.isContain(pathSource, offset) then
        return nil
    end
    local literal = guide.getLiteral(pathSource)
    if type(literal) ~= 'string' then
        return nil
    end
    local lib = vm.getLibrary(func)
    if not lib then
        return nil
    end
    if     lib.name == 'require' then
        return workspace.findUrisByRequirePath(literal, true)
    elseif lib.name == 'dofile'
    or     lib.name == 'loadfile' then
        return workspace.findUrisByFilePath(literal, true)
    end
    return nil
end

return function (uri, offset)
    local ast = files.getAst(uri)
    if not ast then
        return nil
    end

    local source = findSource(ast, offset)
    if not source then
        return nil
    end

    local results = {}
    local uris = checkRequire(source)
    if uris then
        for i, uri in ipairs(uris) do
            results[#uris+1] = {
                uri    = files.getOriginUri(uri),
                source = source,
                target = {
                    start  = 0,
                    finish = 0,
                }
            }
        end
    end

    local defs = guide.requestDefinition(source)
    for _, src in ipairs(defs) do
        results[#results+1] = {
            target = src,
            uri    = files.getOriginUri(uri),
            source = source,
        }
    end

    if #results == 0 then
        return nil
    end
    return results
end