diff options
author | Kevin Hahn <hahn.kev@gmail.com> | 2022-06-23 22:25:30 +0700 |
---|---|---|
committer | Kevin Hahn <hahn.kev@gmail.com> | 2022-06-27 14:14:31 +0700 |
commit | eb6165ea4cafe386d8aa38f7ad33a40e14d404fe (patch) | |
tree | 55c4ff0692fb5e0dc5253ab6b2089a1d5a7128cf | |
parent | 0db0e59ea3649d5be702b977073b5418c1d3b8ce (diff) | |
download | lua-language-server-eb6165ea4cafe386d8aa38f7ad33a40e14d404fe.zip |
enable autocomplete of array enum
-rw-r--r-- | script/core/completion/completion.lua | 90 | ||||
-rw-r--r-- | script/parser/guide.lua | 1 | ||||
-rw-r--r-- | script/vm/compiler.lua | 15 |
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' |