diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2022-04-06 05:10:17 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2022-04-06 05:10:17 +0800 |
commit | 989ffe2a809998605750d5400a9455e0b8d279c0 (patch) | |
tree | 991370b3e99a52529cff009bb0a7911d2432c2e7 /script | |
parent | c4c0009ef28de6cd4bfe01c497cbb718f3c2dff8 (diff) | |
download | lua-language-server-989ffe2a809998605750d5400a9455e0b8d279c0.zip |
update
Diffstat (limited to 'script')
-rw-r--r-- | script/core/completion/completion.lua | 180 | ||||
-rw-r--r-- | script/vm/compiler.lua | 25 | ||||
-rw-r--r-- | script/vm/node.lua | 6 | ||||
-rw-r--r-- | script/vm/union.lua | 5 |
4 files changed, 63 insertions, 153 deletions
diff --git a/script/core/completion/completion.lua b/script/core/completion/completion.lua index 9454d6c2..b613a1f2 100644 --- a/script/core/completion/completion.lua +++ b/script/core/completion/completion.lua @@ -20,6 +20,8 @@ local infer = require 'vm.infer' local await = require 'await' local postfix = require 'core.completion.postfix' local globalMgr = require 'vm.global-manager' +local compiler = require 'vm.compiler' +local nodeMgr = require 'vm.node' local diagnosticModes = { 'disable-next-line', @@ -1101,29 +1103,20 @@ local function tryLabelInString(label, source) return util.viewString(state.ast[1], source[2]) end -local function mergeEnums(a, b, source) - local mark = {} - for _, enum in ipairs(a) do - mark[enum.label] = true - end - for _, enum in ipairs(b) do +local function cleanEnums(enums, source) + for i = #enums, 1, -1 do + local enum = enums[i] local label = tryLabelInString(enum.label, source) - if label and not mark[label] then - mark[label] = true - local result = { - label = label, - kind = enum.kind, - description = enum.description, - insertText = enum.insertText, - textEdit = source and { - start = source.start, - finish = source.finish, - newText = enum.insertText or label, - }, + if label then + enum.label = label + enum.textEdit = source and { + start = source.start, + finish = source.finish, + newText = enum.insertText or label, } - a[#a+1] = result end end + return enums end local function checkTypingEnum(state, position, defs, str, results) @@ -1138,12 +1131,8 @@ local function checkTypingEnum(state, position, defs, str, results) } end end - local myResults = {} - mergeEnums(myResults, enums, str) - table.sort(myResults, function (a, b) - return a.label < b.label - end) - for _, res in ipairs(myResults) do + cleanEnums(enums, str) + for _, res in ipairs(enums) do results[#results+1] = res end end @@ -1336,107 +1325,6 @@ function (%s)\ end"):format(table.concat(args, ', ')) end -local function pushCallEnumsAndFuncs(source) - local defs = vm.getDefs(source) - local results = {} - for _, def in ipairs(defs) do - if def.type == 'doc.type.string' - or def.type == 'doc.type.integer' then - results[#results+1] = { - label = util.viewLiteral(def[1]), - description = def.comment, - kind = define.CompletionItemKind.EnumMember, - } - end - if def.type == 'doc.type.function' then - results[#results+1] = { - label = infer.getInfer(def):view(), - description = def.comment, - kind = define.CompletionItemKind.Function, - insertText = buildInsertDocFunction(def), - } - end - end - return results -end - -local function getCallEnumsAndFuncs(source, index, oop, call) - if source.type == 'function' and source.bindDocs then - if not source.args then - return - end - local arg - if index <= #source.args then - arg = source.args[index] - else - local lastArg = source.args[#source.args] - if lastArg.type == '...' then - arg = lastArg - else - return - end - end - for _, doc in ipairs(source.bindDocs) do - if doc.type == 'doc.param' - and doc.param[1] == arg[1] then - return pushCallEnumsAndFuncs(doc.extends) - elseif doc.type == 'doc.vararg' - and arg.type == '...' then - return pushCallEnumsAndFuncs(doc.vararg) - end - end - end - if source.type == 'doc.type.function' then - local arg = source.args[index] - if arg and arg.extends then - return pushCallEnumsAndFuncs(arg.extends) - end - end - if source.type == 'doc.field' then - local currentIndex = index - if oop then - currentIndex = index - 1 - end - local results = {} - local valueBeforeIndex = index > 1 and call.args[index - 1][1] - - for _, doc in ipairs(class.fields) do - if doc ~= source - and doc.field[1] == source[1] then - local indexType = currentIndex - if not oop then - local args = noder.getFieldArgs(doc) - -- offset if doc's first arg is `self` - if args and args[1] and args[1].name[1] == 'self' then - indexType = indexType - 1 - end - end - local eventName = noder.getFieldEventName(doc) - if eventName then - if indexType == 1 then - results[#results+1] = { - label = infer.getInfer(docFunc):view(), - description = doc.comment, - kind = define.CompletionItemKind.EnumMember, - } - elseif indexType == 2 then - if eventName == valueBeforeIndex then - local docFunc = doc.extends.types[1].args[index].extends.types[1] - results[#results+1] = { - label = infer.viewDocFunction(docFunc), - description = doc.comment, - kind = define.CompletionItemKind.Function, - insertText = buildInsertDocFunction(docFunc), - } - end - end - end - end - end - return results - end -end - local function findCall(state, position) local call guide.eachSourceContain(state.ast, position, function (src) @@ -1451,15 +1339,14 @@ end local function getCallArgInfo(call, position) if not call.args then - return 1, nil, nil + return 1, nil end - local oop = call.node.type == 'getmethod' for index, arg in ipairs(call.args) do if arg.start <= position and arg.finish >= position then - return index, arg, oop + return index, arg end end - return #call.args + 1, nil, oop + return #call.args + 1, nil end local function checkTableLiteralField(state, position, tbl, fields, results) @@ -1511,23 +1398,32 @@ local function tryCallArg(state, position, results) if not call then return end - local myResults = {} - local argIndex, arg, oop = getCallArgInfo(call, position) + local argIndex, arg = getCallArgInfo(call, position) if arg and arg.type == 'function' then return end - if not arg then - arg = { type = 'dummy' } - end - local defs = vm.getDefs(call.node) - for _, def in ipairs(defs) do - def = vm.getObjectValue(def) or def - local enums = getCallEnumsAndFuncs(def, argIndex, oop, call) - if enums then - mergeEnums(myResults, enums, arg) + local node = compiler.compileCallArg({ type = 'dummyarg' }, call, argIndex) + local enums = {} + for src in nodeMgr.eachNode(node) do + if src.type == 'doc.type.string' + or src.type == 'doc.type.integer' then + enums[#enums+1] = { + label = util.viewLiteral(src[1]), + description = src.comment, + kind = define.CompletionItemKind.EnumMember, + } + end + if src.type == 'doc.type.function' then + enums[#enums+1] = { + label = infer.getInfer(src):view(), + description = src.comment, + kind = define.CompletionItemKind.Function, + insertText = buildInsertDocFunction(src), + } end end - for _, enum in ipairs(myResults) do + cleanEnums(enums, arg) + for _, enum in ipairs(enums) do results[#results+1] = enum end end diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua index d5d65dfb..7c5eb721 100644 --- a/script/vm/compiler.lua +++ b/script/vm/compiler.lua @@ -483,7 +483,7 @@ local function isValidCallArgNode(source, node) return node.type == 'doc.type.table' or (node.type == 'global' and node.cate == 'type' and not guide.isBasicType(node.name)) end - if source.type == 'dummy' then + if source.type == 'dummyarg' then return true end return false @@ -501,7 +501,7 @@ local function getFuncArg(func, index) return args[index] end local lastArg = args[#args] - if lastArg.type == '...' then + if lastArg and lastArg.type == '...' then return lastArg end return nil @@ -519,12 +519,14 @@ local function compileCallArgNode(arg, call, callNode, fixIndex, myIndex) end local eventIndex, eventMap - for i = 1, 2 do - local eventArg = call.args[i + fixIndex] - eventMap = valueMgr.getLiterals(eventArg) - if eventMap then - eventIndex = i - break + if call.args then + for i = 1, 2 do + local eventArg = call.args[i + fixIndex] + eventMap = valueMgr.getLiterals(eventArg) + if eventMap then + eventIndex = i + break + end end end @@ -564,6 +566,7 @@ function m.compileCallArg(arg, call, index) callNode = m.compileNode(call.args[1]) compileCallArgNode(arg, call, callNode, fixIndex, index) end + return nodeMgr.getNode(arg) end local compilerSwitch = util.switch() @@ -702,7 +705,8 @@ local compilerSwitch = util.switch() : case 'setindex' : call(function (source) compileByLocalID(source) - m.compileByParentNode(source.node, guide.getKeyName(source), function (src) + local key = guide.getKeyName(source) + m.compileByParentNode(source.node, key, function (src) if src.type == 'doc.type.field' then nodeMgr.setNode(source, m.compileNode(src)) end @@ -713,7 +717,8 @@ local compilerSwitch = util.switch() : case 'getindex' : call(function (source) compileByLocalID(source) - m.compileByParentNode(source.node, guide.getKeyName(source), function (src) + local key = guide.getKeyName(source) + m.compileByParentNode(source.node, key, function (src) nodeMgr.setNode(source, m.compileNode(src)) end) end) diff --git a/script/vm/node.lua b/script/vm/node.lua index b8b7917d..514625f1 100644 --- a/script/vm/node.lua +++ b/script/vm/node.lua @@ -32,7 +32,11 @@ function m.setNode(source, node) end local me = m.nodeCache[source] if not me then - m.nodeCache[source] = node + if node.type == 'union' then + m.nodeCache[source] = node:copy() + else + m.nodeCache[source] = node + end return end if me == node then diff --git a/script/vm/union.lua b/script/vm/union.lua index 809dd78f..b66b34db 100644 --- a/script/vm/union.lua +++ b/script/vm/union.lua @@ -40,6 +40,11 @@ function mt:merge(node) end end +---@return vm.node +function mt:copy() + return createUnion(self, nil) +end + ---@param source parser.object function mt:subscribeLocal(source) for _, c in ipairs(self) do |