commit 48541a114febfd1d7ff9ae54f5008873c9926b2d
Author: John MacFarlane <jgm@berkeley.edu>
Date:   Sun May 19 10:34:26 2024 -0700

    Revert "Revert "Refactor: corrupted LuaLS annotations for completion""
    
    This reverts commit 8f9b25eab7b70a4517da4d8df69d22d3843bb024.

diff --git a/djot.lua b/djot.lua
index 29f4240..eb41c56 100644
--- a/djot.lua
+++ b/djot.lua
@@ -1,4 +1,4 @@
---- @module djot
+--- @module 'djot'
 --- Parse and render djot light markup format. See https://djot.net.
 ---
 --- @usage
@@ -33,8 +33,10 @@ local html = require("djot.html")
 local json = require("djot.json")
 local filter = require("djot.filter")
 
+--- @class StringHandle
 local StringHandle = {}
 
+--- @return (StringHandle)
 function StringHandle:new()
   local buffer = {}
   setmetatable(buffer, StringHandle)
@@ -42,21 +44,23 @@ function StringHandle:new()
   return buffer
 end
 
+--- @param s (string)
 function StringHandle:write(s)
   self[#self + 1] = s
 end
 
+--- @return (string)
 function StringHandle:flush()
   return table.concat(self)
 end
 
 --- Parse a djot text and construct an abstract syntax tree (AST)
 --- representing the document.
---- @param input input string
---- @param sourcepos if true, source positions are included in the AST
---- @param warn function that processes a warning, accepting a warning
+--- @param input (string) input string
+--- @param sourcepos (boolean) if true, source positions are included in the AST
+--- @param warn (function) function that processes a warning, accepting a warning
 --- object with `pos` and `message` fields.
---- @return AST
+--- @return (AST)
 local function parse(input, sourcepos, warn)
   local parser = Parser:new(input, warn)
   return ast.to_ast(parser, sourcepos)
@@ -65,10 +69,10 @@ end
 --- Parses a djot text and returns an iterator over events, consisting
 --- of a start position (bytes), and an position (bytes), and an
 --- annotation.
---- @param input input string
---- @param warn function that processes a warning, accepting a warning
+--- @param input (string) input string
+--- @param warn (function) function that processes a warning, accepting a warning
 --- object with `pos` and `message` fields.
---- @return an iterator over events.
+--- @return integer, integer, string an iterator over events.
 ---
 ---     for startpos, endpos, annotation in djot.parse_events("hello *world") do
 ---     ...
@@ -78,8 +82,8 @@ local function parse_events(input, warn)
 end
 
 --- Render a document's AST in human-readable form.
---- @param doc the AST
---- @return rendered AST (string)
+--- @param doc (AST) the AST
+--- @return (string) rendered AST
 local function render_ast_pretty(doc)
   local handle = StringHandle:new()
   ast.render(doc, handle)
@@ -87,15 +91,15 @@ local function render_ast_pretty(doc)
 end
 
 --- Render a document's AST in JSON.
---- @param doc the AST
---- @return rendered AST (JSON string)
+--- @param doc (AST) the AST
+--- @return (string) rendered AST (JSON string)
 local function render_ast_json(doc)
   return json.encode(doc) .. "\n"
 end
 
 --- Render a document as HTML.
---- @param doc the AST
---- @return rendered document (HTML string)
+--- @param doc (AST) the AST
+--- @return (string) rendered document (HTML string)
 local function render_html(doc)
   local handle = StringHandle:new()
   local renderer = html.Renderer:new()
@@ -104,19 +108,19 @@ local function render_html(doc)
 end
 
 --- Render an event as a JSON array.
---- @param startpos starting byte position
---- @param endpos ending byte position
---- @param annotation annotation of event
---- @return rendered event (JSON string)
+--- @param startpos (integer) starting byte position
+--- @param endpos (integer) ending byte position
+--- @param annotation (string) annotation of event
+--- @return (string) rendered event (JSON string)
 local function render_event(startpos, endpos, annotation)
   return string.format("[%q,%d,%d]", annotation, startpos, endpos)
 end
 
 --- Parse a document and render as a JSON array of events.
---- @param input the djot document (string)
---- @param warn function that emits warnings, taking as argumnet
+--- @param input (string) the djot document
+--- @param warn (function) function that emits warnings, taking as argumnet
 --- an object with fields 'message' and 'pos'
---- @return rendered events (JSON string)
+--- @return (string) rendered events (JSON string)
 local function parse_and_render_events(input, warn)
   local handle = StringHandle:new()
   local idx = 0
diff --git a/djot/ast.lua b/djot/ast.lua
index b6bbcc2..a846271 100644
--- a/djot/ast.lua
+++ b/djot/ast.lua
@@ -1,6 +1,27 @@
---- @module djot.ast
+--- @module 'djot.ast'
 --- Construct an AST for a djot document.
 
+--- @class Attributes
+--- @field class? string
+--- @field id? string
+
+--- @class AST
+--- @field t string tag for the node
+--- @field s? string text for the node
+--- @field c AST[] child node
+--- @field alias string
+--- @field level integer
+--- @field startidx integer
+--- @field startmarker string
+--- @field styles table
+--- @field style_marker string
+--- @field attr Attributes
+--- @field display boolean
+--- @field references table
+--- @field footnotes table
+--- @field pos? string[]
+--- @field destination? string[]
+
 if not utf8 then -- if not lua 5.3 or higher...
   -- this is needed for the __pairs metamethod, used below
   -- The following code is derived from the compat53 rock:
@@ -212,7 +233,7 @@ mt.__pairs = sortedpairs(function(a,b)
 
 --- Create a new AST node.
 --- @param tag (string) tag for the node
---- @return node (table)
+--- @return (AST) node (table)
 local function new_node(tag)
   local node = { t = tag, c = nil }
   setmetatable(node, mt)
@@ -220,8 +241,8 @@ local function new_node(tag)
 end
 
 --- Add `child` as a child of `node`.
---- @param node parent node
---- @param child child node
+--- @param node (AST) node parent node
+--- @param child (AST) node child node
 local function add_child(node, child)
   if (not node.c) then
     node.c = {child}
@@ -231,15 +252,15 @@ local function add_child(node, child)
 end
 
 --- Returns true if `node` has children.
---- @param node node to check
---- @return true if node has children
+--- @param node (AST) node to check
+--- @return (boolean) true if node has children
 local function has_children(node)
   return (node.c and #node.c > 0)
 end
 
 --- Returns an attributes object.
---- @param tbl table of attributes and values
---- @return attributes object (table including special metatable for
+--- @param tbl (Attributes?) table of attributes and values
+--- @return (Attributes) attributes object (table including special metatable for
 --- deterministic order of iteration)
 local function new_attributes(tbl)
   local attr = tbl or {}
@@ -250,7 +271,7 @@ local function new_attributes(tbl)
 end
 
 --- Insert an attribute into an attributes object.
---- @param attr attributes object
+--- @param attr (Attributes)
 --- @param key (string) key of new attribute
 --- @param val (string) value of new attribute
 local function insert_attribute(attr, key, val)
@@ -267,8 +288,8 @@ local function insert_attribute(attr, key, val)
 end
 
 --- Copy attributes from `source` to `target`.
---- @param target attributes object
---- @param source table associating keys and values
+--- @param target (Attributes)
+--- @param source (table) associating keys and values
 local function copy_attributes(target, source)
   if source then
     for k,v in pairs(source) do
@@ -277,6 +298,8 @@ local function copy_attributes(target, source)
   end
 end
 
+--- @param targetnode (AST)
+--- @param cs (AST)
 local function insert_attributes_from_nodes(targetnode, cs)
   targetnode.attr = targetnode.attr or new_attributes()
   local i=1
@@ -297,6 +320,7 @@ local function insert_attributes_from_nodes(targetnode, cs)
   end
 end
 
+--- @param node (AST)
 local function make_definition_list_item(node)
   node.t = "definition_list_item"
   if not has_children(node) then
@@ -380,8 +404,8 @@ end
 
 --- Create an abstract syntax tree based on an event
 --- stream and references.
---- @param parser djot streaming parser
---- @param sourcepos if true, include source positions
+--- @param parser (Parser) djot streaming parser
+--- @param sourcepos (boolean) if true, include source positions
 --- @return table representing the AST
 local function to_ast(parser, sourcepos)
   local subject = parser.subject
@@ -645,6 +669,7 @@ local function to_ast(parser, sourcepos)
         elseif node.t == "attributes" then
           -- parse attributes, add to last node
           local tip = containers[#containers]
+          --- @type AST|false
           local prevnode = has_children(tip) and tip.c[#tip.c]
           if prevnode then
             local endswithspace = false
@@ -980,9 +1005,8 @@ end
 
 --- Render an AST in human-readable form, with indentation
 --- showing the hierarchy.
---- @param doc (table) djot AST
---- @param handle handle to which to write content
---- @return result of flushing handle
+--- @param doc (AST) djot AST
+--- @param handle (StringHandle) handle to which to write content
 local function render(doc, handle)
   render_node(doc, handle, 0)
   if next(doc.references) ~= nil then
diff --git a/djot/block.lua b/djot/block.lua
index 72e3bc5..2d5debf 100644
--- a/djot/block.lua
+++ b/djot/block.lua
@@ -43,6 +43,11 @@ local function get_list_styles(marker)
   end
 end
 
+---@class Parser
+---@field subject string
+---@field warn function
+---@field matches table
+---@field containers table
 local Parser = {}
 
 function Parser:new(subject, warn)
diff --git a/djot/filter.lua b/djot/filter.lua
index 0026bdf..46dfad3 100644
--- a/djot/filter.lua
+++ b/djot/filter.lua
@@ -1,4 +1,4 @@
---- @module djot.filter
+--- @module 'djot.filter'
 --- Support filters that walk the AST and transform a
 --- document between parsing and rendering, like pandoc Lua filters.
 ---