151 lines
4.1 KiB
Lua
151 lines
4.1 KiB
Lua
|
local files = require 'files'
|
||
|
local vm = require 'vm'
|
||
|
local getLabel = require 'core.hover.label'
|
||
|
local getDesc = require 'core.hover.description'
|
||
|
local util = require 'utility'
|
||
|
local findSource = require 'core.find-source'
|
||
|
local markdown = require 'provider.markdown'
|
||
|
local guide = require 'parser.guide'
|
||
|
local wssymbol = require 'core.workspace-symbol'
|
||
|
|
||
|
---@async
|
||
|
local function getHover(source)
|
||
|
local md = markdown()
|
||
|
local defMark = {}
|
||
|
local labelMark = {}
|
||
|
local descMark = {}
|
||
|
|
||
|
if source.type == 'doc.see.name' then
|
||
|
for _, symbol in ipairs(wssymbol(source[1], guide.getUri(source))) do
|
||
|
if symbol.name == source[1] then
|
||
|
source = symbol.source
|
||
|
break
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
---@async
|
||
|
local function addHover(def, checkLable, oop)
|
||
|
if defMark[def] then
|
||
|
return
|
||
|
end
|
||
|
defMark[def] = true
|
||
|
|
||
|
if checkLable then
|
||
|
local label = getLabel(def, oop)
|
||
|
if not labelMark[tostring(label)] then
|
||
|
labelMark[tostring(label)] = true
|
||
|
md:add('lua', label)
|
||
|
md:splitLine()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local desc = getDesc(def)
|
||
|
if not descMark[tostring(desc)] then
|
||
|
descMark[tostring(desc)] = true
|
||
|
md:add('md', desc)
|
||
|
md:splitLine()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local oop
|
||
|
if vm.getInfer(source):view(guide.getUri(source)) == 'function' then
|
||
|
local defs = vm.getDefs(source)
|
||
|
-- make sure `function` is before `doc.type.function`
|
||
|
local orders = {}
|
||
|
for i, def in ipairs(defs) do
|
||
|
if def.type == 'function' then
|
||
|
orders[def] = i - 20000
|
||
|
elseif def.type == 'doc.type.function' then
|
||
|
orders[def] = i - 10000
|
||
|
else
|
||
|
orders[def] = i
|
||
|
end
|
||
|
end
|
||
|
table.sort(defs, function (a, b)
|
||
|
return orders[a] < orders[b]
|
||
|
end)
|
||
|
local hasFunc
|
||
|
for _, def in ipairs(defs) do
|
||
|
if guide.isOOP(def) then
|
||
|
oop = true
|
||
|
end
|
||
|
if def.type == 'function'
|
||
|
and not vm.isVarargFunctionWithOverloads(def) then
|
||
|
hasFunc = true
|
||
|
addHover(def, true, oop)
|
||
|
end
|
||
|
if def.type == 'doc.type.function' then
|
||
|
hasFunc = true
|
||
|
addHover(def, true, oop)
|
||
|
end
|
||
|
end
|
||
|
if not hasFunc then
|
||
|
addHover(source, true, oop)
|
||
|
end
|
||
|
else
|
||
|
addHover(source, true, oop)
|
||
|
for _, def in ipairs(vm.getDefs(source)) do
|
||
|
if def.type == 'global' then
|
||
|
goto CONTINUE
|
||
|
end
|
||
|
if guide.isOOP(def) then
|
||
|
oop = true
|
||
|
end
|
||
|
local isFunction
|
||
|
if def.type == 'function'
|
||
|
or def.type == 'doc.type.function' then
|
||
|
isFunction = true
|
||
|
end
|
||
|
addHover(def, isFunction, oop)
|
||
|
::CONTINUE::
|
||
|
end
|
||
|
end
|
||
|
|
||
|
return md
|
||
|
end
|
||
|
|
||
|
local accept = {
|
||
|
['local'] = true,
|
||
|
['setlocal'] = true,
|
||
|
['getlocal'] = true,
|
||
|
['setglobal'] = true,
|
||
|
['getglobal'] = true,
|
||
|
['field'] = true,
|
||
|
['method'] = true,
|
||
|
['string'] = true,
|
||
|
['number'] = true,
|
||
|
['integer'] = true,
|
||
|
['doc.type.name'] = true,
|
||
|
['doc.class.name'] = true,
|
||
|
['doc.enum.name'] = true,
|
||
|
['function'] = true,
|
||
|
['doc.module'] = true,
|
||
|
['doc.see.name'] = true,
|
||
|
}
|
||
|
|
||
|
---@async
|
||
|
local function getHoverByUri(uri, position)
|
||
|
local ast = files.getState(uri)
|
||
|
if not ast then
|
||
|
return nil
|
||
|
end
|
||
|
local source = findSource(ast, position, accept)
|
||
|
if not source then
|
||
|
return nil
|
||
|
end
|
||
|
local hover = getHover(source)
|
||
|
if SHOWSOURCE then
|
||
|
hover:splitLine()
|
||
|
hover:add('lua', util.dump(source, {
|
||
|
deep = 1,
|
||
|
}))
|
||
|
end
|
||
|
return hover, source
|
||
|
end
|
||
|
|
||
|
return {
|
||
|
get = getHover,
|
||
|
byUri = getHoverByUri,
|
||
|
}
|