summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2022-03-07 20:49:20 +0800
committer最萌小汐 <sumneko@hotmail.com>2022-03-07 20:49:20 +0800
commita31cb772fa4f1da3fd78e4d9f5a01729c22883f7 (patch)
tree956f02534821541185648a4b784e6faa8f998053
parentf5f0620a09708c07acbb024a0a98bd8595658116 (diff)
downloadlua-language-server-a31cb772fa4f1da3fd78e4d9f5a01729c22883f7.zip
update
-rw-r--r--script/parser/guide.lua3
-rw-r--r--script/parser/luadoc.lua106
-rw-r--r--script/vm/compiler.lua28
-rw-r--r--script/vm/generic-manager.lua18
-rw-r--r--script/vm/generic.lua25
-rw-r--r--script/vm/getDef.lua11
-rw-r--r--script/vm/global-manager.lua15
-rw-r--r--test/definition/luadoc.lua2
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