summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfesily <fesil@foxmail.com>2024-01-17 15:00:54 +0800
committerfesily <fesil@foxmail.com>2024-01-17 15:00:54 +0800
commit1e51dd0617a9ae55703700550b6db211080a8c13 (patch)
treeda8e68fa128b106a32f0ff28cc393f66f3ac381a
parent4432dfea0fe8390be166b832a1ac416c8228296f (diff)
downloadlua-language-server-1e51dd0617a9ae55703700550b6db211080a8c13.zip
doc param support generic pattern
-rw-r--r--script/parser/luadoc.lua48
-rw-r--r--script/vm/sign.lua2
-rw-r--r--test/completion/common.lua21
-rw-r--r--test/definition/luadoc.lua30
4 files changed, 100 insertions, 1 deletions
diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua
index b835fd42..47396df6 100644
--- a/script/parser/luadoc.lua
+++ b/script/parser/luadoc.lua
@@ -633,6 +633,53 @@ local function parseCode(parent)
return code
end
+local function parseCodePattern(parent)
+ local tp, pattern = peekToken()
+ if not tp or tp ~= 'name' then
+ return nil
+ end
+ local codeOffset
+ local finishOffset
+ local content
+ for i = 2, 8 do
+ local next, nextContent = peekToken(i)
+ if not next or TokenFinishs[Ci+i-1] + 1 ~= TokenStarts[Ci+i] then
+ if codeOffset then
+ finishOffset = i
+ break
+ end
+ ---不连续的name,无效的
+ return nil
+ end
+ if next == 'code' then
+ if codeOffset and content ~= nextContent then
+ -- 暂时不支持多generic
+ return nil
+ end
+ codeOffset = i
+ pattern = pattern .. "%s"
+ content = nextContent
+ elseif next ~= 'name' then
+ return nil
+ else
+ pattern = pattern .. nextContent
+ end
+ end
+ local start = getStart()
+ for i = 2 , finishOffset do
+ nextToken()
+ end
+ local code = {
+ type = 'doc.type.code',
+ start = start,
+ finish = getFinish(),
+ parent = parent,
+ pattern = pattern,
+ [1] = content,
+ }
+ return code
+end
+
local function parseInteger(parent)
local tp, content = peekToken()
if not tp or tp ~= 'integer' then
@@ -687,6 +734,7 @@ function parseTypeUnit(parent)
or parseInteger(parent)
or parseBoolean(parent)
or parseParen(parent)
+ or parseCodePattern(parent)
if not result then
result = parseName('doc.type.name', parent)
or parseDots('doc.type.name', parent)
diff --git a/script/vm/sign.lua b/script/vm/sign.lua
index 38cb2242..ddc8258f 100644
--- a/script/vm/sign.lua
+++ b/script/vm/sign.lua
@@ -53,7 +53,7 @@ function mt:resolve(uri, args)
for n in node:eachObject() do
if n.type == 'string' then
---@cast n parser.object
- local type = vm.declareGlobal('type', n[1], guide.getUri(n))
+ local type = vm.declareGlobal('type', object.pattern and object.pattern:format(n[1]) or n[1], guide.getUri(n))
resolved[key] = vm.createNode(type, resolved[key])
end
end
diff --git a/test/completion/common.lua b/test/completion/common.lua
index 90037c27..3ea02ed7 100644
--- a/test/completion/common.lua
+++ b/test/completion/common.lua
@@ -4413,3 +4413,24 @@ new 'A' {
kind = define.CompletionItemKind.Property,
}
}
+
+TEST [[
+---@class namespace.A
+---@overload fun(x: {id: string})
+
+---@generic T
+---@param t namespace.`T`
+---@return T
+local function new(t) end
+
+new 'A' {
+ <??>
+}
+]]
+{
+ {
+ label = 'id',
+ kind = define.CompletionItemKind.Property,
+ }
+}
+
diff --git a/test/definition/luadoc.lua b/test/definition/luadoc.lua
index b877f5cd..7a460593 100644
--- a/test/definition/luadoc.lua
+++ b/test/definition/luadoc.lua
@@ -304,6 +304,21 @@ local v1 = Generic(Foo)
print(v1.<?bar1?>)
]]
+
+TEST [[
+---@class n.Foo
+local Foo = {}
+function Foo:bar1() end
+
+---@generic T
+---@param arg1 n.`T`
+---@return T
+function Generic(arg1) print(arg1) end
+
+local v1 = Generic(Foo)
+print(v1.<?bar1?>)
+]]
+
TEST [[
---@class Foo
local Foo = {}
@@ -318,6 +333,21 @@ local v1 = Generic("Foo")
print(v1.<?bar1?>)
]]
+
+TEST [[
+---@class n.Foo
+local Foo = {}
+function Foo:<!bar1!>() end
+
+---@generic T
+---@param arg1 n.`T`
+---@return T
+function Generic(arg1) print(arg1) end
+
+local v1 = Generic("Foo")
+print(v1.<?bar1?>)
+]]
+
TEST [[
---@class A
local t