feat(lua): typing for vim.fn.* (#24473)

Problem:
  No LSP information for `vim.fn.*`

Solution:
  Add meta file for `vim.fn.*`.
This commit is contained in:
Lewis Russell 2023-07-26 09:50:54 +01:00 committed by GitHub
parent b8b7782037
commit fd089c8e50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 11584 additions and 133 deletions

2
.gitattributes vendored
View File

@ -4,6 +4,8 @@
runtime/doc/* linguist-documentation
runtime/lua/vim/_meta/vimfn.lua linguist-generated
src/xdiff/** linguist-vendored
src/cjson/** linguist-vendored
src/unicode/** linguist-vendored

View File

@ -1,14 +1,15 @@
# Check if any PR needs to run the autogenerate script
name: Autogenerate API docs
name: Autogenerate API docs and types
on:
pull_request:
paths:
- 'src/nvim/api/*.[ch]'
- 'src/nvim/eval.lua'
- 'runtime/lua/**.lua'
- 'runtime/doc/**'
jobs:
regen-api-docs:
regen-api-docs-and-types:
runs-on: ubuntu-latest
permissions:
contents: write
@ -28,11 +29,13 @@ jobs:
id: docs
run: |
python3 scripts/gen_vimdoc.py
./scripts/gen_vimfn_types.lua
printf 'UPDATED_DOCS=%s\n' $([ -z "$(git diff)" ]; echo $?) >> $GITHUB_OUTPUT
- name: FAIL, PR has not committed doc changes
if: ${{ steps.docs.outputs.UPDATED_DOCS != 0 }}
run: |
echo "Job failed, run ./scripts/gen_vimdoc.py and commit your doc changes"
echo "Job failed, run ./scripts/gen_vimdoc.py and/or ./scripts/gen_vimfn_types.lua"
echo "and commit your doc changes"
echo "The doc generation produces the following changes:"
git diff --color --exit-code

View File

@ -44,5 +44,6 @@ globals = {
exclude_files = {
'test/functional/fixtures/lua/syntax_error.lua',
'runtime/lua/vim/treesitter/_meta.lua',
'runtime/lua/vim/_meta/vimfn.lua',
'runtime/lua/vim/re.lua',
}

11162
runtime/lua/vim/_meta/vimfn.lua generated Normal file

File diff suppressed because it is too large Load Diff

244
scripts/gen_vimfn_types.lua Executable file
View File

@ -0,0 +1,244 @@
#!/usr/bin/env -S nvim -l
--- @class vim.EvalFn2 : vim.EvalFn
--- @field signature string
--- @field desc string[]
--- @field params {[1]: string, [2]: string}[]
--- @param filename string
--- @return string
local function safe_read(filename)
local file, err = io.open(filename, 'r')
if not file then
error(err)
end
local content = file:read('*a')
io.close(file)
return content
end
local nvim_eval = require'src/nvim/eval'
local funcs = nvim_eval.funcs --[[@as table<string,vim.EvalFn2>]]
local LUA_KEYWORDS = {
['and'] = true,
['end'] = true,
['function'] = true,
['or'] = true,
['if'] = true,
['while'] = true,
['repeat'] = true
}
local SOURCES = {
{
path = 'runtime/doc/builtin.txt',
from = '^2. Details',
to = '==========',
},
{
path = 'runtime/doc/sign.txt',
from = '^3. Functions',
to = 'vim:'
},
{
path = 'runtime/doc/testing.txt',
from = '^3. Assert functions',
to = 'vim:'
}
}
local ARG_NAME_TYPES = {
col = 'integer',
nosuf = 'boolean',
dir = 'string',
mode = 'string',
width = 'integer',
height = 'integer',
timeout = 'integer',
libname = 'string',
funcname = 'string',
end_ = 'integer',
file = 'string',
flags = 'string',
fname = 'integer',
idx = 'integer',
lnum = 'integer',
mods = 'string',
name = 'string',
nr = 'integer',
options = 'table',
opts = 'table',
path = 'string',
regname = 'string',
silent = 'boolean',
string = 'string',
tabnr = 'integer',
varname = 'string',
winid = 'integer',
winnr = 'integer',
}
local function process_source(source)
local src_txt = safe_read(source.path)
--- @type string[]
local src_lines = vim.split(src_txt, '\n', { plain = true })
local s = 0
for i, l in ipairs(src_lines) do
if l:match(source.from) then
s = i+1
end
end
local lines = {} --- @type string[]
local last_f --- @type string?
for i = s, #src_lines do
local l = src_lines[i]
if not l or l:match(source.to) then
break
end
local f = l:match('^([a-z][a-zA-Z0-9_]*)%(')
if f then
if last_f then
funcs[last_f].desc = lines
end
last_f = f
local sig = l:match('[^)]+%)')
local params = {} --- @type string[]
if sig then
for param in string.gmatch(sig, '{([a-z][a-zA-Z0-9_]*)}') do
local t = ARG_NAME_TYPES[param] or 'any'
params[#params+1] = {param, t}
end
else
print('error parsing', l)
end
funcs[last_f].signature = sig
funcs[last_f].params = params
lines = {}
else
lines[#lines+1] = l:gsub('^(<?)\t\t', '%1'):gsub('\t', ' ')
end
end
if last_f then
funcs[last_f].desc = lines
end
end
local function render_fun_sig(f, params)
local param_str --- @type string
if params == true then
param_str = '...'
else
param_str = table.concat(vim.tbl_map(function(v)
return v[1]
end, params), ', ')
end
if LUA_KEYWORDS[f] then
return string.format('vim.fn[\'%s\'] = function(%s) end', f, param_str)
else
return string.format('function vim.fn.%s(%s) end', f, param_str)
end
end
--- Uniquify names
--- Fix any names that are lua keywords
--- @param fun vim.EvalFn2
local function process_params(fun)
if not fun.params then
return
end
local seen = {} --- @type table<string,true>
local sfx = 1
for _, p in ipairs(fun.params) do
if LUA_KEYWORDS[p[1]] then
p[1] = p[1]..'_'
end
if seen[p[1]] then
p[1] = p[1]..sfx
sfx = sfx + 1
else
seen[p[1]] = true
end
end
end
--- @param funname string
--- @param fun vim.EvalFn2
--- @param write fun(line: string)
local function render_fun(funname, fun, write)
if fun.deprecated then
write('')
write('--- @deprecated')
for _, l in ipairs(fun.deprecated) do
write('--- '.. l)
end
write(render_fun_sig(funname, true))
return
end
if fun.desc and fun.signature then
write('')
for _, l in ipairs(fun.desc) do
write('--- '.. l:gsub('@', '\\@'))
end
local req_args = type(fun.args) == 'table' and fun.args[1] or fun.args or 0
for i, param in ipairs(fun.params) do
if i <= req_args then
write('--- @param '..param[1]..' '..param[2])
else
write('--- @param '..param[1]..'? '..param[2])
end
end
if fun.returns ~= false then
write('--- @return '..(fun.returns or 'any'))
end
write(render_fun_sig(funname, fun.params))
return
end
print('no doc for', funname)
end
local function main(outfile)
local o = assert(io.open(outfile, 'w'))
local function write(l)
local l1 = l:gsub('%s+$', '')
o:write(l1)
o:write('\n')
end
for _, source in ipairs(SOURCES) do
process_source(source)
end
--- @type string[]
local fnames = vim.tbl_keys(funcs)
table.sort(fnames)
write('--- @meta')
write('-- THIS FILE IS GENERATED')
write('-- DO NOT EDIT')
for _, f in ipairs(fnames) do
local fun = funcs[f]
process_params(fun)
render_fun(f, fun, write)
end
end
main('runtime/lua/vim/_meta/vimfn.lua')

View File

@ -2,74 +2,85 @@
--
-- Keys:
--
-- args Number of arguments, list with maximum and minimum number of arguments
-- or list with a minimum number of arguments only. Defaults to zero
-- arguments.
-- base For methods: the argument to use as the base argument (1-indexed):
-- base->method()
-- Defaults to BASE_NONE (function cannot be used as a method).
-- func Name of the C function which implements the Vimscript function. Defaults to
-- `f_{funcname}`.
-- fast Function can run in |api-fast| events. Defaults to false.
local varargs = function(nr)
return {nr}
end
--- @class vim.EvalFn
--- @field args? integer|integer[] Number of arguments, list with maximum and minimum number of arguments
--- or list with a minimum number of arguments only. Defaults to zero
--- arguments.
--- @field base? integer For methods: the argument to use as the base argument (1-indexed):
--- base->method()
--- Defaults to BASE_NONE (function cannot be used as a method).
--- @field func? string Name of the C function which implements the Vimscript function. Defaults to
--- `f_{funcname}`.
--- @field fast? boolean Function can run in |api-fast| events. Defaults to false.
--- @field deprecated? string[]|true
--- @field returns? string|false
-- Usable with the base key: use the last function argument as the method base.
-- Value is from funcs.h file. "BASE_" prefix is omitted.
-- local LAST = "BASE_LAST" (currently unused after port of v8.2.1168)
local VIMBOOL = '0|1'
return {
--- @type table<string,vim.EvalFn>
funcs={
abs={args=1, base=1},
acos={args=1, base=1, float_func="acos"}, -- WJMc
acos={args=1, base=1, float_func="acos", returns='number'}, -- WJMc
add={args=2, base=1},
['and']={args=2, base=1},
api_info={fast=true},
append={args=2, base=2},
appendbufline={args=3, base=3},
argc={args={0, 1}},
argidx={},
arglistid={args={0, 2}},
argc={args={0, 1}, returns='integer'},
argidx={returns='integer'},
arglistid={args={0, 2}, returns='integer'},
argv={args={0, 2}},
asin={args=1, base=1, float_func="asin"}, -- WJMc
assert_beeps={args=1, base=1},
assert_equal={args={2, 3}, base=2},
assert_beeps={args=1, base=1, returns=VIMBOOL},
assert_equal={args={2, 3}, base=2, returns=VIMBOOL},
assert_equalfile={args={2, 3}, base=1},
assert_exception={args={1, 2}},
assert_fails={args={1, 5}, base=1},
assert_false={args={1, 2}, base=1},
assert_inrange={args={3, 4}, base=3},
assert_match={args={2, 3}, base=2},
assert_nobeep={args=1, base=1},
assert_exception={args={1, 2}, returns=VIMBOOL},
assert_fails={args={1, 5}, base=1, returns=VIMBOOL},
assert_false={args={1, 2}, base=1, returns=VIMBOOL},
assert_inrange={args={3, 4}, base=3, returns=VIMBOOL},
assert_match={args={2, 3}, base=2, returns=VIMBOOL},
assert_nobeep={args=1, base=1, returns=VIMBOOL},
assert_notequal={args={2, 3}, base=2},
assert_notmatch={args={2, 3}, base=2},
assert_report={args=1, base=1},
assert_true={args={1, 2}, base=1},
atan={args=1, base=1, float_func="atan"},
atan2={args=2, base=1},
atan={args=1, base=1, float_func="atan", returns='number'},
atan2={args=2, base=1, returns='number'},
blob2list={args=1, base=1},
browse={args=4},
browsedir={args=2},
bufadd={args=1, base=1},
bufexists={args=1, base=1},
buffer_exists={args=1, base=1, func='f_bufexists'}, -- obsolete
buffer_name={args={0, 1}, base=1, func='f_bufname'}, -- obsolete
buffer_number={args={0, 1}, base=1, func='f_bufnr'}, -- obsolete
buflisted={args=1, base=1},
bufload={args=1, base=1},
bufloaded={args=1, base=1},
bufname={args={0, 1}, base=1},
bufnr={args={0, 2}, base=1},
bufwinid={args=1, base=1},
bufwinnr={args=1, base=1},
byte2line={args=1, base=1},
byteidx={args={2, 3}, base=1, fast=true},
byteidxcomp={args={2, 3}, base=1, fast=true},
bufadd={args=1, base=1, returns='integer'},
bufexists={args=1, base=1, returns=VIMBOOL},
buffer_exists={
args=1, base=1, func='f_bufexists',
deprecated = { 'Obsolete name for |bufexists()|.' }
},
buffer_name={
args={0, 1}, base=1, func='f_bufname',
deprecated = { 'Obsolete name for |bufname()|.' }
},
buffer_number={
args={0, 1}, base=1, func='f_bufnr',
deprecated = { 'Obsolete name for |bufnr()|.' }
},
buflisted={args=1, base=1, returns=VIMBOOL},
bufload={args=1, base=1, returns=false},
bufloaded={args=1, base=1, returns=VIMBOOL},
bufname={args={0, 1}, base=1, returns='string'},
bufnr={args={0, 2}, base=1, returns='integer'},
bufwinid={args=1, base=1, returns='integer'},
bufwinnr={args=1, base=1, returns='integer'},
byte2line={args=1, base=1, returns='integer'},
byteidx={args={2, 3}, base=1, fast=true, returns='integer'},
byteidxcomp={args={2, 3}, base=1, fast=true, returns='integer'},
call={args={2, 3}, base=1},
ceil={args=1, base=1, float_func="ceil"},
changenr={},
changenr={returns='integer'},
chanclose={args={1, 2}},
chansend={args=2},
char2nr={args={1, 2}, base=1, fast=true},
@ -79,11 +90,11 @@ return {
chdir={args=1, base=1},
cindent={args=1, base=1},
clearmatches={args={0, 1}, base=1},
col={args={1, 2}, base=1},
complete={args=2, base=2},
complete_add={args=1, base=1},
complete_check={},
complete_info={args={0, 1}, base=1},
col={args={1, 2}, base=1, returns='integer'},
complete={args=2, base=2, returns=false},
complete_add={args=1, base=1, returns='0|1|2'},
complete_check={returns=VIMBOOL},
complete_info={args={0, 1}, base=1, returns='table'},
confirm={args={1, 4}, base=1},
copy={args=1, base=1},
cos={args=1, base=1, float_func="cos"},
@ -97,7 +108,7 @@ return {
cursor={args={1, 3}, base=1},
debugbreak={args={1, 1}, base=1},
deepcopy={args={1, 2}, base=1},
delete={args={1,2}, base=1},
delete={args={1,2}, base=1, returns='integer'},
deletebufline={args={2,3}, base=1},
dictwatcheradd={args=3},
dictwatcherdel={args=3},
@ -116,33 +127,36 @@ return {
executable={args=1, base=1, fast=true},
execute={args={1, 2}, base=1},
exepath={args=1, base=1},
exists={args=1, base=1},
exists={args=1, base=1, returns=VIMBOOL},
exp={args=1, base=1, float_func="exp"},
expand={args={1, 3}, base=1},
expand={args={1, 3}, base=1, returns='string|string[]'},
expandcmd={args={1, 2}, base=1},
extend={args={2, 3}, base=1},
extendnew={args={2, 3}, base=1},
feedkeys={args={1, 2}, base=1},
file_readable={args=1, base=1, func='f_filereadable'}, -- obsolete
filereadable={args=1, base=1, fast=true},
filewritable={args=1, base=1, fast=true},
file_readable={
args=1, base=1, func='f_filereadable',
deprecated = { 'Obsolete name for |filereadable()|.' }
},
filereadable={args=1, base=1, fast=true, returns=VIMBOOL},
filewritable={args=1, base=1, fast=true, returns=VIMBOOL},
filter={args=2, base=1},
finddir={args={1, 3}, base=1},
findfile={args={1, 3}, base=1},
flatten={args={1, 2}, base=1},
flattennew={args={1, 2}, base=1},
flatten={args={1, 2}, base=1, returns='any[]|0'},
flattennew={args={1, 2}, base=1, returns='any[]|0'},
float2nr={args=1, base=1},
floor={args=1, base=1, float_func="floor"},
fmod={args=2, base=1},
fnameescape={args=1, base=1, fast=true},
fnamemodify={args=2, base=1, fast=true},
foldclosed={args=1, base=1},
foldclosedend={args=1, base=1},
foldlevel={args=1, base=1},
foldtext={},
foldtextresult={args=1, base=1},
fnameescape={args=1, base=1, fast=true, returns='string'},
fnamemodify={args=2, base=1, fast=true, returns='string'},
foldclosed={args=1, base=1, returns='integer'},
foldclosedend={args=1, base=1, returns='integer'},
foldlevel={args=1, base=1, returns='integer'},
foldtext={returns='string'},
foldtextresult={args=1, base=1, returns='string'},
foreground={},
fullcommand={args=1, base=1},
fullcommand={args=1, base=1, returns='string'},
funcref={args={1, 3}, base=1},
['function']={args={1, 3}, base=1},
garbagecollect={args={0, 1}},
@ -153,39 +167,39 @@ return {
getbufvar={args={2, 3}, base=1},
getcellwidths={},
getchangelist={args={0, 1}, base=1},
getchar={args={0, 1}},
getcharmod={},
getchar={args={0, 1}, returns='integer'},
getcharmod={returns='integer'},
getcharpos={args=1, base=1},
getcharsearch={},
getcharstr={args={0, 1}},
getcmdcompltype={},
getcmdline={},
getcharstr={args={0, 1}, returns='string'},
getcmdcompltype={returns='string'},
getcmdline={returns='string'},
getcmdpos={},
getcmdscreenpos={},
getcmdtype={},
getcmdwintype={},
getcompletion={args={2, 3}, base=1},
getcmdtype={returns="':'|'>'|'/'|'?'|'@'|'-'|'='"},
getcmdwintype={returns="':'|'>'|'/'|'?'|'@'|'-'|'='"},
getcompletion={args={2, 3}, base=1, returns='string[]'},
getcurpos={args={0, 1}, base=1},
getcursorcharpos={args={0, 1}, base=1},
getcwd={args={0, 2}, base=1},
getenv={args=1, base=1},
getfontname={args={0, 1}},
getfperm={args=1, base=1, fast=true},
getfsize={args=1, base=1, fast=true},
getftime={args=1, base=1, fast=true},
getftype={args=1, base=1, fast=true},
getcwd={args={0, 2}, base=1, returns='string'},
getenv={args=1, base=1, returns='string'},
getfontname={args={0, 1}, returns='string'},
getfperm={args=1, base=1, fast=true, returns='string'},
getfsize={args=1, base=1, fast=true, returns='integer'},
getftime={args=1, base=1, fast=true, returns='integer'},
getftype={args=1, base=1, fast=true, returns="'file'|'dir'|'link'|'bdev'|'cdev'|'socket'|'fifo'|'other'"},
getjumplist={args={0, 2}, base=1},
getline={args={1, 2}, base=1},
getloclist={args={1, 2}},
getmarklist={args={0, 1}, base=1},
getmatches={args={0, 1}},
getmousepos={},
getpid={fast=true},
getpid={fast=true, returns='integer'},
getpos={args=1, base=1},
getqflist={args={0, 1}},
getreg={args={0, 3}, base=1},
getreginfo={args={0, 1}, base=1},
getregtype={args={0, 1}, base=1},
getreg={args={0, 3}, base=1, returns='string|string[]'},
getreginfo={args={0, 1}, base=1, returns='table'},
getregtype={args={0, 1}, base=1, returns='string'},
gettabinfo={args={0, 1}, base=1},
gettabvar={args={2, 3}, base=1},
gettabwinvar={args={3, 4}, base=1},
@ -194,31 +208,40 @@ return {
gettext={args=1, base=1},
getwininfo={args={0, 1}, base=1},
getwinpos={args={0, 1}, base=1},
getwinposx={},
getwinposy={},
getwinposx={returns='integer'},
getwinposy={returns='integer'},
getwinvar={args={2, 3}, base=1},
glob={args={1, 4}, base=1},
glob2regpat={args=1, base=1},
globpath={args={2, 5}, base=2},
has={args=1},
has_key={args=2, base=1},
haslocaldir={args={0, 2}, base=1},
hasmapto={args={1, 3}, base=1},
highlightID={args=1, base=1, func='f_hlID'}, -- obsolete
highlight_exists={args=1, base=1, func='f_hlexists'}, -- obsolete
histadd={args=2, base=2},
histdel={args={1, 2}, base=1},
histget={args={1, 2}, base=1},
histnr={args=1, base=1},
hlID={args=1, base=1},
hlexists={args=1, base=1},
hostname={fast=true},
has={args=1, returns=VIMBOOL},
has_key={args=2, base=1, returns=VIMBOOL},
haslocaldir={args={0, 2}, base=1, returns=VIMBOOL},
hasmapto={args={1, 3}, base=1, returns=VIMBOOL},
highlightID={
args=1, base=1, func='f_hlID',
deprecated = { 'Obsolete name for |hlID()|.' }
},
highlight_exists={
args=1, base=1, func='f_hlexists',
deprecated = { 'Obsolete name for |hlexists()|.' }
},
histadd={args=2, base=2, returns=VIMBOOL},
histdel={args={1, 2}, base=1, returns=VIMBOOL},
histget={args={1, 2}, base=1, returns='string'},
histnr={args=1, base=1, returns='integer'},
hlID={args=1, base=1, returns='integer'},
hlexists={args=1, base=1, returns=VIMBOOL},
hostname={fast=true, returns='string'},
iconv={args=3, base=1, fast=true},
indent={args=1, base=1},
indent={args=1, base=1, returns='integer'},
index={args={2, 4}, base=1},
indexof={args={2, 3}, base=1},
input={args={1, 3}, base=1},
inputdialog={args={1, 3}, base=1},
inputdialog={
args={1, 3}, base=1,
deprecated = { 'Use |input()| instead.' }
},
inputlist={args=1, base=1},
inputrestore={},
inputsave={},
@ -226,16 +249,22 @@ return {
insert={args={2, 3}, base=1},
interrupt={args=0},
invert={args=1, base=1},
isdirectory={args=1, base=1, fast=true},
isinf={args=1, base=1},
islocked={args=1, base=1},
isnan={args=1, base=1},
isdirectory={args=1, base=1, fast=true, returns=VIMBOOL},
isinf={args=1, base=1, returns='1|0|-1'},
islocked={args=1, base=1, returns=VIMBOOL},
isnan={args=1, base=1, returns=VIMBOOL},
id={args=1},
items={args=1, base=1},
jobclose={args={1, 2}, func="f_chanclose"},
jobpid={args=1},
jobclose={
args={1, 2}, func="f_chanclose",
deprecated = { 'Obsolete name for |chanclose()|' }
},
jobpid={args=1, returns='integer'},
jobresize={args=3},
jobsend={args=2, func="f_chansend"},
jobsend={
args=2, func="f_chansend",
deprecated = { 'Obsolete name for |chansend()|' }
},
jobstart={args={1, 2}},
jobstop={args=1},
jobwait={args={1, 2}},
@ -244,12 +273,14 @@ return {
json_encode={args=1, base=1},
keys={args=1, base=1},
keytrans={args=1, base=1},
last_buffer_nr={}, -- obsolete
last_buffer_nr={
deprecated = { 'Obsolete name for bufnr("$").' }
},
len={args=1, base=1},
libcall={args=3, base=3},
libcallnr={args=3, base=3},
line={args={1, 2}, base=1},
line2byte={args=1, base=1},
line={args={1, 2}, base=1, returns='integer'},
line2byte={args=1, base=1, returns='integer'},
lispindent={args=1, base=1},
list2blob={args=1, base=1},
list2str={args={1, 2}, base=1},
@ -286,7 +317,7 @@ return {
pathshorten={args={1, 2}, base=1},
pow={args=2, base=1},
prevnonblank={args=1, base=1},
printf={args=varargs(1), base=2},
printf={args={1}, base=2},
prompt_getprompt={args=1, base=1},
prompt_setcallback={args={2, 2}, base=1},
prompt_setinterrupt={args={2, 2}, base=1},
@ -315,10 +346,18 @@ return {
resolve={args=1, base=1, fast=true},
reverse={args=1, base=1},
round={args=1, base=1, float_func="round"},
rpcnotify={args=varargs(2)},
rpcrequest={args=varargs(2)},
rpcnotify={args={2}},
rpcrequest={args={2}},
rpcstart={args={1, 2}},
rpcstop={args=1},
rpcstop={
args=1,
deprecated = {
'Use |jobstop()| instead to stop any job, or',
'`chanclose(id, "rpc")` to close RPC communication',
'without stopping the job. Use chanclose(id) to close',
'any socket.'
}
},
rubyeval={args=1, base=1},
screenattr={args=2, base=1},
screenchar={args=2, base=1},
@ -419,7 +458,7 @@ return {
taglist={args={1, 2}, base=1},
tan={args=1, base=1, float_func="tan"},
tanh={args=1, base=1, float_func="tanh"},
tempname={},
tempname={returns='string'},
termopen={args={1, 2}},
test_garbagecollect_now={},
test_write_list_log={args=1},
@ -428,16 +467,16 @@ return {
timer_start={args={2, 3}, base=1},
timer_stop={args=1, base=1},
timer_stopall={args=0},
tolower={args=1, base=1, fast=true},
toupper={args=1, base=1, fast=true},
tolower={args=1, base=1, fast=true, returns='string'},
toupper={args=1, base=1, fast=true, returns='string'},
tr={args=3, base=1},
trim={args={1, 3}, base=1},
trim={args={1, 3}, base=1, returns='string'},
trunc={args=1, base=1, float_func="trunc"},
type={args=1, base=1, fast=true},
undofile={args=1, base=1},
undofile={args=1, base=1, returns='string'},
undotree={},
uniq={args={1, 3}, base=1},
utf16idx={args={2, 4}, base=1},
uniq={args={1, 3}, base=1, returns='any[]|0'},
utf16idx={args={2, 4}, base=1, returns='integer'},
values={args=1, base=1},
virtcol={args={1, 2}, base=1},
virtcol2col={args=3, base=1},
@ -445,22 +484,22 @@ return {
wait={args={2,3}},
wildmenumode={},
win_execute={args={2, 3}, base=2},
win_findbuf={args=1, base=1},
win_getid={args={0, 2}, base=1},
win_gettype={args={0, 1}, base=1},
win_gotoid={args=1, base=1},
win_findbuf={args=1, base=1, returns='integer[]'},
win_getid={args={0, 2}, base=1, returns='integer'},
win_gettype={args={0, 1}, base=1, returns="'autocmd'|'command'|''|'loclist'|'popup'|'preview'|'quickfix'|'unknown'"},
win_gotoid={args=1, base=1, returns=VIMBOOL},
win_id2tabwin={args=1, base=1},
win_id2win={args=1, base=1},
win_move_separator={args=2, base=1},
win_move_statusline={args=2, base=1},
win_screenpos={args=1, base=1},
win_splitmove={args={2, 3}, base=1},
winbufnr={args=1, base=1},
wincol={},
windowsversion={fast=true},
winheight={args=1, base=1},
winbufnr={args=1, base=1, returns='integer'},
wincol={returns='integer'},
windowsversion={fast=true, returns='string'},
winheight={args=1, base=1, returns='integer'},
winlayout={args={0, 1}, base=1},
winline={},
winline={returns='integer'},
winnr={args={0, 1}, base=1},
winrestcmd={},
winrestview={args=1, base=1},