summaryrefslogtreecommitdiff
path: root/server/src/matcher/find_result.lua
blob: 2b7c1b980d9ca9fc3247d439c2b2f6eb153ddc3f (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
local function isContainPos(obj, pos)
    if obj.start <= pos and obj.finish + 1 >= pos then
        return true
    end
    return false, pos - (obj.finish + 1)
end

local function findAtPos(results, pos)
    for sources, object in pairs(results.sources) do
        if sources.type == 'multi-source' then
            for _, source in ipairs(source) do
                if source.type ~= 'simple' and isContainPos(source, pos) then
                    return object, source
                end
            end
        else
            local source = sources
            if source.type ~= 'simple' and isContainPos(source, pos) then
                return object, source
            end
        end
    end
    return nil
end

local function findClosePos(results, pos)
    local curDis = math.maxinteger
    local parent = nil
    for sources, object in pairs(results.sources) do
        if sources.type == 'multi-source' then
            for _, source in ipairs(source) do
                if source.type ~= 'simple' then
                    local inside, dis = isContainPos(source, pos)
                    if inside then
                        return object, source
                    elseif dis > 0 and dis < curDis then
                        curDis = dis
                        parent = object
                    end
                end
            end
        else
            local source = sources
            if source.type ~= 'simple' then
                local inside, dis = isContainPos(source, pos)
                if inside then
                    return object, source
                elseif dis > 0 and dis < curDis then
                    curDis = dis
                    parent = object
                end
            end
        end
    end
    if parent then
        -- 造个假的 DirtyName
        local source = {
            type = 'name',
            start = pos,
            finish = pos,
            [1]    = '',
        }
        local result = {
            type = 'field',
            parent = parent,
            key = '',
            source = source,
        }
        return result, source
    end
    return nil
end

return function (vm, pos, close)
    local results = vm.results
    if close then
        return findClosePos(results, pos)
    else
        return findAtPos(results, pos)
    end
end