summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author最萌小汐 <sumneko@hotmail.com>2022-04-16 03:32:43 +0800
committer最萌小汐 <sumneko@hotmail.com>2022-04-16 03:32:43 +0800
commit1407055930f23b06fbe9a6cc29cc9e54b1356783 (patch)
tree97b65707b0e4a434c9ce9e566453e03e4dfb6176
parent8a14323f7da5a4ee5956c417a38a9a85665cf128 (diff)
downloadlua-language-server-1407055930f23b06fbe9a6cc29cc9e54b1356783.zip
fix definition of `table<k, v>`
-rw-r--r--changelog.md3
-rw-r--r--script/parser/guide.lua2
-rw-r--r--script/parser/luadoc.lua91
-rw-r--r--script/vm/compiler.lua36
-rw-r--r--script/vm/global-manager.lua4
-rw-r--r--script/vm/infer.lua10
-rw-r--r--test/definition/luadoc.lua12
7 files changed, 97 insertions, 61 deletions
diff --git a/changelog.md b/changelog.md
index 9a493187..1db4aecd 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,9 +1,10 @@
# changelog
## 3.1.0
-* `CHG` inlay-hint: move to LSP and enable by default. Its font is now controlled by the client.
+* `CHG` hint: move to LSP and enable by default. Its font is now controlled by the client.
* `CHG` hover: split `local` into `local` / `parameter` / `upvalue` / `self`.
* `CHG` hover: added parentheses to some words, such as `global` / `field` / `class`.
+* `FIX` definition of `table<k, v>`
## 3.0.2
`2022-4-15`
diff --git a/script/parser/guide.lua b/script/parser/guide.lua
index 884a5271..0ece65fc 100644
--- a/script/parser/guide.lua
+++ b/script/parser/guide.lua
@@ -123,7 +123,6 @@ local childMap = {
['doc'] = {'#'},
['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'},
@@ -137,6 +136,7 @@ local childMap = {
['doc.type.literal'] = {'node'},
['doc.type.arg'] = {'name', 'extends'},
['doc.type.field'] = {'name', 'extends'},
+ ['doc.type.sign'] = {'node', '#signs'},
['doc.overload'] = {'overload', 'comment'},
['doc.see'] = {'name', 'field'},
['doc.version'] = {'#versions'},
diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua
index 22a2df1b..1d8d7c42 100644
--- a/script/parser/luadoc.lua
+++ b/script/parser/luadoc.lua
@@ -309,34 +309,21 @@ local function parseTable(parent)
return typeUnit
end
-local function parseSigns(parent, mode)
+local function parseSigns(parent)
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
+ local sign = parseName('doc.generic.name', parent)
+ if not sign then
+ pushWarning {
+ type = 'LUADOC_MISS_SIGN_NAME',
+ start = getFinish(),
+ finish = getFinish(),
+ }
+ break
end
signs[#signs+1] = sign
if checkToken('symbol', ',', 1) then
@@ -345,17 +332,7 @@ local function parseSigns(parent, mode)
break
end
end
- if not checkToken('symbol', '>', 1) then
- pushWarning {
- type = 'LUADOC_MISS_SYMBOL',
- start = getFinish(),
- finish = getFinish(),
- symbol = {
- symbol = '>',
- }
- }
- end
- nextToken()
+ nextSymbolOrError '>'
return signs
end
@@ -376,7 +353,7 @@ local function parseClass(parent)
end
result.start = getStart()
result.finish = getFinish()
- result.signs = parseSigns(result, 'name')
+ result.signs = parseSigns(result)
if not checkToken('symbol', ':', 1) then
return result
end
@@ -421,6 +398,42 @@ local function parseTypeUnitArray(parent, node)
return result
end
+local function parseTypeUnitSign(parent, node)
+ if not checkToken('symbol', '<', 1) then
+ return nil
+ end
+ nextToken()
+ local result = {
+ type = 'doc.type.sign',
+ start = node.start,
+ finish = getFinish(),
+ node = node,
+ parent = parent,
+ signs = {},
+ }
+ node.parent = result
+ while true do
+ local sign = parseType(result)
+ if not sign then
+ pushWarning {
+ type = 'LUA_DOC_MISS_SIGN',
+ start = getFinish(),
+ finish = getFinish(),
+ }
+ break
+ end
+ result.signs[#result.signs+1] = sign
+ if checkToken('symbol', ',', 1) then
+ nextToken()
+ else
+ break
+ end
+ end
+ nextSymbolOrError '>'
+ result.finish = getFinish()
+ return result
+end
+
local function parseDots(tp, parent)
if not checkToken('symbol', '...', 1) then
return
@@ -629,7 +642,13 @@ function parseTypeUnit(parent)
result.literal = true
nextSymbolOrError '`'
end
- result.signs = parseSigns(result, 'type')
+ end
+ while true do
+ local newResult = parseTypeUnitSign(parent, result)
+ if not newResult then
+ break
+ end
+ result = newResult
end
while true do
local newResult = parseTypeUnitArray(parent, result)
@@ -777,7 +796,7 @@ local function parseAlias()
return nil
end
result.start = getStart()
- result.signs = parseSigns(result, 'name')
+ result.signs = parseSigns(result)
result.extends = parseType(result)
if not result.extends then
pushWarning {
diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua
index 3840c857..e3c7e2b9 100644
--- a/script/vm/compiler.lua
+++ b/script/vm/compiler.lua
@@ -1122,30 +1122,28 @@ local compilerSwitch = util.switch()
: call(function (source)
vm.setNode(source, source)
end)
- : case 'doc.type.name'
+ : case 'doc.type.sign'
: call(function (source)
- if source.signs then
- local uri = guide.getUri(source)
- vm.setNode(source, source)
- local global = globalMgr.getGlobal('type', source[1])
- for _, set in ipairs(global:getSets(uri)) do
- if set.type == 'doc.class' then
- if set.extends then
- for _, ext in ipairs(set.extends) do
- if ext.type == 'doc.type.table' then
- if ext._generic then
- local resolved = ext._generic:resolve(uri, source.signs)
- vm.setNode(source, resolved)
- end
+ local uri = guide.getUri(source)
+ vm.setNode(source, source)
+ local global = globalMgr.getGlobal('type', source.node[1])
+ for _, set in ipairs(global:getSets(uri)) do
+ if set.type == 'doc.class' then
+ if set.extends then
+ for _, ext in ipairs(set.extends) do
+ if ext.type == 'doc.type.table' then
+ if ext._generic then
+ local resolved = ext._generic:resolve(uri, source.signs)
+ vm.setNode(source, resolved)
end
end
end
end
- if set.type == 'doc.alias' then
- if set.extends._generic then
- local resolved = set.extends._generic:resolve(uri, source.signs)
- vm.setNode(source, resolved)
- end
+ end
+ if set.type == 'doc.alias' then
+ if set.extends._generic then
+ local resolved = set.extends._generic:resolve(uri, source.signs)
+ vm.setNode(source, resolved)
end
end
end
diff --git a/script/vm/global-manager.lua b/script/vm/global-manager.lua
index 2a3aea2f..1481f14e 100644
--- a/script/vm/global-manager.lua
+++ b/script/vm/global-manager.lua
@@ -189,9 +189,7 @@ local compilerGlobalSwitch = util.switch()
local name = source[1]
local type = m.declareGlobal('type', name, uri)
type:addGet(uri, source)
- if not source.signs then
- source._globalNode = type
- end
+ source._globalNode = type
end)
: case 'doc.extends.name'
: call(function (source)
diff --git a/script/vm/infer.lua b/script/vm/infer.lua
index a5b113d6..a47783f7 100644
--- a/script/vm/infer.lua
+++ b/script/vm/infer.lua
@@ -87,7 +87,6 @@ local viewNodeSwitch = util.switch()
end)
: case 'doc.type.name'
: call(function (source, infer)
- infer._hasClass = true
if source.signs then
local buf = {}
for i, sign in ipairs(source.signs) do
@@ -115,6 +114,15 @@ local viewNodeSwitch = util.switch()
end
return view .. '[]'
end)
+ : case 'doc.type.sign'
+ : call(function (source, infer)
+ infer._hasClass = true
+ local buf = {}
+ for i, sign in ipairs(source.signs) do
+ buf[i] = m.getInfer(sign):view()
+ end
+ return ('%s<%s>'):format(source.node[1], table.concat(buf, ', '))
+ end)
: case 'doc.type.table'
: call(function (source, infer)
infer._hasTable = true
diff --git a/test/definition/luadoc.lua b/test/definition/luadoc.lua
index d7ac9a5b..19b4421b 100644
--- a/test/definition/luadoc.lua
+++ b/test/definition/luadoc.lua
@@ -881,3 +881,15 @@ G = {
local f
f.<?x?>
]]
+
+TEST [[
+---@class <!XXX!><K, V>: {}
+
+---@type <?XXX?><>
+]]
+
+TEST [[
+---@class <!YYY!>
+
+---@type XXX<<?YYY?>>
+]]