From 0b8dd67e0b9800a06ca5a0dabd3637a71963411c Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Tue, 12 Apr 2016 16:54:25 +0100 Subject: [PATCH] docgen: correctly resolve references in docs --- gendoc.lua | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 126 insertions(+), 14 deletions(-) diff --git a/gendoc.lua b/gendoc.lua index d9a31db..a5b643a 100644 --- a/gendoc.lua +++ b/gendoc.lua @@ -185,6 +185,20 @@ local Buffer = Writer:clone { -- eolian to various doc elements conversions +local classt_to_str = { + [eolian.class_type.REGULAR] = "class", + [eolian.class_type.ABSTRACT] = "class", + [eolian.class_type.MIXIN] = "mixin", + [eolian.class_type.INTERFACE] = "interface" +} + +local funct_to_str = { + [eolian.function_type.PROPERTY] = "property", + [eolian.function_type.PROP_GET] = "property", + [eolian.function_type.PROP_SET] = "property", + [eolian.function_type.METHOD] = "method" +} + local str_split = function(str, delim) if not str then return nil @@ -212,6 +226,95 @@ local notetypes = { ["TODO: "] = "\n**TODO:** " } +local get_decl_nspace = function(decl) + local dt = eolian.declaration_type + local tp = decl:type_get() + if tp == dt.ALIAS then + return "alias" + elseif tp == dt.STRUCT then + return "struct" + elseif tp == dt.ENUM then + return "enum" + elseif tp == dt.VAR then + return "var" + elseif tp == dt.CLASS then + local ret = classt_to_str[decl:class_get():type_get()] + if not ret then + error("unknown class type for class '" .. decl:name_get() .. "'") + end + return ret + else + error("unknown declaration type for declaration '" + .. decl:name_get() .. "'") + end +end + +local gen_ref_link +gen_ref_link = function(str) + local decl = eolian.declaration_get_by_name(str) + if decl then + return table.concat { + ":", root_nspace, ":", get_decl_nspace(decl), ":", + str:gsub("%.", ":"):lower() + } + end + + -- field or func + local bstr = str:match("(.+)%.[^.]+") + if not bstr then + error("invalid reference '" .. str .. "'") + end + + local sfx = str:sub(#bstr + 1) + + decl = eolian.declaration_get_by_name(bstr) + if decl then + local dt = eolian.declaration_type + local tp = decl:type_get() + if tp == dt.STRUCT or tp == dt.ENUM then + -- TODO: point to the actual item + return gen_ref_link(bstr) + end + end + + local ftp = eolian.function_type + + local cl = eolian.class_get_by_name(bstr) + local fn + local ftype = ftp.UNRESOLVED + if not cl then + if sfx == ".get" then + ftype = ftp.PROP_GET + elseif sfx == ".set" then + ftype = ftp.PROP_SET + end + local mname + if ftype ~= ftp.UNRESOLVED then + mname = bstr:match(".+%.([^.]+)") + if not mname then + error("invalid reference '" .. str .. "'") + end + bstr = bstr:match("(.+)%.[^.]+") + cl = eolian.class_get_by_name(bstr) + if cl then + fn = cl:function_get_by_name(mname, ftype) + end + end + else + fn = cl:function_get_by_name(sfx:sub(2), ftype) + if fn then ftype = fn:type_get() end + end + + if not fn or not funct_to_str[ftype] then + error("invalid reference '" .. str .. "'") + end + + return table.concat { + gen_ref_link(bstr), ":", funct_to_str[ftype], ":", + fn:name_get():lower() + } +end + local gen_doc_markup = function(str) local f = str:gmatch(".") local c = f() @@ -237,6 +340,29 @@ local gen_doc_markup = function(str) else buf[#buf + 1] = "$" end + elseif c == "@" then + c = f() + if c and c:match("[a-zA-Z_]") then + local rbuf = { c } + c = f() + while c and c:match("[a-zA-Z0-9_.]") do + rbuf[#rbuf + 1] = c + c = f() + end + local ldot = false + if rbuf[#rbuf] == "." then + ldot = true + rbuf[#rbuf] = nil + end + local title = table.concat(rbuf) + buf[#buf + 1] = Buffer():write_link(gen_ref_link(title), + title):finish() + if ldot then + buf[#buf + 1] = "." + end + else + buf[#buf + 1] = "@" + end else buf[#buf + 1] = c c = f() @@ -345,13 +471,6 @@ local gen_namespaces = function(v, subnspace, root) return table.concat(nspaces, ":") end -local funct_to_str = { - [eolian.function_type.PROPERTY] = "property", - [eolian.function_type.PROP_GET] = "property", - [eolian.function_type.PROP_SET] = "property", - [eolian.function_type.METHOD] = "method" -} - local propt_to_type = { [eolian.function_type.PROPERTY] = "(get, set)", [eolian.function_type.PROP_GET] = "(get)", @@ -445,13 +564,6 @@ end -- builders -local classt_to_str = { - [eolian.class_type.REGULAR] = "class", - [eolian.class_type.ABSTRACT] = "class", - [eolian.class_type.MIXIN] = "mixin", - [eolian.class_type.INTERFACE] = "interface" -} - local build_method, build_property local build_reftable = function(f, title, ctitle, ctype, t) -- 2.7.4