forked from enlightenment/efl
This has long been replaced with tools/edocgen.git and most likely does not even work.devs/lauromoura/pin-unpin
parent
b5a7ee2ae4
commit
34ef9c3139
10 changed files with 1 additions and 4668 deletions
@ -1,9 +0,0 @@ |
||||
# docgen |
||||
|
||||
This is the upcoming documentation generator for EFL. It takes documentation |
||||
described in Eo files and turns it into a DokuWiki structure (with possibility |
||||
of adapting it to other systems later on). |
||||
|
||||
Use the supplied build.sh script to generate. By default, it assumes that a |
||||
directory called "dokuwiki" is present in the current directory, so symlink |
||||
your dokuwiki setup into it (or change the path). |
File diff suppressed because it is too large
Load Diff
@ -1,41 +0,0 @@ |
||||
local M = {} |
||||
|
||||
local key_refs = {} |
||||
|
||||
M.add = function(key, link, lang) |
||||
local rfs = key_refs[lang] |
||||
if not rfs then |
||||
key_refs[lang] = {} |
||||
rfs = key_refs[lang] |
||||
end |
||||
rfs[key] = link |
||||
end |
||||
|
||||
M.build = function() |
||||
local writer = require("docgen.writer") |
||||
local dutil = require("docgen.util") |
||||
for lang, rfs in pairs(key_refs) do |
||||
local f = writer.Writer({ "ref", lang, "keyword-list" }) |
||||
local arr = {} |
||||
for refn, v in pairs(rfs) do |
||||
arr[#arr + 1] = refn |
||||
local rf = writer.Writer({ "ref", lang, "key", refn }) |
||||
v[#v + 1] = true |
||||
rf:write_include(rf.INCLUDE_PAGE, v) |
||||
rf:finish() |
||||
end |
||||
table.sort(arr) |
||||
f:write_raw(table.concat(arr, "\n")) |
||||
f:write_nl() |
||||
f:finish() |
||||
local lf = writer.Writer({ "ref", lang, "keyword-link" }) |
||||
lf:write_raw("/", dutil.path_join( |
||||
dutil.nspace_to_path(dutil.get_root_ns()), |
||||
"ref", lang, "key", "{FNAME}" |
||||
)) |
||||
lf:write_nl() |
||||
lf:finish() |
||||
end |
||||
end |
||||
|
||||
return M |
@ -1,614 +0,0 @@ |
||||
|
||||
local writer = require("docgen.writer") |
||||
local dtree = require("docgen.doctree") |
||||
|
||||
local M = {} |
||||
|
||||
local propt_to_type = { |
||||
[dtree.Function.PROPERTY] = "(get, set)", |
||||
[dtree.Function.PROP_GET] = "(get)", |
||||
[dtree.Function.PROP_SET] = "(set)", |
||||
} |
||||
|
||||
local verbs = { |
||||
"add", |
||||
"get", |
||||
"is", |
||||
"del", |
||||
"thaw", |
||||
"freeze", |
||||
"save", |
||||
"wait", |
||||
"eject", |
||||
"raise", |
||||
"lower", |
||||
"load", |
||||
"dup", |
||||
"reset", |
||||
"unload", |
||||
"close", |
||||
"set", |
||||
"interpolate", |
||||
"has", |
||||
"grab", |
||||
"check", |
||||
"find", |
||||
"ungrab", |
||||
"unset", |
||||
"clear", |
||||
"pop", |
||||
"new", |
||||
"peek", |
||||
"push", |
||||
"update", |
||||
"show", |
||||
"move", |
||||
"hide", |
||||
"calculate", |
||||
"resize", |
||||
"attach", |
||||
"pack", |
||||
"unpack", |
||||
"emit", |
||||
"call", |
||||
"append" |
||||
} |
||||
|
||||
local not_verbs = { |
||||
"below", |
||||
"above", |
||||
"name", |
||||
"unfreezable", |
||||
"value", |
||||
"r", |
||||
"g", |
||||
"b", |
||||
"a", |
||||
"finalize", |
||||
"destructor", |
||||
"to", |
||||
"circle", |
||||
"rect", |
||||
"path", |
||||
"commands", |
||||
"type", |
||||
"colorspace", |
||||
"op", |
||||
"type", |
||||
"properties", |
||||
"status", |
||||
"status", |
||||
"relative", |
||||
"ptr", |
||||
"pair", |
||||
"pos", |
||||
"end" |
||||
} |
||||
|
||||
local get_class_name = function(cls) |
||||
local words = {} |
||||
local klass = cls:name_get() |
||||
for word in string.gmatch(klass, "%a+") do |
||||
words[#words+1] = word |
||||
end |
||||
for i = 1, #words -1 do |
||||
words[i] = string.lower(words[i]) |
||||
end |
||||
return table.concat(words, '.') |
||||
end |
||||
|
||||
local get_mono_type |
||||
get_mono_type = function(tp) |
||||
if not tp then |
||||
return "void " |
||||
end |
||||
|
||||
tpt = tp:type_get() |
||||
tpdecl = tp:typedecl_get() |
||||
|
||||
if tpt == tp.REGULAR then |
||||
if tp:name_get() == "string" then |
||||
return "System.String" |
||||
elseif tp:name_get() == "list" then |
||||
ntp = tp:base_type_get() |
||||
--assert(btp ~= nil) |
||||
--ntp = btp:next_type_get() |
||||
return "eina.List<" .. get_mono_type(ntp) .. ">" |
||||
elseif tpdecl then |
||||
--print("typedecl type is ", tp:name_get()) |
||||
tpt = tpdecl:type_get() |
||||
return get_class_name(tp) --tp:name_get() |
||||
else |
||||
--print("regular type is ", tp:name_get()) |
||||
return tp:name_get() |
||||
end |
||||
elseif tpt == tp.CLASS then |
||||
return get_class_name(tp) |
||||
else |
||||
return "unknown" |
||||
end |
||||
end |
||||
|
||||
|
||||
local is_verb = function(word) |
||||
for i = 1, #verbs do |
||||
if verbs[i] == word then |
||||
return true |
||||
end |
||||
end |
||||
return false |
||||
end |
||||
|
||||
local mono_method_name_get = function(f, ftype) |
||||
local cn = f:name_get(ftype) |
||||
|
||||
local words = {} |
||||
|
||||
for word in string.gmatch(cn, "%a+") do |
||||
words[#words+1] = word |
||||
end |
||||
|
||||
if #words > 1 and is_verb(words[#words]) then |
||||
local tmp = words[#words] |
||||
words[#words] = words[1] |
||||
words[1] = tmp |
||||
end |
||||
|
||||
for i = 1, #words do |
||||
words[i] = words[i]:gsub("^%l", string.upper) |
||||
end |
||||
|
||||
if ftype == f.PROP_GET then |
||||
table.insert(words, 1, "Get") |
||||
elseif ftype == f.PROP_SET then |
||||
table.insert(words, 1, "Set") |
||||
end |
||||
|
||||
return table.concat(words) |
||||
end |
||||
|
||||
local gen_mono_param = function(par, out) |
||||
local part = par:type_get() |
||||
out = out or (par:direction_get() == par.OUT) |
||||
if out then |
||||
out = "out " |
||||
else |
||||
out = "" |
||||
end |
||||
|
||||
return out .. get_mono_type(par:type_get()) .. ' ' .. par:name_get() |
||||
--local tstr = part:c_type_get() |
||||
--return out .. dtree.type_cstr_get(tstr, par:name_get()) |
||||
end |
||||
|
||||
local get_func_mono_sig_part = function(cn, tp) |
||||
return get_mono_type(tp) .. " " .. cn |
||||
end |
||||
|
||||
local find_parent_impl |
||||
find_parent_impl = function(fulln, cl) |
||||
for i, pcl in ipairs(cl:inherits_get()) do |
||||
for j, impl in ipairs(pcl:implements_get()) do |
||||
if impl:name_get() == fulln then |
||||
--if get_class_name(impl) == fulln then |
||||
return impl, pcl |
||||
end |
||||
end |
||||
local pimpl, pcl = find_parent_impl(fulln, pcl) |
||||
if pimpl then |
||||
return pimpl, pcl |
||||
end |
||||
end |
||||
return nil, cl |
||||
end |
||||
|
||||
local find_parent_briefdoc |
||||
find_parent_briefdoc = function(fulln, cl) |
||||
local pimpl, pcl = find_parent_impl(fulln, cl) |
||||
if not pimpl then |
||||
return dtree.Doc():brief_get() |
||||
end |
||||
local pdoc = pimpl:doc_get(dtree.Function.METHOD, true) |
||||
local pdocf = pimpl:fallback_doc_get(true) |
||||
if not pdoc:exists() and (not pdocf or not pdocf:exists()) then |
||||
return find_parent_briefdoc(fulln, pcl) |
||||
end |
||||
return pdoc:brief_get(pdocf) |
||||
end |
||||
|
||||
|
||||
local write_description = function(f, impl, func, cl) |
||||
local over = impl:is_overridden(cl) |
||||
local bdoc |
||||
|
||||
local doc = impl:doc_get(func.METHOD, true) |
||||
local docf = impl:fallback_doc_get(true) |
||||
if over and (not doc:exists() and (not docf or not docf:exists())) then |
||||
bdoc = find_parent_briefdoc(impl:name_get(), cl) |
||||
else |
||||
bdoc = doc:brief_get(docf) |
||||
end |
||||
if bdoc ~= "No description supplied." then |
||||
f:write_raw(bdoc) |
||||
end |
||||
end |
||||
|
||||
local write_scope = function(f, func) |
||||
local ftt = { |
||||
[func.scope.PROTECTED] = "protected", |
||||
[func.scope.PRIVATE] = "private" |
||||
} |
||||
if func:is_class() then |
||||
f:write_raw(" ") |
||||
f:write_m("class") |
||||
end |
||||
if func:type_get() == func.PROPERTY then |
||||
local ft1, ft2 = ftt[func:scope_get(func.PROP_GET)], |
||||
ftt[func:scope_get(func.PROP_SET)] |
||||
if ft1 and ft1 == ft2 then |
||||
f:write_raw(" ") |
||||
f:write_m(ft1) |
||||
elseif ft1 or ft2 then |
||||
local s = "" |
||||
if ft1 then |
||||
s = s .. ft1 .. " get" .. (ft2 and ", " or "") |
||||
end |
||||
if ft2 then |
||||
s = s .. ft2 .. " set" |
||||
end |
||||
f:write_raw(" ") |
||||
f:write_m(s) |
||||
end |
||||
else |
||||
local ft = ftt[func:scope_get(func:type_get())] |
||||
if ft then |
||||
f:write_raw(" ") |
||||
f:write_m(ft) |
||||
end |
||||
end |
||||
end |
||||
|
||||
local write_function = function(f, func, cl) |
||||
local llbuf = writer.Buffer() |
||||
llbuf:write_link(func:nspaces_get(cl, true), func:name_get()) |
||||
f:write_b(llbuf:finish()) |
||||
|
||||
local pt = propt_to_type[func:type_get()] |
||||
if pt then |
||||
f:write_raw(" ") |
||||
local llbuf = writer.Buffer() |
||||
llbuf:write_b(pt) |
||||
f:write_i(llbuf:finish()) |
||||
end |
||||
end |
||||
|
||||
local gen_func_mono_sig = function(f, ftype) |
||||
ftype = ftype or f.METHOD |
||||
assert(ftype ~= f.PROPERTY) |
||||
|
||||
local cn = mono_method_name_get(f, ftype) |
||||
local rtype = f:return_type_get(ftype) |
||||
local prefix = "" |
||||
local suffix = "" |
||||
|
||||
if f:is_class() then |
||||
prefix = "static " |
||||
elseif f:is_const() or ftype == f.PROP_GET then |
||||
suffix = " const" |
||||
end |
||||
|
||||
if f:type_get() == f.METHOD then |
||||
local pars = f:parameters_get() |
||||
local cnrt = get_func_mono_sig_part(cn, rtype) |
||||
for i = 1, #pars do |
||||
pars[i] = gen_mono_param(pars[i]) |
||||
end |
||||
return prefix .. cnrt .. "(" .. table.concat(pars, ", ") .. ")" .. suffix .. ";" |
||||
end |
||||
|
||||
local keys = f:property_keys_get(ftype) |
||||
local vals = f:property_values_get(ftype) |
||||
|
||||
if ftype == f.PROP_SET then |
||||
local cnrt = get_func_mono_sig_part(cn, rtype) |
||||
local pars = {} |
||||
for i, par in ipairs(keys) do |
||||
pars[#pars + 1] = gen_mono_param(par) |
||||
end |
||||
for i, par in ipairs(vals) do |
||||
pars[#pars + 1] = gen_mono_param(par) |
||||
end |
||||
return cnrt .. "(" .. table.concat(pars, ", ") .. ");" |
||||
end |
||||
|
||||
-- getters |
||||
local cnrt |
||||
if not rtype then |
||||
if #vals == 1 then |
||||
cnrt = get_func_mono_sig_part(cn, vals[1]:type_get()) |
||||
table.remove(vals, 1) |
||||
else |
||||
cnrt = get_func_mono_sig_part(cn) |
||||
end |
||||
else |
||||
cnrt = get_func_mono_sig_part(cn, rtype) |
||||
end |
||||
local pars = {} |
||||
for i, par in ipairs(keys) do |
||||
pars[#pars + 1] = gen_mono_param(par) |
||||
end |
||||
for i, par in ipairs(vals) do |
||||
--print('parameter is value for get, so out') |
||||
pars[#pars + 1] = gen_mono_param(par, true) |
||||
end |
||||
|
||||
return cnrt .. "(" .. table.concat(pars, ", ") .. ");" |
||||
end |
||||
|
||||
local build_functable = function(f, tcl, tbl) |
||||
if #tbl == 0 then |
||||
return |
||||
end |
||||
local nt = {} |
||||
for i, implt in ipairs(tbl) do |
||||
local lbuf = writer.Buffer() |
||||
|
||||
local cl, impl = unpack(implt) |
||||
local func = impl:function_get() |
||||
|
||||
local wt = {} |
||||
wt[0] = cl |
||||
wt[1] = func |
||||
wt[2] = impl |
||||
|
||||
nt[#nt + 1] = wt |
||||
end |
||||
|
||||
local get_best_scope = function(f) |
||||
local ft = f:type_get() |
||||
if ft == f.PROPERTY then |
||||
local fs1, fs2 = f:scope_get(f.PROP_GET), f:scope_get(f.PROP_SET) |
||||
if fs1 == f.scope.PUBLIC or fs2 == f.scope.PUBLIC then |
||||
return f.scope.PUBLIC |
||||
elseif fs1 == f.scope.PROTECTED or fs2 == f.scope.PROTECTED then |
||||
return f.scope.PROTECTED |
||||
else |
||||
return f.scope.PRIVATE |
||||
end |
||||
else |
||||
return f:scope_get(ft) |
||||
end |
||||
end |
||||
table.sort(nt, function(v1, v2) |
||||
local cl1, cl2 = v1[0], v2[0] |
||||
if cl1 ~= cl2 then |
||||
return cl1:name_get() < cl2:name_get() |
||||
end |
||||
|
||||
local f1, f2 = v1[1], v2[1] |
||||
local f1s, f2s = get_best_scope(f1), get_best_scope(f2) |
||||
if f1s ~= f2s then |
||||
if f1s ~= f1.scope.PROTECED then |
||||
-- public funcs go first, private funcs go last |
||||
return f1s == f1.scope.PUBLIC |
||||
else |
||||
-- protected funcs go second |
||||
return f2s == f2.scope.PRIVATE |
||||
end |
||||
end |
||||
return f1:name_get() < f2:name_get() |
||||
end) |
||||
|
||||
return nt |
||||
end |
||||
|
||||
local find_callables |
||||
find_callables = function(cl, omeths, events, written) |
||||
for i, pcl in ipairs(cl:inherits_get()) do |
||||
for j, impl in ipairs(pcl:implements_get()) do |
||||
local func = impl:function_get() |
||||
local fid = func:id_get() |
||||
if not written[fid] then |
||||
omeths[#omeths + 1] = { pcl, impl } |
||||
written[fid] = true |
||||
end |
||||
end |
||||
for i, ev in ipairs(pcl:events_get()) do |
||||
local evid = ev:name_get() |
||||
if not written[evid] then |
||||
events[#events + 1] = { pcl, ev } |
||||
written[evid] = true |
||||
end |
||||
end |
||||
find_callables(pcl, omeths, events, written) |
||||
end |
||||
end |
||||
|
||||
M.build_inherits = function(cl, t, lvl) |
||||
t = t or {} |
||||
lvl = lvl or 0 |
||||
local lbuf = writer.Buffer() |
||||
if lvl > 0 then |
||||
local cln = cl:nspaces_get(true) |
||||
cln[#cln] = nil |
||||
cln[#cln] = cln[#cln] .. "_mono" |
||||
cln = ":" .. 'develop:api' .. ":" |
||||
.. table.concat(cln, ":") |
||||
lbuf:write_raw("[[", cln, "|", get_class_name(cl), "]]") |
||||
--lbuf:write_link(cl:nspaces_get(true), cl:name_get()) |
||||
lbuf:write_raw(" ") |
||||
lbuf:write_i("(" .. cl:type_str_get() .. ")") |
||||
|
||||
t[#t + 1] = { lvl - 1, lbuf:finish() } |
||||
end |
||||
|
||||
for i, acl in ipairs(cl:inherits_get()) do |
||||
M.build_inherits(acl, t, lvl + 1) |
||||
end |
||||
return t |
||||
end |
||||
|
||||
M.build_inherit_summary = function(cl, buf) |
||||
buf = buf or writer.Buffer() |
||||
buf:write_raw(" => ") |
||||
|
||||
local cln = cl:nspaces_get(true) |
||||
cln[#cln] = nil |
||||
cln[#cln] = cln[#cln] .. "_mono" |
||||
cln = ":" .. 'develop:api' .. ":" |
||||
.. table.concat(cln, ":") |
||||
buf:write_raw("[[", cln, "|", get_class_name(cl), "]]") |
||||
buf:write_raw(" ") |
||||
buf:write_i("(" .. cl:type_str_get() .. ")") |
||||
|
||||
local inherits = cl:inherits_get() |
||||
if #inherits ~= 0 then |
||||
M.build_inherit_summary(inherits[1], buf) |
||||
end |
||||
return buf |
||||
end |
||||
|
||||
M.write_inherit_functable = function(f, tcl, tbl) |
||||
if #tbl == 0 then |
||||
return |
||||
end |
||||
local nt = build_functable(t, tcl, tbl) |
||||
|
||||
local prevcl = tcl |
||||
for i, wt in ipairs(nt) do |
||||
local cl = wt[0] |
||||
local func = wt[1] |
||||
local impl = wt[2] |
||||
|
||||
local ocl = impl:class_get() |
||||
local func = impl:function_get() |
||||
|
||||
-- class grouping for inheritance |
||||
if cl ~= prevcl then |
||||
prevcl = cl |
||||
f:write_raw("^ ") |
||||
f:write_link(cl:nspaces_get(true), cl:name_get()) |
||||
f:write_raw(" ^^^") |
||||
f:write_nl() |
||||
end |
||||
|
||||
-- scope |
||||
f:write_raw("| ") |
||||
write_scope(f, func) |
||||
f:write_raw(" | ") |
||||
-- function |
||||
write_function(f, func, cl) |
||||
f:write_raw(" | ") |
||||
-- description |
||||
write_description(f, impl, func, cl) |
||||
f:write_raw(" |") |
||||
f:write_nl() |
||||
end |
||||
f:write_nl() |
||||
end |
||||
|
||||
M.write_functable = function(f, tcl, tbl) |
||||
if #tbl == 0 then |
||||
return |
||||
end |
||||
local nt = build_functable(t, tcl, tbl) |
||||
|
||||
local wrote = false |
||||
for i, wt in ipairs(nt) do |
||||
local cl = wt[0] |
||||
local func = wt[1] |
||||
local impl = wt[2] |
||||
|
||||
local ocl = impl:class_get() |
||||
local func = impl:function_get() |
||||
local over = impl:is_overridden(cl) |
||||
|
||||
-- function |
||||
write_function(f, func, cl) |
||||
-- scope |
||||
write_scope(f, func) |
||||
|
||||
-- overrides |
||||
if over then |
||||
-- TODO: possibly also mention which part of a property was |
||||
-- overridden and where, get/set override point might differ! |
||||
-- but we get latest doc every time so it's ok for now |
||||
local llbuf = writer.Buffer() |
||||
llbuf:write_raw(" [Overridden from ") |
||||
llbuf:write_link(ocl:nspaces_get(true), ocl:name_get()) |
||||
llbuf:write_raw("]") |
||||
f:write_i(llbuf:finish()) |
||||
end |
||||
|
||||
-- description |
||||
f:write_br(true) |
||||
f:write_raw("> ") |
||||
write_description(f, impl, func, cl) |
||||
|
||||
-- code snippets |
||||
f:write_nl() |
||||
local codes = {} |
||||
if func:type_get() ~= dtree.Function.PROPERTY then |
||||
codes[#codes + 1] = gen_func_mono_sig(func, func:type_get()) |
||||
else |
||||
codes[#codes + 1] = gen_func_mono_sig(func, dtree.Function.PROP_GET) |
||||
codes[#codes + 1] = gen_func_mono_sig(func, dtree.Function.PROP_SET) |
||||
end |
||||
f:write_code(table.concat(codes, "\n"), "c") |
||||
f:write_br(true) |
||||
end |
||||
f:write_nl() |
||||
end |
||||
|
||||
M.build_class = function(cl) |
||||
local cln = cl:nspaces_get() |
||||
local fulln = cl:name_get() |
||||
--table.insert(cln, "mono") |
||||
cln[#cln] = cln[#cln] .. "_mono" |
||||
--printgen("Generating (MONO) class: " .. fulln .. " in ns ", unpack(cln)) |
||||
local f = writer.Writer(cln, fulln .. " (mono)") |
||||
f:write_h(cl:name_get() .. " (" .. cl:type_str_get() .. ")", 1) |
||||
|
||||
f:write_h("Description", 2) |
||||
f:write_raw(cl:doc_get():full_get(nil, true)) |
||||
f:write_nl(2) |
||||
|
||||
f:write_editable(cln, "description") |
||||
f:write_nl() |
||||
|
||||
local inherits = cl:inherits_get() |
||||
if #inherits ~= 0 then |
||||
f:write_h("Inheritance", 2) |
||||
|
||||
f:write_raw(M.build_inherit_summary(inherits[1]):finish()) |
||||
f:write_nl() |
||||
|
||||
f:write_folded("Full hierarchy", function() |
||||
f:write_list(M.build_inherits(cl)) |
||||
end) |
||||
f:write_nl() |
||||
end |
||||
|
||||
local written = {} |
||||
local ievs = {} |
||||
local meths, omeths = {}, {} |
||||
for i, impl in ipairs(cl:implements_get()) do |
||||
local func = impl:function_get() |
||||
written[func:id_get()] = true |
||||
meths[#meths + 1] = { cl, impl } |
||||
end |
||||
find_callables(cl, omeths, ievs, written) |
||||
|
||||
f:write_h("Members", 2) |
||||
M.write_functable(f, cl, meths, true) |
||||
if #omeths ~= 0 then |
||||
f:write_h("Inherited", 3) |
||||
end |
||||
M.write_inherit_functable(f, cl, omeths, false) |
||||
|
||||
f:finish() |
||||
end |
||||
|
||||
return M |
||||
|
||||
|
@ -1,274 +0,0 @@ |
||||
local is_verbose = false |
||||
|
||||
local M = {} |
||||
|
||||
local stats = {} |
||||
|
||||
local stats_pd = function(n) |
||||
local ret = 0 |
||||
if n == 0 then |
||||
return 1 |
||||
end |
||||
while (n ~= 0) do |
||||
n = math.floor(n / 10) |
||||
ret = ret + 1 |
||||
end |
||||
return ret |
||||
end |
||||
|
||||
local fcol = 30 |
||||
local ncol = 0 |
||||
|
||||
local get_percent = function(sv, svu) |
||||
return (sv == 0) and 100 or math.floor(((sv - svu) / sv) * 100 + 0.5) |
||||
end |
||||
|
||||
local print_stat = function(printname, statname) |
||||
local sv = stats[statname] or 0 |
||||
local svu = stats[statname .. "_undoc"] or 0 |
||||
local percent = get_percent(sv, svu) |
||||
local tb = (" "):rep(math.max(0, fcol - #printname - 1) + ncol - stats_pd(sv)) |
||||
local dtb = (" "):rep(ncol - stats_pd(sv - svu)) |
||||
local ptb = (" "):rep(3 - stats_pd(percent)) |
||||
print(("%s:%s%d (documented: %s%d or %s%d%%)") |
||||
:format(printname, tb, sv, dtb, sv - svu, ptb, percent)) |
||||
end |
||||
|
||||
local get_secstats = function(...) |
||||
local sv, svu = 0, 0 |
||||
for i, v in ipairs({ ... }) do |
||||
sv = sv + (stats[v] or 0) |
||||
svu = svu + (stats[v .. "_undoc"] or 0) |
||||
end |
||||
return sv - svu, sv, get_percent(sv, svu) |
||||
end |
||||
|
||||
M.print = function() |
||||
for k, v in pairs(stats) do |
||||
ncol = math.max(ncol, stats_pd(v)) |
||||
end |
||||
|
||||
print(("=== CLASS SECTION: %d out of %d (%d%%) ===\n") |
||||
:format(get_secstats("class", "interface", "mixin", "event"))) |
||||
print_stat("Classes", "class") |
||||
print_stat("Interfaces", "interface") |
||||
print_stat("Mixins", "mixin") |
||||
print_stat("Events", "event") |
||||
|
||||
print(("\n=== FUNCTION SECTION: %d out of %d (%d%%) ===\n") |
||||
:format(get_secstats("method", "param", "mret", |
||||
"getter", "gret", "gkey", "gvalue", |
||||
"setter", "sret", "skey", "svalue"))) |
||||
print_stat("Methods", "method") |
||||
print_stat(" Method params", "param") |
||||
print_stat(" Method returns", "mret") |
||||
print_stat("Getters", "getter") |
||||
print_stat(" Getter returns", "gret") |
||||
print_stat(" Getter keys", "gkey") |
||||
print_stat(" Getter values", "gvalue") |
||||
print_stat("Setters", "setter") |
||||
print_stat(" Setter returns", "sret") |
||||
print_stat(" Setter keys", "skey") |
||||
print_stat(" Setter values", "svalue") |
||||
|
||||
print(("\n=== TYPE SECTION: %d out of %d (%d%%) ===\n") |
||||
:format(get_secstats("alias", "struct", "sfield", "enum", "efield"))) |
||||
print_stat("Aliases", "alias") |
||||
print_stat("Structs", "struct") |
||||
print_stat("Struct fields", "sfield") |
||||
print_stat("Enums", "enum") |
||||
print_stat("Enum fields", "efield") |
||||
|
||||
print(("\n=== VARIABLE SECTION: %d out of %d (%d%%) ===\n") |
||||
:format(get_secstats("constant", "global"))) |
||||
print_stat("Constants", "constant") |
||||
print_stat("Globals", "global") |
||||
|
||||
local sv, svu = 0, 0 |
||||
for k, v in pairs(stats) do |
||||
if k:match(".*_undoc$") then |
||||
svu = svu + v |
||||
else |
||||
sv = sv + v |
||||
end |
||||
end |
||||
print(("\n=== TOTAL: %d out of %d (%d%%) ===") |
||||
:format(sv - svu, sv, get_percent(sv, svu))) |
||||
end |
||||
|
||||
local stat_incr = function(name, missing) |
||||
if not stats[name] then |
||||
stats[name], stats[name .. "_undoc"] = 0, 0 |
||||
end |
||||
stats[name] = stats[name] + 1 |
||||
if missing then |
||||
stats[name .. "_undoc"] = stats[name .. "_undoc"] + 1 |
||||
end |
||||
end |
||||
|
||||
local print_missing = function(name, tp) |
||||
if not is_verbose then |
||||
return |
||||
end |
||||
print(tp .. " '" .. name .. "'" .. " missing documentation") |
||||
end |
||||
|
||||
M.check_class = function(cl) |
||||
local ct = cl:type_str_get() |
||||
if not ct then |
||||
return |
||||
end |
||||
if not cl:doc_get():exists() then |
||||
print_missing(cl:name_get(), ct) |
||||
stat_incr(ct, true) |
||||
else |
||||
stat_incr(ct, false) |
||||
end |
||||
|
||||
for i, ev in ipairs(cl:events_get()) do |
||||
if not ev:doc_get():exists() then |
||||
print_missing(cl:name_get() .. "." .. ev:name_get(), "event") |
||||
stat_incr("event", true) |
||||
else |
||||
stat_incr("event", false) |
||||
end |
||||
end |
||||
end |
||||
|
||||
M.check_method = function(fn, cl) |
||||
local fulln = cl:name_get() .. "." .. fn:name_get() |
||||
if fn:return_type_get(fn.METHOD) then |
||||
if not fn:return_doc_get(fn.METHOD):exists() then |
||||
print_missing(fulln, "method return") |
||||
stat_incr("mret", true) |
||||
else |
||||
stat_incr("mret", false) |
||||
end |
||||
end |
||||
if not fn:implement_get():doc_get(fn.METHOD):exists() then |
||||
print_missing(fulln, "method") |
||||
stat_incr("method", true) |
||||
else |
||||
stat_incr("method", false) |
||||
end |
||||
for i, p in ipairs(fn:parameters_get()) do |
||||
if not p:doc_get():exists() then |
||||
print_missing(fulln .. "." .. p:name_get(), "method parameter") |
||||
stat_incr("param", true) |
||||
else |
||||
stat_incr("param", false) |
||||
end |
||||
end |
||||
end |
||||
|
||||
M.check_property = function(fn, cl, ft) |
||||
local pfxs = { |
||||
[fn.PROP_GET] = "g", |
||||
[fn.PROP_SET] = "s", |
||||
} |
||||
local pfx = pfxs[ft] |
||||
|
||||
local fulln = cl:name_get() .. "." .. fn:name_get() |
||||
if fn:return_type_get(ft) then |
||||
if not fn:return_doc_get(ft):exists() then |
||||
print_missing(fulln, pfx .. "etter return") |
||||
stat_incr(pfx .. "ret", true) |
||||
else |
||||
stat_incr(pfx .. "ret", false) |
||||
end |
||||
end |
||||
|
||||
local pimp = fn:implement_get() |
||||
|
||||
if not pimp:doc_get(fn.PROPERTY):exists() and not pimp:doc_get(ft):exists() then |
||||
print_missing(fulln, pfx .. "etter") |
||||
stat_incr(pfx .. "etter", true) |
||||
else |
||||
stat_incr(pfx .. "etter", false) |
||||
end |
||||
|
||||
for i, p in ipairs(fn:property_keys_get(ft)) do |
||||
if not p:doc_get():exists() then |
||||
print_missing(fulln .. "." .. p:name_get(), pfx .. "etter key") |
||||
stat_incr(pfx .. "key", true) |
||||
else |
||||
stat_incr(pfx .. "key", false) |
||||
end |
||||
end |
||||
|
||||
for i, p in ipairs(fn:property_values_get(ft)) do |
||||
if not p:doc_get():exists() then |
||||
print_missing(fulln .. "." .. p:name_get(), pfx .. "etter value") |
||||
stat_incr(pfx .. "value", true) |
||||
else |
||||
stat_incr(pfx .. "value", false) |
||||
end |
||||
end |
||||
end |
||||
|
||||
M.check_alias = function(v) |
||||
if not v:doc_get():exists() then |
||||
print_missing(v:name_get(), "alias") |
||||
stat_incr("alias", true) |
||||
else |
||||
stat_incr("alias", false) |
||||
end |
||||
end |
||||
|
||||
M.check_struct = function(v) |
||||
if not v:doc_get():exists() then |
||||
print_missing(v:name_get(), "struct") |
||||
stat_incr("struct", true) |
||||
else |
||||
stat_incr("struct", false) |
||||
end |
||||
for i, fl in ipairs(v:struct_fields_get()) do |
||||
if not fl:doc_get():exists() then |
||||
print_missing(v:name_get() .. "." .. fl:name_get(), "struct field") |
||||
stat_incr("sfield", true) |
||||
else |
||||
stat_incr("sfield", false) |
||||
end |
||||
end |
||||
end |
||||
|
||||
M.check_enum = function(v) |
||||
if not v:doc_get():exists() then |
||||
print_missing(v:name_get(), "enum") |
||||
stat_incr("enum", true) |
||||
else |
||||
stat_incr("enum", false) |
||||
end |
||||
for i, fl in ipairs(v:enum_fields_get()) do |
||||
if not fl:doc_get():exists() then |
||||
print_missing(v:name_get() .. "." .. fl:name_get(), "enum field") |
||||
stat_incr("efield", true) |
||||
else |
||||
stat_incr("efield", false) |
||||
end |
||||
end |
||||
end |
||||
|
||||
M.check_constant = function(v) |
||||
if not v:doc_get():exists() then |
||||
print_missing(v:name_get(), "constant") |
||||
stat_incr("constant", true) |
||||
else |
||||
stat_incr("constant", false) |
||||
end |
||||
end |
||||
|
||||
M.check_global = function(v) |
||||
if not v:doc_get():exists() then |
||||
print_missing(v:name_get(), "global") |
||||
stat_incr("global", true) |
||||
else |
||||
stat_incr("global", false) |
||||
end |
||||
end |
||||
|
||||
M.init = function(verbose) |
||||
is_verbose = verbose |
||||
end |
||||
|
||||
return M |
@ -1,50 +0,0 @@ |
||||
local cutil = require("cutil") |
||||
local ffi = require("ffi") |
||||
|
||||
local M = {} |
||||
|
||||
local doc_root, root_ns |
||||
|
||||
local path_sep, rep_sep = "/", "\\" |
||||
if ffi.os == "Windows" then |
||||
path_sep, rep_sep = rep_sep, path_sep |
||||
end |
||||
|
||||
M.path_join = function(...) |
||||
return (table.concat({ ... }, path_sep):gsub(rep_sep, path_sep)) |
||||
end |
||||
|
||||
M.path_to_nspace = function(p) |
||||
return p:gsub(rep_sep, ":"):gsub(path_sep, ":"):lower() |
||||
end |
||||
|
||||
M.nspace_to_path = function(ns) |
||||
return ns:gsub(":", path_sep):gsub(rep_sep, path_sep):lower() |
||||
end |
||||
|
||||
M.make_page = function(path, ext) |
||||
return M.path_join(doc_root, path .. "." .. ext) |
||||
end |
||||
|
||||
M.get_root_ns = function() |
||||
return root_ns |
||||
end |
||||
|
||||
M.mkdir_r = function(dirn) |
||||
assert(cutil.file_mkpath(M.path_join(doc_root, dirn))) |
||||
end |
||||
|
||||
M.mkdir_p = function(path) |
||||
M.mkdir_r(path:match("(.+)" .. path_sep .. "([^" .. path_sep .. "]+)")) |
||||
end |
||||
|
||||
M.rm_root = function() |
||||
cutil.file_rmrf(doc_root) |
||||
end |
||||
|
||||
M.init = function(root, rns) |
||||
doc_root = root:gsub(rep_sep, path_sep) |
||||
root_ns = rns |
||||
end |
||||
|
||||
return M |
@ -1,397 +0,0 @@ |
||||
local util = require("util") |
||||
|
||||
local dutil = require("docgen.util") |
||||
local dtree = require("docgen.doctree") |
||||
|
||||
local M = {} |
||||
|
||||
local root_nspace, features |
||||
|
||||
M.has_feature = function(fname) |
||||
if not features then |
||||
return false |
||||
end |
||||
return not not features[fname] |
||||
end |
||||
|
||||
local allowed_incflags = { |
||||
noheader = { "noheader", "showheader" }, |
||||
firstseconly = { "firstseconly", "fullpage" }, |
||||
readmore = { "readmore", "noreadmore" }, |
||||
footer = { "footer", "nofooter" }, |
||||
link = { "link", "nolink" }, |
||||
permalink = { "permalink", "nopermalink" }, |
||||
date = { "date", "nodate" }, |
||||
mdate = { "mdate", "nomdate" }, |
||||
user = { "user", "nouser" }, |
||||
comments = { "comments", "nocomments" }, |
||||
linkbacks = { "linkbacks", "nolinkbacks" }, |
||||
tags = { "tags", "notags" }, |
||||
editbutton = { "editbtn", "noeditbtn" }, |
||||
redirect = { "redirect", "noredirect" }, |
||||
indent = { "indent", "noindent" }, |
||||
linkonly = { "linkonly", "nolinkonly" }, |
||||
title = { "title", "notitle" }, |
||||
pageexists = { "pageexists", "nopageexists" }, |
||||
parlink = { "parlink", "noparlink" }, |
||||
order = { { "id", "title", "created", "modified", "indexmenu", "custom" } }, |
||||
rsort = { "rsort", "sort" }, |
||||
depth = 0, |
||||
inline = true, |
||||
beforeeach = "", |
||||
aftereach = "" |
||||
} |
||||
|
||||
local writers = {} |
||||
|
||||
local Buffer = { |
||||
__ctor = function(self) |
||||
self.buf = {} |
||||
end, |
||||
|
||||
write_raw = function(self, ...) |
||||
for i, v in ipairs({ ... }) do |
||||
self.buf[#self.buf + 1] = v |
||||
end |
||||
return self |
||||
end, |
||||
|
||||
finish = function(self) |
||||
self.result = table.concat(self.buf) |
||||
self.buf = {} |
||||
return self.result |
||||
end |
||||
} |
||||
|
||||
local write_include = function(self, tp, name, flags) |
||||
local it_to_tp = { |
||||
[self.INCLUDE_PAGE] = "page", |
||||
[self.INCLUDE_SECTION] = "section", |
||||
[self.INCLUDE_NAMESPACE] = "namespace", |
||||
[self.INCLUDE_TAG] = "tagtopic" |
||||
} |
||||
if type(name) == "table" then |
||||
if name[#name] == true then |
||||
name[#name] = nil |
||||
name = ":" .. root_nspace .. ":" |
||||
.. table.concat(name, ":") |
||||
elseif name[#name] == false then |
||||
name[#name] = nil |
||||
name = ":" .. root_nspace .. "-include:" |
||||
.. table.concat(name, ":") |
||||
else |
||||
name = table.concat(name, ":") |
||||
end |
||||
end |
||||
self:write_raw("{{", it_to_tp[tp], ">", name); |
||||
if flags then |
||||
if tp == self.INCLUDE_SECTION and flags.section then |
||||
self:write_raw("#", flags.section) |
||||
end |
||||
flags.section = nil |
||||
local flstr = {} |
||||
for k, v in pairs(flags) do |
||||
local allow = allowed_incflags[k] |
||||
if allow ~= nil then |
||||
if type(allow) == "boolean" then |
||||
flstr[#flstr + 1] = k |
||||
elseif type(allow) == "number" or type(allow) == "string" then |
||||
if type(v) ~= type(allow) then |
||||
error("invalid value type for flag " .. k) |
||||
end |
||||
flstr[#flstr + 1] = k .. "=" .. v |
||||
elseif type(allow) == "table" then |
||||
if type(allow[1]) == "table" then |
||||
local valid = false |
||||
for i, vv in ipairs(allow[1]) do |
||||
if v == vv then |
||||
flstr[#flstr + 1] = k .. "=" .. v |
||||
valid = true |
||||
break |
||||
end |
||||
end |
||||
if not valid then |
||||
error("invalid value " .. v .. " for flag " .. k) |
||||
end |
||||
elseif type(allow[1]) == "string" and |
||||
type(allow[2]) == "string" then |
||||
if v then |
||||
flstr[#flstr + 1] = allow[1] |
||||
else |
||||
flstr[#flstr + 1] = allow[2] |
||||
end |
||||
end |
||||
end |
||||
else |
||||
error("invalid include flag: " .. tostring(k)) |
||||
end |
||||
end |
||||
flstr = table.concat(flstr, "&") |
||||
if #flstr > 0 then |
||||
self:write_raw("&", flstr) |
||||
end |
||||
end |
||||
self:write_raw("}}") |
||||
self:write_nl() |
||||
return self |
||||
end |
||||
|
||||
M.set_backend = function(bend) |
||||
M.Writer = assert(writers[bend], "invalid generation backend") |
||||
M.Buffer = M.Writer:clone(Buffer) |
||||
end |
||||
|
||||
writers["dokuwiki"] = util.Object:clone { |
||||
INCLUDE_PAGE = 0, |
||||
INCLUDE_SECTION = 1, |
||||
INCLUDE_NAMESPACE = 2, |
||||
INCLUDE_TAG = 3, |
||||
|
||||
__ctor = function(self, path, title) |
||||
local subs |
||||
if type(path) == "table" then |
||||
subs = dutil.path_join(unpack(path)) |
||||
else |
||||
subs = dutil.nspace_to_path(path) |
||||
end |
||||
dutil.mkdir_p(subs) |
||||
self.file = assert(io.open(dutil.make_page(subs, "txt"), "w")) |
||||
if title then |
||||
if M.has_feature("title") then |
||||
self:write_raw("~~Title: ", title, "~~") |
||||
self:write_nl() |
||||
else |
||||
self:write_h(title, 1) |
||||
end |
||||
end |
||||
end, |
||||
|
||||
write_raw = function(self, ...) |
||||
self.file:write(...) |
||||
return self |
||||
end, |
||||
|
||||
write_nl = function(self, n) |
||||
self:write_raw(("\n"):rep(n or 1)) |
||||
return self |
||||
end, |
||||
|
||||
write_h = function(self, heading, level, nonl) |
||||
local s = ("="):rep(7 - level) |
||||
self:write_raw(s, " ", heading, " ", s, "\n") |
||||
if not nonl then |
||||
self:write_nl() |
||||
end |
||||
return self |
||||
end, |
||||
|
||||
write_include = function(self, tp, name, flags) |
||||
return write_include(self, tp, name, flags) |
||||
end, |
||||
|
||||
write_editable = function(self, ns, name) |
||||
ns[#ns + 1] = name |
||||
ns[#ns + 1] = false |
||||
self:write_include(self.INCLUDE_PAGE, ns, { |
||||
date = false, user = false, link = false |
||||
}) |
||||
-- restore the table for later reuse |
||||
-- the false gets deleted by write_include |
||||
ns[#ns] = nil |
||||
end, |
||||
|
||||
write_inherited = function(self, ns) |
||||
ns[#ns + 1] = true |
||||
self:write_include(self.INCLUDE_PAGE, ns, { |
||||
editbutton = false, date = false, user = false, link = false |
||||
}) |
||||
end, |
||||
|
||||
write_fmt = function(self, fmt1, fmt2, ...) |
||||
self:write_raw(fmt1, ...) |
||||
self:write_raw(fmt2) |
||||
return self |
||||
end, |
||||
|
||||
write_b = function(self, ...) |
||||
self:write_fmt("**", "**", ...) |
||||
return self |
||||
end, |
||||
|
||||
write_i = function(self, ...) |
||||
self:write_fmt("//", "//", ...) |
||||
return self |
||||
end, |
||||
|
||||
write_u = function(self, ...) |
||||
self:write_fmt("__", "__", ...) |
||||
return self |
||||
end, |
||||
|
||||
write_s = function(self, ...) |
||||
self:write_fmt("<del>", "</del>", ...) |
||||
return self |
||||
end, |
||||
|
||||
write_m = function(self, ...) |
||||
self:write_fmt("''", "''", ...) |
||||
return self |
||||
end, |
||||
|
||||
write_sub = function(self, ...) |
||||
self:write_fmt("<sub>", "</sub>", ...) |
||||
return self |
||||
end, |
||||
|
||||
write_sup = function(self, ...) |
||||
self:write_fmt("<sup>", "</sup>", ...) |
||||
return self |
||||
end, |
||||
|
||||
write_br = function(self, nl) |
||||
self:write_raw("\\\\", nl and "\n" or " ") |
||||
return self |
||||
end, |
||||
|
||||
write_pre_inline = function(self, ...) |
||||
self:write_fmt("%%", "%%", ...) |
||||
return self |
||||
end, |
||||
|
||||
write_pre = function(self, ...) |
||||
self:write_fmt("<nowiki>\n", "\n</nowiki>", ...) |
||||
return self |
||||
end, |
||||
|
||||
write_code = function(self, str, lang) |
||||
lang = lang and (" " .. lang) or "" |
||||
self:write_raw("<code" .. lang .. ">\n", str, "\n</code>\n") |
||||
end, |
||||
|
||||
write_link = function(self, target, title) |
||||
if type(target) == "table" then |
||||
if target[#target] == false then |
||||
target[#target] = nil |
||||
target = ":" .. root_nspace .. "-include:" |
||||
.. table.concat(target, ":") |
||||
else |
||||
target[#target] = nil |
||||
target = ":" .. root_nspace .. ":" |
||||
.. table.concat(target, ":") |
||||
end |
||||
end |
||||
if not title then |
||||
self:write_raw("[[", target:lower(), "|", target, "]]") |
||||
return |
||||
end |
||||
target = target:lower() |
||||
if type(title) == "string" then |
||||
self:write_raw("[[", target, "|", title, "]]") |
||||
return self |
||||
end |
||||
self:write_raw("[[", target, "|") |
||||
title(self) |
||||
self:write_raw("]]") |
||||
return self |
||||
end, |
||||
|
||||
write_table = function(self, titles, tbl) |
||||
if titles then |
||||
self:write_raw("^ ", table.concat(titles, " ^ "), " ^\n") |
||||
end |
||||
for i, v in ipairs(tbl) do |
||||
self:write_raw("| ", table.concat(v, " | "), " |\n") |
||||
end |
||||
return self |
||||
end, |
||||
|
||||
write_list = function(self, tbl, ord) |
||||
local prec = ord and "-" or "*" |
||||
for i, v in ipairs(tbl) do |
||||
local lvl, str = 1, v |
||||
if type(v) == "table" then |
||||
lvl, str = v[1] + 1, v[2] |
||||
end |
||||
local pbeg, pend = str:match("([^\n]+)\n(.+)") |
||||
if not pbeg then |
||||
pbeg = str |
||||
end |
||||
self:write_raw((" "):rep(lvl), prec, " ", str, "\n") |
||||
if pend then |
||||
self:write_raw(pend, "\n") |
||||
end |
||||
end |
||||
return self |
||||
end, |
||||
|
||||
write_par = function(self, str) |
||||
local tokp = dtree.DocTokenizer(str) |
||||
local notetypes = M.has_feature("notes") and { |
||||
[tokp.MARK_NOTE] = "<note>\n", |
||||
[tokp.MARK_WARNING] = "<note warning>\n", |
||||
[tokp.MARK_REMARK] = "<note tip>\n", |
||||
[tokp.MARK_TODO] = "<note>\n**TODO:** " |
||||
} or {} |
||||