diff options
author | 最萌小汐 <sumneko@hotmail.com> | 2022-03-07 20:49:20 +0800 |
---|---|---|
committer | 最萌小汐 <sumneko@hotmail.com> | 2022-03-07 20:49:20 +0800 |
commit | a31cb772fa4f1da3fd78e4d9f5a01729c22883f7 (patch) | |
tree | 956f02534821541185648a4b784e6faa8f998053 | |
parent | f5f0620a09708c07acbb024a0a98bd8595658116 (diff) | |
download | lua-language-server-a31cb772fa4f1da3fd78e4d9f5a01729c22883f7.zip |
update
-rw-r--r-- | script/parser/guide.lua | 3 | ||||
-rw-r--r-- | script/parser/luadoc.lua | 106 | ||||
-rw-r--r-- | script/vm/compiler.lua | 28 | ||||
-rw-r--r-- | script/vm/generic-manager.lua | 18 | ||||
-rw-r--r-- | script/vm/generic.lua | 25 | ||||
-rw-r--r-- | script/vm/getDef.lua | 11 | ||||
-rw-r--r-- | script/vm/global-manager.lua | 15 | ||||
-rw-r--r-- | test/definition/luadoc.lua | 2 |
8 files changed, 151 insertions, 57 deletions
diff --git a/script/parser/guide.lua b/script/parser/guide.lua index 9be84e4e..1d634cbf 100644 --- a/script/parser/guide.lua +++ b/script/parser/guide.lua @@ -118,8 +118,9 @@ local childMap = { ['unary'] = {1}, ['doc'] = {'#'}, - ['doc.class'] = {'class', '#extends', 'comment'}, + ['doc.class'] = {'class', '#extends', '#signs', 'comment'}, ['doc.type'] = {'#types', 'name', 'comment'}, + ['doc.type.name'] = {'#signs'}, ['doc.alias'] = {'alias', 'extends', 'comment'}, ['doc.param'] = {'param', 'extends', 'comment'}, ['doc.return'] = {'#returns', 'comment'}, diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua index 62dff4bd..fbecbb3e 100644 --- a/script/parser/luadoc.lua +++ b/script/parser/luadoc.lua @@ -122,6 +122,7 @@ Symbol <- ({} { ---@class parser.object ---@field literal boolean +---@field signs parser.object[] local function trim(str) return str:match '^%s*(%S+)%s*$' @@ -306,6 +307,56 @@ local function parseTable(parent) return typeUnit end +local function parseSigns(parent, mode) + if not checkToken('symbol', '<', 1) then + return nil + end + nextToken() + local signs = {} + while true do + local sign + if mode == 'name' then + sign = parseName('doc.generic.name', parent) + if not sign then + pushWarning { + type = 'LUADOC_MISS_SIGN_NAME', + start = getFinish(), + finish = getFinish(), + } + break + end + elseif mode == 'type' then + sign = parseType(parent) + if not sign then + pushWarning { + type = 'LUADOC_MISS_TYPE_NAME', + start = getFinish(), + finish = getFinish(), + } + break + end + end + signs[#signs+1] = sign + if checkToken('symbol', ',', 1) then + nextToken() + else + break + end + end + if not checkToken('symbol', '>', 1) then + pushWarning { + type = 'LUADOC_MISS_SYMBOL', + start = getFinish(), + finish = getFinish(), + symbol = { + symbol = '>', + } + } + end + nextToken() + return signs +end + local function parseClass(parent) local result = { type = 'doc.class', @@ -323,6 +374,7 @@ local function parseClass(parent) end result.start = getStart() result.finish = getFinish() + result.signs = parseSigns(result, 'name') if not checkToken('symbol', ':', 1) then return result end @@ -367,39 +419,6 @@ local function parseTypeUnitArray(parent, node) return result end -local function parseTypeUnitTable(parent, node) - if not checkToken('symbol', '<', 1) then - return nil - end - if not nextSymbolOrError('<') then - return nil - end - - local result = { - type = 'doc.type.table', - start = node.start, - node = node, - parent = parent, - } - - local key = parseType(result) - if not key or not nextSymbolOrError(',') then - return nil - end - local value = parseType(result) - if not value then - return nil - end - nextSymbolOrError('>') - - node.parent = result - result.finish = getFinish() - result.tkey = key - result.tvalue = value - - return result -end - local function parseDots(tp, parent) if not checkToken('symbol', '...', 1) then return @@ -529,6 +548,7 @@ function parseTypeUnit(parent) parent = parent, [1] = token, } + result.signs = parseSigns(result, 'type') end if not result then return nil @@ -1267,14 +1287,26 @@ end local function bindGeneric(binded) local generics = {} for _, doc in ipairs(binded) do - if doc.type == 'doc.generic' then + if doc.type == 'doc.generic' then for _, obj in ipairs(doc.generics) do local name = obj.generic[1] generics[name] = true end - elseif doc.type == 'doc.param' - or doc.type == 'doc.return' - or doc.type == 'doc.type' then + end + if doc.type == 'doc.class' + or doc.type == 'doc.alias' then + if doc.signs then + for _, sign in ipairs(doc.signs) do + local name = sign[1] + generics[name] = true + end + end + end + if doc.type == 'doc.param' + or doc.type == 'doc.return' + or doc.type == 'doc.type' + or doc.type == 'doc.class' + or doc.type == 'doc.alias' then guide.eachSourceType(doc, 'doc.type.name', function (src) local name = src[1] if generics[name] then diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua index 59ef9cbe..10b79a3c 100644 --- a/script/vm/compiler.lua +++ b/script/vm/compiler.lua @@ -72,6 +72,11 @@ local searchFieldMap = util.switch() end end end + if fieldKey.type == 'doc.field.name' then + if fieldKey[1] == key then + pushResult(field.extends) + end + end end end) : getMap() @@ -115,9 +120,11 @@ function m.getClassFields(node, key, pushResult) -- look into extends(if field not found) if not hasFounded and set.extends then for _, extend in ipairs(set.extends) do - local extendType = globalMgr.getGlobal('type', extend[1]) - if extendType then - searchClass(extendType) + if extend.type == 'doc.extends.name' then + local extendType = globalMgr.getGlobal('type', extend[1]) + if extendType then + searchClass(extendType) + end end end end @@ -227,13 +234,7 @@ local function getReturn(func, index, source, args) or cnode.type == 'doc.type.function' then local returnNode = getReturnOfFunction(cnode, index) if returnNode and returnNode.type == 'generic' then - local argNodes = {} - if args then - for i, arg in ipairs(args) do - argNodes[i] = m.compileNode(arg) - end - end - returnNode = returnNode:resolve(argNodes) + returnNode = returnNode:resolve(args) end if returnNode then nodeMgr.setNode(source, m.compileNode(returnNode)) @@ -586,7 +587,12 @@ local function compileByGlobal(source) if set.extends then for _, ext in ipairs(set.extends) do if ext.type == 'doc.type.table' then - nodeMgr.setNode(source, m.compileNode(ext)) + if ext._generic then + local resolved = ext._generic:resolve(source.signs) + nodeMgr.setNode(source, resolved) + else + nodeMgr.setNode(source, m.compileNode(ext)) + end end end end diff --git a/script/vm/generic-manager.lua b/script/vm/generic-manager.lua index 7c5a741c..76bdd9c5 100644 --- a/script/vm/generic-manager.lua +++ b/script/vm/generic-manager.lua @@ -1,5 +1,4 @@ local createGeneric = require 'vm.generic' -local globalMgr = require 'vm.global-manager' local guide = require 'parser.guide' local nodeMgr = require 'vm.node' @@ -24,8 +23,12 @@ end ---@param argNodes vm.node[] ---@return table<string, vm.node> function mt:resolve(argNodes) - local typeMgr = require 'vm.type' - local compiler = require 'vm.compiler' + if not argNodes then + return nil + end + local typeMgr = require 'vm.type' + local compiler = require 'vm.compiler' + local globalMgr = require 'vm.global-manager' local resolved = {} ---@param typeUnit parser.object @@ -76,8 +79,13 @@ function mt:resolve(argNodes) if not sign then break end - for _, typeUnit in ipairs(sign.types) do - resolve(typeUnit, node) + if sign.type == 'doc.type' then + for _, typeUnit in ipairs(sign.types) do + resolve(typeUnit, compiler.compileNode(node)) + end + end + if sign.type == 'doc.generic.name' then + resolve(sign, compiler.compileNode(node)) end end diff --git a/script/vm/generic.lua b/script/vm/generic.lua index 6d5a19da..3aa61231 100644 --- a/script/vm/generic.lua +++ b/script/vm/generic.lua @@ -7,10 +7,13 @@ local mt = {} mt.__index = mt mt.type = 'generic' ----@param node vm.node ----@param resolved table<string, vm.node> +---@param node vm.node +---@param resolved? table<string, vm.node> ---@return vm.node local function cloneObject(node, resolved) + if not resolved then + return node + end if node.type == 'doc.generic.name' then local key = node[1] return resolved[key] or node @@ -56,7 +59,25 @@ local function cloneObject(node, resolved) end if node.type == 'doc.type.table' then local newTable = { + type = node.type, + start = node.start, + finish = node.finish, + parent = node.parent, + fields = {}, } + for i, field in ipairs(node.fields) do + local newField = { + type = field.type, + start = field.start, + finish = field.finish, + parent = newTable, + name = field.name, + extends = cloneObject(field.extends, resolved) + } + newField.name.parent = newField + newField.extends.parent = newField + newTable.fields[i] = newField + end return newTable end if node.type == 'doc.type.function' then diff --git a/script/vm/getDef.lua b/script/vm/getDef.lua index 1665154b..2105eeb6 100644 --- a/script/vm/getDef.lua +++ b/script/vm/getDef.lua @@ -112,6 +112,17 @@ local searchFieldMap = util.switch() end end end) + : case 'doc.type.table' + : call(function (node, key, pushResult) + for _, field in ipairs(node.fields) do + local fieldKey = field.name + if fieldKey.type == 'doc.field.name' then + if fieldKey[1] == key then + pushResult(fieldKey) + end + end + end + end) : getMap() local searchByParentNode diff --git a/script/vm/global-manager.lua b/script/vm/global-manager.lua index a225be87..130a11db 100644 --- a/script/vm/global-manager.lua +++ b/script/vm/global-manager.lua @@ -1,6 +1,7 @@ local util = require 'utility' local guide = require 'parser.guide' local globalBuilder = require 'vm.global' +local genericMgr = require 'vm.generic-manager' ---@class parser.object ---@field _globalNode vm.node.global @@ -142,6 +143,20 @@ local compilerGlobalMap = util.switch() local class = m.declareGlobal('type', name, uri) class:addSet(uri, source) source._globalNode = class + + if source.signs then + source._generic = genericMgr(source) + for _, sign in ipairs(source.signs) do + source._generic:addSign(sign) + end + if source.extends then + for _, ext in ipairs(source.extends) do + if ext.type == 'doc.type.table' then + ext._generic = source._generic:getChild(ext) + end + end + end + end end) : case 'doc.alias' : call(function (source) diff --git a/test/definition/luadoc.lua b/test/definition/luadoc.lua index ff54f0ed..7b6fd0da 100644 --- a/test/definition/luadoc.lua +++ b/test/definition/luadoc.lua @@ -633,7 +633,7 @@ end ]] TEST [[ ----@class TT<V>: { x: V } +---@class TT<V>: { <!x!>: V } ---@type TT<A> local t |