summaryrefslogtreecommitdiff
path: root/script
diff options
context:
space:
mode:
authorKevin Hahn <hahn.kev@gmail.com>2022-06-23 22:25:30 +0700
committerKevin Hahn <hahn.kev@gmail.com>2022-06-27 14:14:31 +0700
commiteb6165ea4cafe386d8aa38f7ad33a40e14d404fe (patch)
tree55c4ff0692fb5e0dc5253ab6b2089a1d5a7128cf /script
parent0db0e59ea3649d5be702b977073b5418c1d3b8ce (diff)
downloadlua-language-server-eb6165ea4cafe386d8aa38f7ad33a40e14d404fe.zip
enable autocomplete of array enum
Diffstat (limited to 'script')
-rw-r--r--script/core/completion/completion.lua90
-rw-r--r--script/parser/guide.lua1
-rw-r--r--script/vm/compiler.lua15
3 files changed, 71 insertions, 35 deletions
diff --git a/script/core/completion/completion.lua b/script/core/completion/completion.lua
index 243a9a76..b8e863cc 100644
--- a/script/core/completion/completion.lua
+++ b/script/core/completion/completion.lua
@@ -56,6 +56,7 @@ local function trim(str)
end
local function findNearestSource(state, position)
+ ---@type parser.object
local source
guide.eachSourceContain(state.ast, position, function (src)
source = src
@@ -1132,24 +1133,34 @@ local function cleanEnums(enums, source)
return enums
end
-local function checkTypingEnum(state, position, defs, str, results)
+---@return boolean
+local function insertEnum(state, src, enums, isInArray)
+ if src.type == 'doc.type.string'
+ or src.type == 'doc.type.integer'
+ or src.type == 'doc.type.boolean' then
+ ---@cast src parser.object
+ enums[#enums+1] = {
+ label = vm.viewObject(src, state.uri),
+ description = src.comment,
+ kind = define.CompletionItemKind.EnumMember,
+ }
+ elseif src.type == 'doc.type.code' then
+ enums[#enums+1] = {
+ label = src[1],
+ description = src.comment,
+ kind = define.CompletionItemKind.EnumMember,
+ }
+ elseif isInArray and src.type == 'doc.type.array' then
+ for i, d in ipairs(vm.getDefs(src.node)) do
+ insertEnum(state, d, enums, isInArray)
+ end
+ end
+end
+
+local function checkTypingEnum(state, position, defs, str, results, isInArray)
local enums = {}
for _, def in ipairs(defs) do
- if def.type == 'doc.type.string'
- or def.type == 'doc.type.integer'
- or def.type == 'doc.type.boolean' then
- enums[#enums+1] = {
- label = vm.viewObject(def, state.uri),
- description = def.comment and def.comment.text,
- kind = define.CompletionItemKind.EnumMember,
- }
- elseif def.type == 'doc.type.code' then
- enums[#enums+1] = {
- label = def[1],
- description = def.comment and def.comment.text,
- kind = define.CompletionItemKind.EnumMember,
- }
- end
+ insertEnum(state, def, enums, isInArray)
end
cleanEnums(enums, str)
for _, res in ipairs(enums) do
@@ -1157,7 +1168,7 @@ local function checkTypingEnum(state, position, defs, str, results)
end
end
-local function checkEqualEnumLeft(state, position, source, results)
+local function checkEqualEnumLeft(state, position, source, results, isInArray)
if not source then
return
end
@@ -1167,7 +1178,7 @@ local function checkEqualEnumLeft(state, position, source, results)
end
end)
local defs = vm.getDefs(source)
- checkTypingEnum(state, position, defs, str, results)
+ checkTypingEnum(state, position, defs, str, results, isInArray)
end
local function checkEqualEnum(state, position, results)
@@ -1211,9 +1222,14 @@ local function checkEqualEnumInString(state, position, results)
end
checkEqualEnumLeft(state, position, parent[1], results)
end
+ if (parent.type == 'tableexp') then
+ checkEqualEnumLeft(state, position, parent.parent.parent, results, true)
+ return
+ end
if parent.type == 'local' then
checkEqualEnumLeft(state, position, parent, results)
end
+
if parent.type == 'setlocal'
or parent.type == 'setglobal'
or parent.type == 'setfield'
@@ -1435,24 +1451,10 @@ local function tryCallArg(state, position, results)
if not node then
return
end
+
local enums = {}
for src in node:eachObject() do
- if src.type == 'doc.type.string'
- or src.type == 'doc.type.integer'
- or src.type == 'doc.type.boolean' then
- ---@cast src parser.object
- enums[#enums+1] = {
- label = vm.viewObject(src, state.uri),
- description = src.comment,
- kind = define.CompletionItemKind.EnumMember,
- }
- elseif src.type == 'doc.type.code' then
- enums[#enums+1] = {
- label = src[1],
- description = src.comment,
- kind = define.CompletionItemKind.EnumMember,
- }
- end
+ insertEnum(state, src, enums, arg and arg.type == 'table')
if src.type == 'doc.type.function' then
---@cast src parser.object
local insertText = buildInsertDocFunction(src)
@@ -1496,6 +1498,7 @@ local function tryTable(state, position, results)
if source.type ~= 'table' then
tbl = source.parent
end
+
local defs = vm.getFields(tbl)
for _, field in ipairs(defs) do
local name = guide.getKeyName(field)
@@ -1507,6 +1510,24 @@ local function tryTable(state, position, results)
checkTableLiteralField(state, position, tbl, fields, results)
end
+local function tryArray(state, position, results)
+ local source = findNearestSource(state, position)
+ if not source then
+ return
+ end
+ if source.type ~= 'table' and (not source.parent or source.parent.type ~= 'table') then
+ return
+ end
+ local mark = {}
+ local fields = {}
+ local tbl = source
+ if source.type ~= 'table' then
+ tbl = source.parent
+ end
+ -- { } inside when enum
+ checkEqualEnumLeft(state, position, tbl, results, true)
+end
+
local function getComment(state, position)
local offset = guide.positionToOffset(state, position)
local symbolOffset = lookBackward.findAnyOffset(state.lua, offset)
@@ -2001,6 +2022,7 @@ local function tryCompletions(state, position, triggerCharacter, results)
trySpecial(state, position, results)
tryCallArg(state, position, results)
tryTable(state, position, results)
+ tryArray(state, position, results)
tryWord(state, position, triggerCharacter, results)
tryIndex(state, position, results)
trySymbol(state, position, results)
diff --git a/script/parser/guide.lua b/script/parser/guide.lua
index 56239fb1..c05c8255 100644
--- a/script/parser/guide.lua
+++ b/script/parser/guide.lua
@@ -889,6 +889,7 @@ local isSetMap = {
['doc.alias.name'] = true,
['doc.field.name'] = true,
['doc.type.field'] = true,
+ ['doc.type.array'] = true,
}
function m.isSet(source)
local tp = source.type
diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua
index ad3295f7..d0063d00 100644
--- a/script/vm/compiler.lua
+++ b/script/vm/compiler.lua
@@ -805,7 +805,7 @@ local function isValidCallArgNode(source, node)
return node.type == 'doc.type.function'
end
if source.type == 'table' then
- return node.type == 'doc.type.table'
+ return node.type == 'doc.type.table' or node.type == 'doc.type.array'
or ( node.type == 'global'
and node.cate == 'type'
---@cast node vm.global
@@ -1274,6 +1274,7 @@ local compilerSwitch = util.switch()
or source.parent.type == 'setlocal'
or source.parent.type == 'tablefield'
or source.parent.type == 'tableindex'
+ or source.parent.type == 'tableexp'
or source.parent.type == 'setfield'
or source.parent.type == 'setindex' then
local parentNode = vm.compileNode(source.parent)
@@ -1490,6 +1491,18 @@ local compilerSwitch = util.switch()
end)
: case 'tableexp'
: call(function (source)
+ if (source.parent.type == 'table') then
+ local node = vm.compileNode(source.parent)
+ for n in node:eachObject() do
+ if (n.type == 'global'
+ and n.cate == 'type') then
+ vm.setNode(source, vm.compileNode(n))
+ elseif n.type == 'doc.type.array' then
+ vm.setNode(source, vm.compileNode(n.node))
+ end
+ end
+ return
+ end
vm.setNode(source, vm.compileNode(source.value))
end)
: case 'function.return'