From 9a5678463c96baf3b39cb3083ddf0da87d39aa23 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sat, 4 Feb 2023 14:58:38 +0000 Subject: fix(treesitter): fix most diagnostics --- scripts/lua2dox.lua | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'scripts/lua2dox.lua') diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index 19f8f8141d..fc0e915307 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -286,7 +286,12 @@ local function checkComment4fn(Fn_magic, MagicLines) return fn_magic end -local types = { 'number', 'string', 'table', 'list', 'boolean', 'function' } +local types = { 'integer', 'number', 'string', 'table', 'list', 'boolean', 'function' } + +local tagged_types = { 'TSNode', 'LanguageTree' } + +-- Document these as 'table' +local alias_types = { 'Range' } --! \brief run the filter function TLua2DoX_filter.readfile(this, AppStamp, Filename) @@ -320,7 +325,12 @@ function TLua2DoX_filter.readfile(this, AppStamp, Filename) offset = 1 end - if string.sub(line, 3, 3) == '@' or string.sub(line, 1, 4) == '---@' then -- it's a magic comment + if vim.startswith(line, '---@cast') + or vim.startswith(line, '---@diagnostic') + or vim.startswith(line, '---@type') then + -- Ignore LSP directives + outStream:writeln('// gg:"' .. line .. '"') + elseif string.sub(line, 3, 3) == '@' or string.sub(line, 1, 4) == '---@' then -- it's a magic comment state = 'in_magic_comment' local magic = string.sub(line, 4 + offset) @@ -366,6 +376,17 @@ function TLua2DoX_filter.readfile(this, AppStamp, Filename) magic_split[type_index] = magic_split[type_index]:gsub(k, v) end end + + for _, type in ipairs(tagged_types) do + magic_split[type_index] = + magic_split[type_index]:gsub(type, '|%1|') + end + + for _, type in ipairs(alias_types) do + magic_split[type_index] = + magic_split[type_index]:gsub('^'..type..'$', 'table') + end + -- surround some types by () for _, type in ipairs(types) do magic_split[type_index] = @@ -373,6 +394,8 @@ function TLua2DoX_filter.readfile(this, AppStamp, Filename) magic_split[type_index] = magic_split[type_index]:gsub('^(' .. type .. '):?$', '(%1)') end + + end magic = table.concat(magic_split, ' ') -- cgit From 75e53341f37eeeda7d9be7f934249f7e5e4397e9 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 23 Feb 2023 15:19:52 +0000 Subject: perf(treesitter): smarter languagetree invalidation Problem: Treesitter injections are slow because all injected trees are invalidated on every change. Solution: Implement smarter invalidation to avoid reparsing injected regions. - In on_bytes, try and update self._regions as best we can. This PR just offsets any regions after the change. - Add valid flags for each region in self._regions. - Call on_bytes recursively for all children. - We still need to run the query every time for the top level tree. I don't know how to avoid this. However, if the new injection ranges don't change, then we re-use the old trees and avoid reparsing children. This should result in roughly a 2-3x reduction in tree parsing when the comment injections are enabled. --- scripts/lua2dox.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts/lua2dox.lua') diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index fc0e915307..17de0ea9b4 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -291,7 +291,7 @@ local types = { 'integer', 'number', 'string', 'table', 'list', 'boolean', 'func local tagged_types = { 'TSNode', 'LanguageTree' } -- Document these as 'table' -local alias_types = { 'Range' } +local alias_types = { 'Range4', 'Range6' } --! \brief run the filter function TLua2DoX_filter.readfile(this, AppStamp, Filename) -- cgit From 8414cfe7f4d8888698343cb54a3f373a28b365db Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 2 Mar 2023 20:46:59 +0100 Subject: docs: fix vim.treesitter tags Problem: Help tags like vim.treesitter.language.add() are confusing because `vim.treesitter.language` is (thankfully) not a user-facing module. Solution: Ignore the "fstem" when generating "treesitter" tags. --- scripts/lua2dox.lua | 55 ++++++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 26 deletions(-) (limited to 'scripts/lua2dox.lua') diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index 17de0ea9b4..d5b693a1a7 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -27,7 +27,10 @@ http://search.cpan.org/~alec/Doxygen-Lua-0.02/lib/Doxygen/Lua.pm Running ------- -This script "lua2dox.lua" gets called by "gen_vimdoc.py". +This script "lua2dox.lua" gets called by "gen_vimdoc.py". To debug, run gen_vimdoc.py with +--keep-tmpfiles: + + python3 scripts/gen_vimdoc.py -t treesitter --keep-tmpfiles Doxygen must be on your system. You can experiment like so: @@ -71,14 +74,14 @@ local function class() return newClass end ---! \brief write to stdout +-- write to stdout local function TCore_IO_write(Str) if Str then io.write(Str) end end ---! \brief write to stdout +-- write to stdout local function TCore_IO_writeln(Str) if Str then io.write(Str) @@ -86,12 +89,12 @@ local function TCore_IO_writeln(Str) io.write('\n') end ---! \brief trims a string +-- trims a string local function string_trim(Str) return Str:match('^%s*(.-)%s*$') end ---! \brief split a string +-- split a string --! --! \param Str --! \param Pattern @@ -117,12 +120,12 @@ local function string_split(Str, Pattern) end ------------------------------- ---! \brief file buffer +-- file buffer --! --! an input file buffer local TStream_Read = class() ---! \brief get contents of file +-- get contents of file --! --! \param Filename name of file to read (or nil == stdin) function TStream_Read.getContents(this, Filename) @@ -143,12 +146,12 @@ function TStream_Read.getContents(this, Filename) return filecontents end ---! \brief get lineno +-- get lineno function TStream_Read.getLineNo(this) return this.currentLineNo end ---! \brief get a line +-- get a line function TStream_Read.getLine(this) local line if this.currentLine then @@ -166,12 +169,12 @@ function TStream_Read.getLine(this) return line end ---! \brief save line fragment +-- save line fragment function TStream_Read.ungetLine(this, LineFrag) this.currentLine = LineFrag end ---! \brief is it eof? +-- is it eof? function TStream_Read.eof(this) if this.currentLine or this.currentLineNo <= this.contentsLen then return false @@ -179,31 +182,31 @@ function TStream_Read.eof(this) return true end ---! \brief output stream +-- output stream local TStream_Write = class() ---! \brief constructor +-- constructor function TStream_Write.init(this) this.tailLine = {} end ---! \brief write immediately +-- write immediately function TStream_Write.write(_, Str) TCore_IO_write(Str) end ---! \brief write immediately +-- write immediately function TStream_Write.writeln(_, Str) TCore_IO_writeln(Str) end ---! \brief write immediately +-- write immediately function TStream_Write.writelnComment(_, Str) TCore_IO_write('// ZZ: ') TCore_IO_writeln(Str) end ---! \brief write to tail +-- write to tail function TStream_Write.writelnTail(this, Line) if not Line then Line = '' @@ -211,7 +214,7 @@ function TStream_Write.writelnTail(this, Line) table.insert(this.tailLine, Line) end ---! \brief output tail lines +-- output tail lines function TStream_Write.write_tailLines(this) for _, line in ipairs(this.tailLine) do TCore_IO_writeln(line) @@ -219,17 +222,17 @@ function TStream_Write.write_tailLines(this) TCore_IO_write('// Lua2DoX new eof') end ---! \brief input filter +-- input filter local TLua2DoX_filter = class() ---! \brief allow us to do errormessages +-- allow us to do errormessages function TLua2DoX_filter.warning(this, Line, LineNo, Legend) this.outStream:writelnTail( '//! \todo warning! ' .. Legend .. ' (@' .. LineNo .. ')"' .. Line .. '"' ) end ---! \brief trim comment off end of string +-- trim comment off end of string --! --! If the string has a comment on the end, this trims it off. --! @@ -243,7 +246,7 @@ local function TString_removeCommentFromLine(Line) return Line, tailComment end ---! \brief get directive from magic +-- get directive from magic local function getMagicDirective(Line) local macro, tail local macroStr = '[\\@]' @@ -264,7 +267,7 @@ local function getMagicDirective(Line) return macro, tail end ---! \brief check comment for fn +-- check comment for fn local function checkComment4fn(Fn_magic, MagicLines) local fn_magic = Fn_magic -- TCore_IO_writeln('// checkComment4fn "' .. MagicLines .. '"') @@ -293,7 +296,7 @@ local tagged_types = { 'TSNode', 'LanguageTree' } -- Document these as 'table' local alias_types = { 'Range4', 'Range6' } ---! \brief run the filter +-- run the filter function TLua2DoX_filter.readfile(this, AppStamp, Filename) local inStream = TStream_Read() local outStream = TStream_Write() @@ -524,10 +527,10 @@ function TLua2DoX_filter.readfile(this, AppStamp, Filename) end end ---! \brief this application +-- this application local TApp = class() ---! \brief constructor +-- constructor function TApp.init(this) this.timestamp = os.date('%c %Z', os.time()) this.name = 'Lua2DoX' -- cgit From 57f26e0903af0e4569a70d310ca18696e7680c74 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Fri, 3 Mar 2023 13:49:22 +0100 Subject: docs: lua2dox.lua debugging --- scripts/lua2dox.lua | 57 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 18 deletions(-) (limited to 'scripts/lua2dox.lua') diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index d5b693a1a7..b99cd955f4 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -24,13 +24,17 @@ Lua-to-Doxygen converter Partially from lua2dox http://search.cpan.org/~alec/Doxygen-Lua-0.02/lib/Doxygen/Lua.pm -Running +RUNNING ------- -This script "lua2dox.lua" gets called by "gen_vimdoc.py". To debug, run gen_vimdoc.py with ---keep-tmpfiles: +This script "lua2dox.lua" gets called by "gen_vimdoc.py". - python3 scripts/gen_vimdoc.py -t treesitter --keep-tmpfiles +DEBUGGING/DEVELOPING +--------------------- + +1. To debug, run gen_vimdoc.py with --keep-tmpfiles: + python3 scripts/gen_vimdoc.py -t treesitter --keep-tmpfiles +2. The filtered result will be written to ./tmp-lua2dox-doc/….lua.c Doxygen must be on your system. You can experiment like so: @@ -52,6 +56,9 @@ However I have put in a hack that will insert the "missing" close paren. The effect is that you will get the function documented, but not with the parameter list you might expect. ]] +local _debug_outfile = nil +local _debug_output = {} + local function class() local newClass = {} -- a new class newClass -- the class will be the metatable for all its newInstanceects, @@ -78,15 +85,16 @@ end local function TCore_IO_write(Str) if Str then io.write(Str) + if _debug_outfile then + table.insert(_debug_output, Str) + end end end -- write to stdout local function TCore_IO_writeln(Str) - if Str then - io.write(Str) - end - io.write('\n') + TCore_IO_write(Str) + TCore_IO_write('\n') end -- trims a string @@ -296,8 +304,8 @@ local tagged_types = { 'TSNode', 'LanguageTree' } -- Document these as 'table' local alias_types = { 'Range4', 'Range6' } --- run the filter -function TLua2DoX_filter.readfile(this, AppStamp, Filename) +-- Processes the file and writes filtered output to stdout. +function TLua2DoX_filter.filter(this, AppStamp, Filename) local inStream = TStream_Read() local outStream = TStream_Write() this.outStream = outStream -- save to this obj @@ -554,8 +562,7 @@ local This_app = TApp() --main -local argv1 = arg[1] -if argv1 == '--help' then +if arg[1] == '--help' then TCore_IO_writeln(This_app:getVersion()) TCore_IO_writeln(This_app:getCopyright()) TCore_IO_writeln([[ @@ -566,16 +573,30 @@ if argv1 == '--help' then : interprets filename --version : show version/copyright info --help : this help text]]) -elseif argv1 == '--version' then +elseif arg[1] == '--version' then TCore_IO_writeln(This_app:getVersion()) TCore_IO_writeln(This_app:getCopyright()) -else - -- it's a filter - local appStamp = This_app:getRunStamp() - local filename = argv1 +else -- It's a filter. + local filename = arg[1] + + if arg[2] == '--outdir' then + local outdir = arg[3] + if type(outdir) ~= 'string' or (0 ~= vim.fn.filereadable(outdir) and 0 == vim.fn.isdirectory(outdir)) then + error(('invalid --outdir: "%s"'):format(tostring(outdir))) + end + vim.fn.mkdir(outdir, 'p') + _debug_outfile = string.format('%s/%s.c', outdir, vim.fs.basename(filename)) + end + local appStamp = This_app:getRunStamp() local filter = TLua2DoX_filter() - filter:readfile(appStamp, filename) + filter:filter(appStamp, filename) + + if _debug_outfile then + local f = assert(io.open(_debug_outfile, 'w')) + f:write(table.concat(_debug_output)) + f:close() + end end --eof -- cgit From 58bbc2ea0b3dfed13471e8cc0447d7598be24276 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Fri, 10 Mar 2023 16:40:27 +0000 Subject: refactor(treesitter): add Range type aliase for Range4|Range6 --- scripts/lua2dox.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts/lua2dox.lua') diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index b99cd955f4..de9f2926f2 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -302,7 +302,7 @@ local types = { 'integer', 'number', 'string', 'table', 'list', 'boolean', 'func local tagged_types = { 'TSNode', 'LanguageTree' } -- Document these as 'table' -local alias_types = { 'Range4', 'Range6' } +local alias_types = { 'Range', 'Range4', 'Range6', 'TSMetadata' } -- Processes the file and writes filtered output to stdout. function TLua2DoX_filter.filter(this, AppStamp, Filename) -- cgit From 4e4203f71b0b9bb2ca4ad9abd2fbf4ea1deaf9a6 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Thu, 23 Mar 2023 11:23:51 +0000 Subject: fix(treesitter): annotations - Begin using `@package` in place of `@private` for functions that are accessed internally but outside their defined class. - Rename Node -> TSP.Node --- scripts/lua2dox.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'scripts/lua2dox.lua') diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index de9f2926f2..014934aebe 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -336,6 +336,8 @@ function TLua2DoX_filter.filter(this, AppStamp, Filename) offset = 1 end + line = line:gsub('@package', '@private') + if vim.startswith(line, '---@cast') or vim.startswith(line, '---@diagnostic') or vim.startswith(line, '---@type') then -- cgit From c0952e62fd0ee16a3275bb69e0de04c836b39015 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 7 Jun 2023 13:52:23 +0100 Subject: feat(lua): add `vim.system()` feat(lua): add vim.system() Problem: Handling system commands in Lua is tedious and error-prone: - vim.fn.jobstart() is vimscript and comes with all limitations attached to typval. - vim.loop.spawn is too low level Solution: Add vim.system(). Partly inspired by Python's subprocess module Does not expose any libuv objects. --- scripts/lua2dox.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts/lua2dox.lua') diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index 014934aebe..bb5214f091 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -340,6 +340,7 @@ function TLua2DoX_filter.filter(this, AppStamp, Filename) if vim.startswith(line, '---@cast') or vim.startswith(line, '---@diagnostic') + or vim.startswith(line, '---@overload') or vim.startswith(line, '---@type') then -- Ignore LSP directives outStream:writeln('// gg:"' .. line .. '"') -- cgit From 3fd504dbec39eeced1bea17d9f3bd06de7f3e4d8 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sun, 16 Jul 2023 09:34:50 +0100 Subject: docs: handle whitespace in emmycomments --- scripts/lua2dox.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'scripts/lua2dox.lua') diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index bb5214f091..b0eb4c086c 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -328,6 +328,7 @@ function TLua2DoX_filter.filter(this, AppStamp, Filename) line = string_trim(inStream:getLine()) l = l + 1 if string.sub(line, 1, 2) == '--' then -- it's a comment + line = line:gsub('^---%s+@', '---@') -- Allow people to write style similar to EmmyLua (since they are basically the same) -- instead of silently skipping things that start with --- if string.sub(line, 3, 3) == '@' then -- it's a magic comment @@ -341,6 +342,7 @@ function TLua2DoX_filter.filter(this, AppStamp, Filename) if vim.startswith(line, '---@cast') or vim.startswith(line, '---@diagnostic') or vim.startswith(line, '---@overload') + or vim.startswith(line, '---@meta') or vim.startswith(line, '---@type') then -- Ignore LSP directives outStream:writeln('// gg:"' .. line .. '"') -- cgit From c2d7c2826ca77b0ca31bec511fdcdf1e4abaf946 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 17 Jul 2023 15:13:54 +0100 Subject: docs(lua): change *lua-foo* -> *vim.foo* --- scripts/lua2dox.lua | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'scripts/lua2dox.lua') diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index b0eb4c086c..3f0d0505dd 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -416,6 +416,11 @@ function TLua2DoX_filter.filter(this, AppStamp, Filename) magic = table.concat(magic_split, ' ') + if magic_split[1] == 'defgroup' or magic_split[1] == 'addtogroup' then + -- Can't use '.' in defgroup, so convert to '--' + magic = magic:gsub('%.', '-dot-') + end + outStream:writeln('/// @' .. magic) fn_magic = checkComment4fn(fn_magic, magic) end -- cgit From 6e9b204afbe5f16c44a2697aed07aafff36bf856 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 17 Jul 2023 16:39:57 +0100 Subject: fix: doc errors --- scripts/lua2dox.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'scripts/lua2dox.lua') diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index 3f0d0505dd..55cb566ca3 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -363,6 +363,8 @@ function TLua2DoX_filter.filter(this, AppStamp, Filename) magic = magic:gsub('^return%s+.*%((' .. type .. ')%)', 'return %1') magic = magic:gsub('^return%s+.*%((' .. type .. '|nil)%)', 'return %1') end + -- handle the return of vim.spell.check + magic = magic:gsub('({.*}%[%])', '`%1`') magic_split = string_split(magic, ' ') end -- cgit From 9fcb0a64ee9195434113c10cb6e958cfe3b2c2cd Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 18 Jul 2023 12:24:53 +0100 Subject: refactor(lua2dox): overhaul (#24386) --- scripts/lua2dox.lua | 774 ++++++++++++++++++++-------------------------------- 1 file changed, 302 insertions(+), 472 deletions(-) (limited to 'scripts/lua2dox.lua') diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index 55cb566ca3..be72b9e1c0 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -1,6 +1,6 @@ ---[[-------------------------------------------------------------------------- --- Copyright (C) 2012 by Simon Dales -- --- simon@purrsoft.co.uk -- +----------------------------------------------------------------------------- +-- Copyright (C) 2012 by Simon Dales -- +-- simon@purrsoft.co.uk -- -- -- -- This program is free software; you can redistribute it and/or modify -- -- it under the terms of the GNU General Public License as published by -- @@ -16,7 +16,7 @@ -- along with this program; if not, write to the -- -- Free Software Foundation, Inc., -- -- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -- -----------------------------------------------------------------------------]] +----------------------------------------------------------------------------- --[[! Lua-to-Doxygen converter @@ -48,536 +48,364 @@ It only has to be good enough for doxygen to see it as legal. One limitation is that each line is treated separately (except for long comments). The implication is that class and function declarations must be on the same line. -Some functions can have their parameter lists extended over multiple lines to make it look neat. -Managing this where there are also some comments is a bit more coding than I want to do at this stage, -so it will probably not document accurately if we do do this. -However I have put in a hack that will insert the "missing" close paren. +There is hack that will insert the "missing" close paren. The effect is that you will get the function documented, but not with the parameter list you might expect. ]] -local _debug_outfile = nil -local _debug_output = {} - -local function class() - local newClass = {} -- a new class newClass - -- the class will be the metatable for all its newInstanceects, - -- and they will look up their methods in it. - newClass.__index = newClass - - -- expose a constructor which can be called by () - setmetatable(newClass, { - __call = function(class_tbl, ...) - local newInstance = {} - setmetatable(newInstance, newClass) - --if init then - -- init(newInstance,...) - if class_tbl.init then - class_tbl.init(newInstance, ...) - end - return newInstance - end - }) - return newClass -end +local TYPES = { 'integer', 'number', 'string', 'table', 'list', 'boolean', 'function' } --- write to stdout -local function TCore_IO_write(Str) - if Str then - io.write(Str) - if _debug_outfile then - table.insert(_debug_output, Str) - end - end -end +local TAGGED_TYPES = { 'TSNode', 'LanguageTree' } --- write to stdout -local function TCore_IO_writeln(Str) - TCore_IO_write(Str) - TCore_IO_write('\n') -end +-- Document these as 'table' +local ALIAS_TYPES = { 'Range', 'Range4', 'Range6', 'TSMetadata' } --- trims a string -local function string_trim(Str) - return Str:match('^%s*(.-)%s*$') -end +local debug_outfile = nil --- @type string? +local debug_output = {} --- split a string ---! ---! \param Str ---! \param Pattern ---! \returns table of string fragments ----@return string[] -local function string_split(Str, Pattern) - local splitStr = {} - local fpat = '(.-)' .. Pattern - local last_end = 1 - local str, e, cap = string.find(Str, fpat, 1) - while str do - if str ~= 1 or cap ~= '' then - table.insert(splitStr, cap) - end - last_end = e + 1 - str, e, cap = string.find(Str, fpat, last_end) +--- write to stdout +--- @param str? string +local function write(str) + if not str then + return end - if last_end <= #Str then - cap = string.sub(Str, last_end) - table.insert(splitStr, cap) + + io.write(str) + if debug_outfile then + table.insert(debug_output, str) end - return splitStr end -------------------------------- --- file buffer ---! ---! an input file buffer -local TStream_Read = class() - --- get contents of file ---! ---! \param Filename name of file to read (or nil == stdin) -function TStream_Read.getContents(this, Filename) - assert(Filename, ('invalid file: %s'):format(Filename)) +--- write to stdout +--- @param str? string +local function writeln(str) + write(str) + write('\n') +end + +--- an input file buffer +--- @class StreamRead +--- @field currentLine string? +--- @field contentsLen integer +--- @field currentLineNo integer +--- @field filecontents string[] +local StreamRead = {} + +--- @return StreamRead +--- @param filename string +function StreamRead.new(filename) + assert(filename, ('invalid file: %s'):format(filename)) -- get lines from file -- syphon lines to our table - local filecontents = {} - for line in io.lines(Filename) do - table.insert(filecontents, line) - end - - if filecontents then - this.filecontents = filecontents - this.contentsLen = #filecontents - this.currentLineNo = 1 + local filecontents = {} --- @type string[] + for line in io.lines(filename) do + filecontents[#filecontents+1] = line end - return filecontents -end - --- get lineno -function TStream_Read.getLineNo(this) - return this.currentLineNo + return setmetatable({ + filecontents = filecontents, + contentsLen = #filecontents, + currentLineNo = 1, + }, { __index = StreamRead }) end -- get a line -function TStream_Read.getLine(this) - local line - if this.currentLine then - line = this.currentLine - this.currentLine = nil - else - -- get line - if this.currentLineNo <= this.contentsLen then - line = this.filecontents[this.currentLineNo] - this.currentLineNo = this.currentLineNo + 1 - else - line = '' - end +function StreamRead:getLine() + if self.currentLine then + self.currentLine = nil + return self.currentLine end - return line + + -- get line + if self.currentLineNo <= self.contentsLen then + local line = self.filecontents[self.currentLineNo] + self.currentLineNo = self.currentLineNo + 1 + return line + end + + return '' end -- save line fragment -function TStream_Read.ungetLine(this, LineFrag) - this.currentLine = LineFrag +--- @param line_fragment string +function StreamRead:ungetLine(line_fragment) + self.currentLine = line_fragment end -- is it eof? -function TStream_Read.eof(this) - if this.currentLine or this.currentLineNo <= this.contentsLen then - return false +function StreamRead:eof() + return not self.currentLine and self.currentLineNo > self.contentsLen +end + +-- input filter +--- @class Lua2DoxFilter +local Lua2DoxFilter = {} +setmetatable(Lua2DoxFilter, { __index = Lua2DoxFilter }) + +--- trim comment off end of string +--- +--- @param line string +--- @return string, string? +local function removeCommentFromLine(line) + local pos_comment = line:find('%-%-') + if not pos_comment then + return line end - return true + return line:sub(1, pos_comment - 1), line:sub(pos_comment) end --- output stream -local TStream_Write = class() +--- @param line string +--- @param generics table +--- @return string? +local function process_magic(line, generics) + line = line:gsub('^%s+@', '@') + line = line:gsub('@package', '@private') --- constructor -function TStream_Write.init(this) - this.tailLine = {} -end + if not vim.startswith(line, '@') then -- it's a magic comment + return '/// ' .. line + end --- write immediately -function TStream_Write.write(_, Str) - TCore_IO_write(Str) -end + local magic = line:sub(2) + local magic_split = vim.split(magic, ' ', { plain = true }) + local directive = magic_split[1] --- write immediately -function TStream_Write.writeln(_, Str) - TCore_IO_writeln(Str) -end + if vim.list_contains({ + 'cast', 'diagnostic', 'overload', 'meta', 'type' + }, directive) then + -- Ignore LSP directives + return '// gg:"' .. line .. '"' + end --- write immediately -function TStream_Write.writelnComment(_, Str) - TCore_IO_write('// ZZ: ') - TCore_IO_writeln(Str) -end + if directive == 'defgroup' or directive == 'addtogroup' then + -- Can't use '.' in defgroup, so convert to '--' + return '/// @' .. magic:gsub('%.', '-dot-') + end --- write to tail -function TStream_Write.writelnTail(this, Line) - if not Line then - Line = '' + if directive == 'generic' then + local generic_name, generic_type = line:match('@generic%s*(%w+)%s*:?%s*(.*)') + if generic_type == '' then + generic_type = 'any' + end + generics[generic_name] = generic_type + return end - table.insert(this.tailLine, Line) -end --- output tail lines -function TStream_Write.write_tailLines(this) - for _, line in ipairs(this.tailLine) do - TCore_IO_writeln(line) + local type_index = 2 + + if directive == 'param' then + for _, type in ipairs(TYPES) do + magic = magic:gsub('^param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. ')%)', 'param %1 %2') + magic = + magic:gsub('^param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. '|nil)%)', 'param %1 %2') + end + magic_split = vim.split(magic, ' ', { plain = true }) + type_index = 3 + elseif directive == 'return' then + for _, type in ipairs(TYPES) do + magic = magic:gsub('^return%s+.*%((' .. type .. ')%)', 'return %1') + magic = magic:gsub('^return%s+.*%((' .. type .. '|nil)%)', 'return %1') + end + -- handle the return of vim.spell.check + magic = magic:gsub('({.*}%[%])', '`%1`') + magic_split = vim.split(magic, ' ', { plain = true }) end - TCore_IO_write('// Lua2DoX new eof') -end --- input filter -local TLua2DoX_filter = class() + local ty = magic_split[type_index] --- allow us to do errormessages -function TLua2DoX_filter.warning(this, Line, LineNo, Legend) - this.outStream:writelnTail( - '//! \todo warning! ' .. Legend .. ' (@' .. LineNo .. ')"' .. Line .. '"' - ) -end + if ty then + -- fix optional parameters + if magic_split[2]:find('%?$') then + if not ty:find('nil') then + ty = ty .. '|nil' + end + magic_split[2] = magic_split[2]:sub(1, -2) + end + + -- replace generic types + for k, v in pairs(generics) do + ty = ty:gsub(k, v) --- @type string + end + + for _, type in ipairs(TAGGED_TYPES) do + ty = ty:gsub(type, '|%1|') + end + + for _, type in ipairs(ALIAS_TYPES) do + ty = ty:gsub('^'..type..'$', 'table') --- @type string + end + + -- surround some types by () + for _, type in ipairs(TYPES) do + ty = ty + :gsub('^(' .. type .. '|nil):?$', '(%1)') + :gsub('^(' .. type .. '):?$', '(%1)') + end + + magic_split[type_index] = ty --- trim comment off end of string ---! ---! If the string has a comment on the end, this trims it off. ---! -local function TString_removeCommentFromLine(Line) - local pos_comment = string.find(Line, '%-%-') - local tailComment - if pos_comment then - Line = string.sub(Line, 1, pos_comment - 1) - tailComment = string.sub(Line, pos_comment) end - return Line, tailComment + + magic = table.concat(magic_split, ' ') + + return '/// @' .. magic end --- get directive from magic -local function getMagicDirective(Line) - local macro, tail - local macroStr = '[\\@]' - local pos_macro = string.find(Line, macroStr) - if pos_macro then - --! ....\\ macro...stuff - --! ....\@ macro...stuff - local line = string.sub(Line, pos_macro + 1) - local space = string.find(line, '%s+') - if space then - macro = string.sub(line, 1, space - 1) - tail = string_trim(string.sub(line, space + 1)) +--- @param line string +--- @param in_stream StreamRead +--- @return string +local function process_block_comment(line, in_stream) + local comment_parts = {} --- @type string[] + local done --- @type boolean? + + while not done and not in_stream:eof() do + local thisComment --- @type string? + local closeSquare = line:find(']]') + if not closeSquare then -- need to look on another line + thisComment = line .. '\n' + line = in_stream:getLine() else - macro = line - tail = '' + thisComment = line:sub(1, closeSquare - 1) + done = true + + -- unget the tail of the line + -- in most cases it's empty. This may make us less efficient but + -- easier to program + in_stream:ungetLine(vim.trim(line:sub(closeSquare + 2))) end + comment_parts[#comment_parts+1] = thisComment end - return macro, tail + + local comment = table.concat(comment_parts) + + if comment:sub(1, 1) == '@' then -- it's a long magic comment + return '/*' .. comment .. '*/ ' + end + + -- discard + return '/* zz:' .. comment .. '*/ ' end --- check comment for fn -local function checkComment4fn(Fn_magic, MagicLines) - local fn_magic = Fn_magic - -- TCore_IO_writeln('// checkComment4fn "' .. MagicLines .. '"') +--- @param line string +--- @return string +local function process_function_header(line) + local pos_fn = assert(line:find('function')) + -- we've got a function + local fn = removeCommentFromLine(vim.trim(line:sub(pos_fn + 8))) + + if fn:sub(1, 1) == '(' then + -- it's an anonymous function + return '// ZZ: '..line + end + -- fn has a name, so is interesting - local magicLines = string_split(MagicLines, '\n') + -- want to fix for iffy declarations + if fn:find('[%({]') then + -- we might have a missing close paren + if not fn:find('%)') then + fn = fn .. ' ___MissingCloseParenHere___)' + end + end - local macro, tail + -- Big hax + if fn:find(':') then + fn = fn:gsub(':', '.', 1) - for _, line in ipairs(magicLines) do - macro, tail = getMagicDirective(line) - if macro == 'fn' then - fn_magic = tail - -- TCore_IO_writeln('// found fn "' .. fn_magic .. '"') - --else - --TCore_IO_writeln('// not found fn "' .. line .. '"') + local paren_start = fn:find('(', 1, true) + local paren_finish = fn:find(')', 1, true) + + -- Nothing in between the parens + local comma --- @type string + if paren_finish == paren_start + 1 then + comma = '' + else + comma = ', ' end + + fn = fn:sub(1, paren_start) + .. 'self' + .. comma + .. fn:sub(paren_start + 1) end - return fn_magic + -- add vanilla function + return 'function ' .. fn .. '{}' end -local types = { 'integer', 'number', 'string', 'table', 'list', 'boolean', 'function' } - -local tagged_types = { 'TSNode', 'LanguageTree' } +--- @param line string +--- @param in_stream StreamRead +--- @param generics table> +--- @return string? +local function process_line(line, in_stream, generics) + if vim.startswith(line, '---') then + return process_magic(line:sub(4), generics) + end --- Document these as 'table' -local alias_types = { 'Range', 'Range4', 'Range6', 'TSMetadata' } + if vim.startswith(line, '--'..'[[') then -- it's a long comment + return process_block_comment(line:sub(5), in_stream) + end --- Processes the file and writes filtered output to stdout. -function TLua2DoX_filter.filter(this, AppStamp, Filename) - local inStream = TStream_Read() - local outStream = TStream_Write() - this.outStream = outStream -- save to this obj - - if inStream:getContents(Filename) then - -- output the file - local line - local fn_magic -- function name/def from magic comment - - outStream:writelnTail('// #######################') - outStream:writelnTail('// app run:' .. AppStamp) - outStream:writelnTail('// #######################') - outStream:writelnTail() - - local state = '' -- luacheck: ignore 231 variable is set but never accessed. - local offset = 0 - local generic = {} - local l = 0 - while not (inStream:eof()) do - line = string_trim(inStream:getLine()) - l = l + 1 - if string.sub(line, 1, 2) == '--' then -- it's a comment - line = line:gsub('^---%s+@', '---@') - -- Allow people to write style similar to EmmyLua (since they are basically the same) - -- instead of silently skipping things that start with --- - if string.sub(line, 3, 3) == '@' then -- it's a magic comment - offset = 0 - elseif string.sub(line, 1, 4) == '---@' then -- it's a magic comment - offset = 1 - end - - line = line:gsub('@package', '@private') - - if vim.startswith(line, '---@cast') - or vim.startswith(line, '---@diagnostic') - or vim.startswith(line, '---@overload') - or vim.startswith(line, '---@meta') - or vim.startswith(line, '---@type') then - -- Ignore LSP directives - outStream:writeln('// gg:"' .. line .. '"') - elseif string.sub(line, 3, 3) == '@' or string.sub(line, 1, 4) == '---@' then -- it's a magic comment - state = 'in_magic_comment' - local magic = string.sub(line, 4 + offset) - - local magic_split = string_split(magic, ' ') - if magic_split[1] == 'param' then - for _, type in ipairs(types) do - magic = magic:gsub('^param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. ')%)', 'param %1 %2') - magic = - magic:gsub('^param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. '|nil)%)', 'param %1 %2') - end - magic_split = string_split(magic, ' ') - elseif magic_split[1] == 'return' then - for _, type in ipairs(types) do - magic = magic:gsub('^return%s+.*%((' .. type .. ')%)', 'return %1') - magic = magic:gsub('^return%s+.*%((' .. type .. '|nil)%)', 'return %1') - end - -- handle the return of vim.spell.check - magic = magic:gsub('({.*}%[%])', '`%1`') - magic_split = string_split(magic, ' ') - end - - if magic_split[1] == 'generic' then - local generic_name, generic_type = line:match('@generic%s*(%w+)%s*:?%s*(.*)') - if generic_type == '' then - generic_type = 'any' - end - generic[generic_name] = generic_type - else - local type_index = 2 - if magic_split[1] == 'param' then - type_index = type_index + 1 - end - - if magic_split[type_index] then - -- fix optional parameters - if magic_split[type_index] and magic_split[2]:find('%?$') then - if not magic_split[type_index]:find('nil') then - magic_split[type_index] = magic_split[type_index] .. '|nil' - end - magic_split[2] = magic_split[2]:sub(1, -2) - end - -- replace generic types - if magic_split[type_index] then - for k, v in pairs(generic) do - magic_split[type_index] = magic_split[type_index]:gsub(k, v) - end - end - - for _, type in ipairs(tagged_types) do - magic_split[type_index] = - magic_split[type_index]:gsub(type, '|%1|') - end - - for _, type in ipairs(alias_types) do - magic_split[type_index] = - magic_split[type_index]:gsub('^'..type..'$', 'table') - end - - -- surround some types by () - for _, type in ipairs(types) do - magic_split[type_index] = - magic_split[type_index]:gsub('^(' .. type .. '|nil):?$', '(%1)') - magic_split[type_index] = - magic_split[type_index]:gsub('^(' .. type .. '):?$', '(%1)') - end - - - end - - magic = table.concat(magic_split, ' ') - - if magic_split[1] == 'defgroup' or magic_split[1] == 'addtogroup' then - -- Can't use '.' in defgroup, so convert to '--' - magic = magic:gsub('%.', '-dot-') - end - - outStream:writeln('/// @' .. magic) - fn_magic = checkComment4fn(fn_magic, magic) - end - elseif string.sub(line, 3, 3) == '-' then -- it's a nonmagic doc comment - local comment = string.sub(line, 4) - outStream:writeln('/// ' .. comment) - elseif string.sub(line, 3, 4) == '[[' then -- it's a long comment - line = string.sub(line, 5) -- nibble head - local comment = '' - local closeSquare, hitend, thisComment - while not hitend and (not inStream:eof()) do - closeSquare = string.find(line, ']]') - if not closeSquare then -- need to look on another line - thisComment = line .. '\n' - line = inStream:getLine() - else - thisComment = string.sub(line, 1, closeSquare - 1) - hitend = true - - -- unget the tail of the line - -- in most cases it's empty. This may make us less efficient but - -- easier to program - inStream:ungetLine(string_trim(string.sub(line, closeSquare + 2))) - end - comment = comment .. thisComment - end - if string.sub(comment, 1, 1) == '@' then -- it's a long magic comment - outStream:write('/*' .. comment .. '*/ ') - fn_magic = checkComment4fn(fn_magic, comment) - else -- discard - outStream:write('/* zz:' .. comment .. '*/ ') - fn_magic = nil - end - -- TODO(justinmk): Uncomment this if we want "--" lines to continue the - -- preceding magic ("---", "--@", …) lines. - -- elseif state == 'in_magic_comment' then -- next line of magic comment - -- outStream:writeln('/// '.. line:sub(3)) - else -- discard - outStream:writeln('// zz:"' .. line .. '"') - fn_magic = nil - end - elseif string.find(line, '^function') or string.find(line, '^local%s+function') then - generic = {} - state = 'in_function' -- it's a function - local pos_fn = string.find(line, 'function') - -- function - -- ....v... - if pos_fn then - -- we've got a function - local fn = TString_removeCommentFromLine(string_trim(string.sub(line, pos_fn + 8))) - if fn_magic then - fn = fn_magic - end - - if string.sub(fn, 1, 1) == '(' then - -- it's an anonymous function - outStream:writelnComment(line) - else - -- fn has a name, so is interesting - - -- want to fix for iffy declarations - local open_paren = string.find(fn, '[%({]') - if open_paren then - -- we might have a missing close paren - if not string.find(fn, '%)') then - fn = fn .. ' ___MissingCloseParenHere___)' - end - end - - -- Big hax - if string.find(fn, ':') then - -- TODO: We need to add a first parameter of "SELF" here - -- local colon_place = string.find(fn, ":") - -- local name = string.sub(fn, 1, colon_place) - fn = fn:gsub(':', '.', 1) - outStream:writeln('/// @param self') - - local paren_start = string.find(fn, '(', 1, true) - local paren_finish = string.find(fn, ')', 1, true) - - -- Nothing in between the parens - local comma - if paren_finish == paren_start + 1 then - comma = '' - else - comma = ', ' - end - fn = string.sub(fn, 1, paren_start) - .. 'self' - .. comma - .. string.sub(fn, paren_start + 1) - end - - -- add vanilla function - outStream:writeln('function ' .. fn .. '{}') - end - else - this:warning(inStream:getLineNo(), 'something weird here') - end - fn_magic = nil -- mustn't inadvertently use it again - - -- TODO: If we can make this learn how to generate these, that would be helpful. - -- elseif string.find(line, "^M%['.*'%] = function") then - -- state = 'in_function' -- it's a function - -- outStream:writeln("function textDocument/publishDiagnostics(...){}") - - -- fn_magic = nil -- mustn't inadvertently use it again - else - state = '' -- unknown - if #line > 0 then -- we don't know what this line means, so just comment it out - outStream:writeln('// zz: ' .. line) - else - outStream:writeln() -- keep this line blank - end - end - end + if line:find('^function') or line:find('^local%s+function') then + return process_function_header(line) + end - -- output the tail - outStream:write_tailLines() - else - outStream:writeln('!empty file') + if #line > 0 then -- we don't know what this line means, so just comment it out + return '// zz: ' .. line end + + return '' end --- this application -local TApp = class() +-- Processes the file and writes filtered output to stdout. +---@param filename string +function Lua2DoxFilter:filter(filename) + local in_stream = StreamRead.new(filename) --- constructor -function TApp.init(this) - this.timestamp = os.date('%c %Z', os.time()) - this.name = 'Lua2DoX' - this.version = '0.2 20130128' - this.copyright = 'Copyright (c) Simon Dales 2012-13' -end + local generics = {} --- @type table -function TApp.getRunStamp(this) - return this.name .. ' (' .. this.version .. ') ' .. this.timestamp -end + while not in_stream:eof() do + local line = vim.trim(in_stream:getLine()) + + local out_line = process_line(line, in_stream, generics) + + if not vim.startswith(line, '---') then + generics = {} + end -function TApp.getVersion(this) - return this.name .. ' (' .. this.version .. ') ' + if out_line then + writeln(out_line) + end + end end -function TApp.getCopyright(this) - return this.copyright +--- @class TApp +--- @field timestamp string|osdate +--- @field name string +--- @field version string +--- @field copyright string +--- this application +local TApp = { + timestamp = os.date('%c %Z', os.time()), + name = 'Lua2DoX', + version = '0.2 20130128', + copyright = 'Copyright (c) Simon Dales 2012-13' +} + +setmetatable(TApp, { __index = TApp }) + +function TApp:getRunStamp() + return self.name .. ' (' .. self.version .. ') ' .. self.timestamp end -local This_app = TApp() +function TApp:getVersion() + return self.name .. ' (' .. self.version .. ') ' +end --main if arg[1] == '--help' then - TCore_IO_writeln(This_app:getVersion()) - TCore_IO_writeln(This_app:getCopyright()) - TCore_IO_writeln([[ + writeln(TApp:getVersion()) + writeln(TApp.copyright) + writeln([[ run as: nvim -l scripts/lua2dox.lua -------------- @@ -586,8 +414,8 @@ if arg[1] == '--help' then --version : show version/copyright info --help : this help text]]) elseif arg[1] == '--version' then - TCore_IO_writeln(This_app:getVersion()) - TCore_IO_writeln(This_app:getCopyright()) + writeln(TApp:getVersion()) + writeln(TApp.copyright) else -- It's a filter. local filename = arg[1] @@ -597,18 +425,20 @@ else -- It's a filter. error(('invalid --outdir: "%s"'):format(tostring(outdir))) end vim.fn.mkdir(outdir, 'p') - _debug_outfile = string.format('%s/%s.c', outdir, vim.fs.basename(filename)) + debug_outfile = string.format('%s/%s.c', outdir, vim.fs.basename(filename)) end - local appStamp = This_app:getRunStamp() - local filter = TLua2DoX_filter() - filter:filter(appStamp, filename) + Lua2DoxFilter:filter(filename) - if _debug_outfile then - local f = assert(io.open(_debug_outfile, 'w')) - f:write(table.concat(_debug_output)) + -- output the tail + writeln('// #######################') + writeln('// app run:' .. TApp:getRunStamp()) + writeln('// #######################') + writeln() + + if debug_outfile then + local f = assert(io.open(debug_outfile, 'w')) + f:write(table.concat(debug_output)) f:close() end end - ---eof -- cgit From be74807eef13ff8c90d55cf8b22b01d6d33b1641 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 18 Jul 2023 15:42:30 +0100 Subject: docs(lua): more improvements (#24387) * docs(lua): teach lua2dox how to table * docs(lua): teach gen_vimdoc.py about local functions No more need to mark local functions with @private * docs(lua): mention @nodoc and @meta in dev-lua-doc * fixup! Co-authored-by: Justin M. Keyes --------- Co-authored-by: Justin M. Keyes --- scripts/lua2dox.lua | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'scripts/lua2dox.lua') diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index be72b9e1c0..9a666ea629 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -160,6 +160,7 @@ end local function process_magic(line, generics) line = line:gsub('^%s+@', '@') line = line:gsub('@package', '@private') + line = line:gsub('@nodoc', '@private') if not vim.startswith(line, '@') then -- it's a magic comment return '/// ' .. line @@ -327,6 +328,11 @@ local function process_function_header(line) .. fn:sub(paren_start + 1) end + if line:match('local') then + -- Special: tell gen_vimdoc.py this is a local function. + return 'local_function ' .. fn .. '{}' + end + -- add vanilla function return 'function ' .. fn .. '{}' end @@ -336,6 +342,9 @@ end --- @param generics table> --- @return string? local function process_line(line, in_stream, generics) + local line_raw = line + line = vim.trim(line) + if vim.startswith(line, '---') then return process_magic(line:sub(4), generics) end @@ -348,6 +357,14 @@ local function process_line(line, in_stream, generics) return process_function_header(line) end + if not line:match('^local') then + local v = line_raw:match('^([A-Za-z][.a-zA-Z_]*)%s+%=') + if v and v:match('%.') then + -- Special: this lets gen_vimdoc.py handle tables. + return 'table '..v..'() {}' + end + end + if #line > 0 then -- we don't know what this line means, so just comment it out return '// zz: ' .. line end @@ -363,11 +380,11 @@ function Lua2DoxFilter:filter(filename) local generics = {} --- @type table while not in_stream:eof() do - local line = vim.trim(in_stream:getLine()) + local line = in_stream:getLine() local out_line = process_line(line, in_stream, generics) - if not vim.startswith(line, '---') then + if not vim.startswith(vim.trim(line), '---') then generics = {} end -- cgit From b1fb04475e6fa0c44895cb6fe97b75816d74c297 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 3 Aug 2023 13:41:47 +0200 Subject: docs: remove "#" comment char in @return Everything after a "#" char is a "description" comment, i.e. luals won't treat it as a type, name, etc. But "#" should not be present in the generated docs (such as :help docs). https://github.com/LuaLS/lua-language-server/wiki/Annotations#return --- scripts/lua2dox.lua | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'scripts/lua2dox.lua') diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index 9a666ea629..01bb8ab57a 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -154,6 +154,8 @@ local function removeCommentFromLine(line) return line:sub(1, pos_comment - 1), line:sub(pos_comment) end +--- Processes "@…" directives in a docstring line. +--- --- @param line string --- @param generics table --- @return string? @@ -206,6 +208,8 @@ local function process_magic(line, generics) magic = magic:gsub('^return%s+.*%((' .. type .. ')%)', 'return %1') magic = magic:gsub('^return%s+.*%((' .. type .. '|nil)%)', 'return %1') end + -- Remove first "#" comment char, if any. https://github.com/LuaLS/lua-language-server/wiki/Annotations#return + magic = magic:gsub('# ', '', 1) -- handle the return of vim.spell.check magic = magic:gsub('({.*}%[%])', '`%1`') magic_split = vim.split(magic, ' ', { plain = true }) -- cgit From c6c21db82b31ea43ce878ab3725dcd901db1e7a1 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 8 Aug 2023 16:36:06 +0100 Subject: fix(filetype): add typing and dry (#24573) --- scripts/lua2dox.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'scripts/lua2dox.lua') diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index 01bb8ab57a..7594a0e7df 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -58,7 +58,11 @@ local TYPES = { 'integer', 'number', 'string', 'table', 'list', 'boolean', 'func local TAGGED_TYPES = { 'TSNode', 'LanguageTree' } -- Document these as 'table' -local ALIAS_TYPES = { 'Range', 'Range4', 'Range6', 'TSMetadata' } +local ALIAS_TYPES = { + 'Range', 'Range4', 'Range6', 'TSMetadata', + 'vim.filetype.add.filetypes', + 'vim.filetype.match.args' +} local debug_outfile = nil --- @type string? local debug_output = {} -- cgit From 877d04d0fb83b5fc602dbab22b58f26a793ec236 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sat, 16 Sep 2023 23:10:30 +0100 Subject: feat(lua): add vim.func._memoize Memoizes a function, using a custom function to hash the arguments. Private for now until: - There are other places in the codebase that could benefit from this (e.g. LSP), but might require other changes to accommodate. - Invalidation of the cache needs to be controllable. Using weak tables is an acceptable invalidation policy, but it shouldn't be the only one. - I don't think the story around `hash_fn` is completely thought out. We may be able to have a good default hash_fn by hashing each argument, so basically a better 'concat'. --- scripts/lua2dox.lua | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'scripts/lua2dox.lua') diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua index 7594a0e7df..1c8bc5a3cb 100644 --- a/scripts/lua2dox.lua +++ b/scripts/lua2dox.lua @@ -361,6 +361,12 @@ local function process_line(line, in_stream, generics) return process_block_comment(line:sub(5), in_stream) end + -- Hax... I'm sorry + -- M.fun = vim.memoize(function(...) + -- -> + -- function M.fun(...) + line = line:gsub('^(.+) = .*_memoize%([^,]+, function%((.*)%)$', 'function %1(%2)') + if line:find('^function') or line:find('^local%s+function') then return process_function_header(line) end -- cgit