summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--changelog.md7
-rw-r--r--script/core/completion/completion.lua3
-rw-r--r--script/core/hover/args.lua2
-rw-r--r--script/core/hover/return.lua12
-rw-r--r--script/parser/luadoc.lua23
-rw-r--r--script/vm/compiler.lua7
-rw-r--r--script/vm/function.lua2
-rw-r--r--script/vm/infer.lua22
-rw-r--r--test/crossfile/hover.lua23
-rw-r--r--test/hover/init.lua40
-rw-r--r--test/signature/init.lua2
-rw-r--r--test/type_inference/init.lua38
12 files changed, 165 insertions, 16 deletions
diff --git a/changelog.md b/changelog.md
index 20b73e9f..da028dec 100644
--- a/changelog.md
+++ b/changelog.md
@@ -30,8 +30,11 @@
```
* `CHG` semicolons and parentheses can be used in `DocTable`
```lua
- ---@type { x: fun():boolean; y: boolean }
- ---@type { (x: fun():boolean), y: boolean }
+ ---@type { (x: number); (y: boolean) }
+ ```
+* `CHG` return names and parentheses can be used in `DocFunction`
+ ```lua
+ ---@type fun():(x: number, y: number, ...: number)
```
* `CHG` supports `---@return boolean ...`
* `CHG` improve experience for diagnostics and semantic-tokens
diff --git a/script/core/completion/completion.lua b/script/core/completion/completion.lua
index 392c21ca..243a9a76 100644
--- a/script/core/completion/completion.lua
+++ b/script/core/completion/completion.lua
@@ -165,7 +165,8 @@ local function buildFunctionSnip(source, value, oop)
truncated = true
end
for i = #args, 1, -1 do
- if args[i]:match('^%s*[^?]+%?:') then
+ if args[i]:match('^%s*[^?]+%?:')
+ or args[i]:match('^%.%.%.') then
table.remove(args)
truncated = true
else
diff --git a/script/core/hover/args.lua b/script/core/hover/args.lua
index 21e7c00f..321fb081 100644
--- a/script/core/hover/args.lua
+++ b/script/core/hover/args.lua
@@ -32,7 +32,7 @@ local function asFunction(source)
vm.getInfer(argNode):view(guide.getUri(source), 'any')
)
elseif arg.type == '...' then
- args[#args+1] = ('%s: %s'):format(
+ args[#args+1] = ('%s%s'):format(
'...',
vm.getInfer(arg):view(guide.getUri(source), 'any')
)
diff --git a/script/core/hover/return.lua b/script/core/hover/return.lua
index 7f96b282..b496990b 100644
--- a/script/core/hover/return.lua
+++ b/script/core/hover/return.lua
@@ -63,7 +63,10 @@ local function asFunction(source)
for i = 1, num do
local rtn = vm.getReturnOfFunction(source, i)
local doc = docs[i]
- local name = doc and doc.name and doc.name[1] and (doc.name[1] .. ': ')
+ local name = doc and doc.name and doc.name[1]
+ if name and name ~= '...' then
+ name = name .. ': '
+ end
local text = rtn and ('%s%s'):format(
name or '',
vm.getInfer(rtn):view(guide.getUri(source))
@@ -85,6 +88,13 @@ local function asDocFunction(source)
local returns = {}
for i, rtn in ipairs(source.returns) do
local rtnText = vm.getInfer(rtn):view(guide.getUri(source))
+ if rtn.name then
+ if rtn.name[1] == '...' then
+ rtnText = rtn.name[1] .. rtnText
+ else
+ rtnText = rtn.name[1] .. ': ' .. rtnText
+ end
+ end
if i == 1 then
returns[#returns+1] = (' -> %s'):format(rtnText)
else
diff --git a/script/parser/luadoc.lua b/script/parser/luadoc.lua
index 06cd5511..392b476f 100644
--- a/script/parser/luadoc.lua
+++ b/script/parser/luadoc.lua
@@ -434,11 +434,31 @@ local function parseTypeUnitFunction(parent)
end
if checkToken('symbol', ':', 1) then
nextToken()
+ local needCloseParen
+ if checkToken('symbol', '(', 1) then
+ nextToken()
+ needCloseParen = true
+ end
while true do
+ local name
+ try(function ()
+ local returnName = parseName('doc.return.name', typeUnit)
+ or parseDots('doc.return.name', typeUnit)
+ if not returnName then
+ return false
+ end
+ if checkToken('symbol', ':', 1) then
+ nextToken()
+ name = returnName
+ return true
+ end
+ return false
+ end)
local rtn = parseType(typeUnit)
if not rtn then
break
end
+ rtn.name = name
if checkToken('symbol', '?', 1) then
nextToken()
rtn.optional = true
@@ -450,6 +470,9 @@ local function parseTypeUnitFunction(parent)
break
end
end
+ if needCloseParen then
+ nextSymbolOrError ')'
+ end
end
typeUnit.finish = getFinish()
return typeUnit
diff --git a/script/vm/compiler.lua b/script/vm/compiler.lua
index 00c8170c..46f6d0e9 100644
--- a/script/vm/compiler.lua
+++ b/script/vm/compiler.lua
@@ -479,7 +479,12 @@ function vm.getReturnOfFunction(func, index)
if func.type == 'doc.type.function' then
local rtn = func.returns[index]
if not rtn then
- return nil
+ local lastReturn = func.returns[#func.returns]
+ if lastReturn and lastReturn.name and lastReturn.name[1] == '...' then
+ rtn = lastReturn
+ else
+ return nil
+ end
end
local sign = getObjectSign(func)
if not sign then
diff --git a/script/vm/function.lua b/script/vm/function.lua
index bdb70faf..f992845f 100644
--- a/script/vm/function.lua
+++ b/script/vm/function.lua
@@ -113,7 +113,7 @@ function vm.countReturnsOfFunction(func, mark)
end
end
end
- if lastReturn then
+ if lastReturn then
if lastReturn.types[1][1] == '...' then
dmax = math.huge
end
diff --git a/script/vm/infer.lua b/script/vm/infer.lua
index d6c4da44..25165de6 100644
--- a/script/vm/infer.lua
+++ b/script/vm/infer.lua
@@ -155,20 +155,36 @@ local viewNodeSwitch = util.switch()
argNode = argNode:copy()
argNode:removeOptional()
end
- args[i] = string.format('%s%s: %s'
+ args[i] = string.format('%s%s%s%s'
, arg.name[1]
, isOptional and '?' or ''
+ , arg.name[1] == '...' and '' or ': '
, vm.getInfer(argNode):view(uri)
)
end
if #args > 0 then
argView = table.concat(args, ', ')
end
+ local needReturnParen
for i, ret in ipairs(source.returns) do
- rets[i] = vm.getInfer(ret):view(uri)
+ local retType = vm.getInfer(ret):view(uri)
+ if ret.name then
+ if ret.name[1] == '...' then
+ rets[i] = ('%s%s'):format(ret.name[1], retType)
+ else
+ needReturnParen = true
+ rets[i] = ('%s: %s'):format(ret.name[1], retType)
+ end
+ else
+ rets[i] = retType
+ end
end
if #rets > 0 then
- regView = ':' .. table.concat(rets, ', ')
+ if needReturnParen then
+ regView = (':(%s)'):format(table.concat(rets, ', '))
+ else
+ regView = (':%s'):format(table.concat(rets, ', '))
+ end
end
return ('fun(%s)%s'):format(argView, regView)
end)
diff --git a/test/crossfile/hover.lua b/test/crossfile/hover.lua
index b9ffd59b..c6991d8f 100644
--- a/test/crossfile/hover.lua
+++ b/test/crossfile/hover.lua
@@ -1158,3 +1158,26 @@ TEST {
---
The color of your awesome apple!]]
}
+
+TEST {
+ {
+ path = 'a.lua',
+ content = [[
+ ---@type fun(x: number, y: number, ...: number):(x: number, y: number, ...: number)
+ local <?f?>
+ ]]
+ },
+ hover = [[
+```lua
+local f: fun(x: number, y: number, ...number):(x: number, y: number, ...number)
+```
+
+---
+
+```lua
+function f(x: number, y: number, ...: number)
+ -> x: number
+ 2. y: number
+ 3. ...number
+```]]
+}
diff --git a/test/hover/init.lua b/test/hover/init.lua
index a97cf3ae..9cdf2ed4 100644
--- a/test/hover/init.lua
+++ b/test/hover/init.lua
@@ -247,7 +247,7 @@ TEST [[
<?print?>()
]]
[[
-function print(...: any)
+function print(...any)
]]
TEST [[
@@ -300,7 +300,7 @@ end
<?x?>(1, 2, 3, 4, 5, 6, 7)
]]
[[
-function x(a: any, ...: any)
+function x(a: any, ...any)
]]
TEST [[
@@ -1518,7 +1518,7 @@ TEST [[
local function f(<?callback?>) end
]]
[[
-(parameter) callback: fun(x: integer, ...: any)
+(parameter) callback: fun(x: integer, ...any)
]]
TEST [[
@@ -2030,3 +2030,37 @@ local t: A {
y: boolean = true,
}
]]
+
+TEST [[
+---@param ... boolean
+---@return number ...
+local function <?f?>(...) end
+]]
+[[
+function f(...boolean)
+ -> ...number
+]]
+
+TEST [[
+---@type fun():x: number
+local <?f?>
+]]
+[[
+local f: fun():(x: number)
+]]
+
+TEST [[
+---@type fun(...: boolean):...: number
+local <?f?>
+]]
+[[
+local f: fun(...boolean):...number
+]]
+
+TEST [[
+---@type fun():x: number, y: boolean
+local <?f?>
+]]
+[[
+local f: fun():(x: number, y: boolean)
+]]
diff --git a/test/signature/init.lua b/test/signature/init.lua
index 0b750cd6..207fc0b7 100644
--- a/test/signature/init.lua
+++ b/test/signature/init.lua
@@ -83,7 +83,7 @@ end
x(1, 2, 3, <??>
]]
-'function x(a: any, <!...: any!>)'
+'function x(a: any, <!...any!>)'
TEST [[
(''):sub(<??>
diff --git a/test/type_inference/init.lua b/test/type_inference/init.lua
index e86983b6..db5a38fd 100644
--- a/test/type_inference/init.lua
+++ b/test/type_inference/init.lua
@@ -510,12 +510,12 @@ TEST 'fun()' [[
local <?x?>
]]
-TEST 'fun(a: string, b: any, ...: any)' [[
+TEST 'fun(a: string, b: any, ...any)' [[
---@type fun(a: string, b, ...)
local <?x?>
]]
-TEST 'fun(a: string, b: any, c?: boolean, ...: any):c, d?, ...' [[
+TEST 'fun(a: string, b: any, c?: boolean, ...any):c, d?, ...' [[
---@type fun(a: string, b, c?: boolean, ...):c, d?, ...
local <?x?>
]]
@@ -3092,3 +3092,37 @@ local function f() end
local _, <?n?> = f()
]]
+
+TEST 'boolean' [[
+---@type fun():name1: boolean, name2:number
+local f
+
+local <?n?> = f()
+]]
+
+TEST 'number' [[
+---@type fun():name1: boolean, name2:number
+local f
+
+local _, <?n?> = f()
+]]
+TEST 'boolean' [[
+---@type fun():(name1: boolean, name2:number)
+local f
+
+local <?n?> = f()
+]]
+
+TEST 'number' [[
+---@type fun():(name1: boolean, name2:number)
+local f
+
+local _, <?n?> = f()
+]]
+
+TEST 'boolean' [[
+---@type fun():...: boolean
+local f
+
+local _, <?n?> = f()
+]]