169 lines
4.7 KiB
Lua
169 lines
4.7 KiB
Lua
|
local files = require 'files'
|
||
|
local guide = require 'parser.guide'
|
||
|
local matchKey = require 'core.matchkey'
|
||
|
local define = require 'proto.define'
|
||
|
local await = require 'await'
|
||
|
local vm = require 'vm'
|
||
|
|
||
|
local function buildSource(uri, source, key, results)
|
||
|
if source.type == 'local'
|
||
|
or source.type == 'setlocal'
|
||
|
or source.type == 'setglobal' then
|
||
|
local name = source[1]
|
||
|
if matchKey(key, name) then
|
||
|
results[#results+1] = {
|
||
|
name = name,
|
||
|
skind = define.SymbolKind.Variable,
|
||
|
ckind = define.CompletionItemKind.Variable,
|
||
|
source = source,
|
||
|
}
|
||
|
end
|
||
|
elseif source.type == 'setfield'
|
||
|
or source.type == 'tablefield' then
|
||
|
local field = source.field
|
||
|
local name = field and field[1]
|
||
|
if name and matchKey(key, name) then
|
||
|
results[#results+1] = {
|
||
|
name = name,
|
||
|
skind = define.SymbolKind.Field,
|
||
|
ckind = define.CompletionItemKind.Field,
|
||
|
source = field,
|
||
|
}
|
||
|
end
|
||
|
elseif source.type == 'setmethod' then
|
||
|
local method = source.method
|
||
|
local name = method and method[1]
|
||
|
if name and matchKey(key, name) then
|
||
|
results[#results+1] = {
|
||
|
name = name,
|
||
|
skind = define.SymbolKind.Method,
|
||
|
ckind = define.CompletionItemKind.Method,
|
||
|
source = method,
|
||
|
}
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
local function searchFile(uri, key, results)
|
||
|
local ast = files.getState(uri)
|
||
|
if not ast then
|
||
|
return
|
||
|
end
|
||
|
|
||
|
guide.eachSource(ast.ast, function (source)
|
||
|
buildSource(uri, source, key, results)
|
||
|
end)
|
||
|
end
|
||
|
|
||
|
---@async
|
||
|
---@param key string
|
||
|
---@param suri? uri
|
||
|
---@param results table[]
|
||
|
local function searchGlobalAndClass(key, suri, results)
|
||
|
for _, global in pairs(vm.getAllGlobals()) do
|
||
|
local name = global:getCodeName()
|
||
|
if matchKey(key, name) then
|
||
|
local sets
|
||
|
if suri then
|
||
|
sets = global:getSets(suri)
|
||
|
else
|
||
|
sets = global:getAllSets()
|
||
|
end
|
||
|
for _, set in ipairs(sets) do
|
||
|
local skind, ckind
|
||
|
if set.type == 'doc.class' then
|
||
|
skind = define.SymbolKind.Class
|
||
|
ckind = define.CompletionItemKind.Class
|
||
|
elseif set.type == 'doc.alias' then
|
||
|
skind = define.SymbolKind.Struct
|
||
|
ckind = define.CompletionItemKind.Struct
|
||
|
else
|
||
|
skind = define.SymbolKind.Variable
|
||
|
ckind = define.CompletionItemKind.Variable
|
||
|
end
|
||
|
results[#results+1] = {
|
||
|
name = name,
|
||
|
skind = skind,
|
||
|
ckind = ckind,
|
||
|
source = set,
|
||
|
}
|
||
|
end
|
||
|
await.delay()
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
---@async
|
||
|
---@param key string
|
||
|
---@param suri? uri
|
||
|
---@param results table[]
|
||
|
local function searchClassField(key, suri, results)
|
||
|
local class, inField = key:match('^(.+)%.(.-)$')
|
||
|
if not class then
|
||
|
return
|
||
|
end
|
||
|
local global = vm.getGlobal('type', class)
|
||
|
if not global then
|
||
|
return
|
||
|
end
|
||
|
local set
|
||
|
if suri then
|
||
|
set = global:getSets(suri)[1]
|
||
|
else
|
||
|
set = global:getAllSets()[1]
|
||
|
end
|
||
|
if not set then
|
||
|
return
|
||
|
end
|
||
|
suri = suri or guide.getUri(set)
|
||
|
vm.getClassFields(suri, global, nil, false, function (field, isMark)
|
||
|
if field.type == 'generic' then
|
||
|
return
|
||
|
end
|
||
|
---@cast field -vm.generic
|
||
|
local keyName = guide.getKeyName(field)
|
||
|
if not keyName then
|
||
|
return
|
||
|
end
|
||
|
if not matchKey(inField, keyName) then
|
||
|
return
|
||
|
end
|
||
|
results[#results+1] = {
|
||
|
name = class .. '.' .. keyName,
|
||
|
skind = define.SymbolKind.Field,
|
||
|
ckind = define.SymbolKind.Field,
|
||
|
source = field,
|
||
|
}
|
||
|
end)
|
||
|
end
|
||
|
|
||
|
---@async
|
||
|
---@param key string
|
||
|
---@param suri? uri
|
||
|
---@param results table[]
|
||
|
local function searchWords(key, suri, results)
|
||
|
for uri in files.eachFile(suri) do
|
||
|
searchFile(uri, key, results)
|
||
|
if #results > 1000 then
|
||
|
break
|
||
|
end
|
||
|
await.delay()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
---@async
|
||
|
---@param key string
|
||
|
---@param suri? uri
|
||
|
---@param includeWords? boolean
|
||
|
return function (key, suri, includeWords)
|
||
|
local results = {}
|
||
|
|
||
|
searchGlobalAndClass(key, suri, results)
|
||
|
searchClassField(key, suri, results)
|
||
|
if includeWords then
|
||
|
searchWords(key, suri, results)
|
||
|
end
|
||
|
|
||
|
return results
|
||
|
end
|