diff options
-rw-r--r-- | changelog.md | 7 | ||||
-rw-r--r-- | script/core/completion/completion.lua | 3 | ||||
-rw-r--r-- | script/core/hover/args.lua | 2 | ||||
-rw-r--r-- | script/core/hover/return.lua | 12 | ||||
-rw-r--r-- | script/parser/luadoc.lua | 23 | ||||
-rw-r--r-- | script/vm/compiler.lua | 7 | ||||
-rw-r--r-- | script/vm/function.lua | 2 | ||||
-rw-r--r-- | script/vm/infer.lua | 22 | ||||
-rw-r--r-- | test/crossfile/hover.lua | 23 | ||||
-rw-r--r-- | test/hover/init.lua | 40 | ||||
-rw-r--r-- | test/signature/init.lua | 2 | ||||
-rw-r--r-- | test/type_inference/init.lua | 38 |
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() +]] |