summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2018-02-21 15:40:15 -0300
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2018-04-08 11:25:25 -0300
commit94702524505f93b9a7f8ac9192ce6fdd88271423 (patch)
tree9149332cc371936a029f6e4a70455926f54a8d67
parentc2b067453a06eeb0e6d88133dc34db93b617d9c8 (diff)
gendoc-mono: Add documentation generation for C# language
-rw-r--r--src/scripts/elua/apps/docgen/mono.lua614
-rw-r--r--src/scripts/elua/apps/gendoc.lua3
2 files changed, 617 insertions, 0 deletions
diff --git a/src/scripts/elua/apps/docgen/mono.lua b/src/scripts/elua/apps/docgen/mono.lua
new file mode 100644
index 0000000000..430a9ebebd
--- /dev/null
+++ b/src/scripts/elua/apps/docgen/mono.lua
@@ -0,0 +1,614 @@
1
2local writer = require("docgen.writer")
3local dtree = require("docgen.doctree")
4
5local M = {}
6
7local propt_to_type = {
8 [dtree.Function.PROPERTY] = "(get, set)",
9 [dtree.Function.PROP_GET] = "(get)",
10 [dtree.Function.PROP_SET] = "(set)",
11}
12
13local verbs = {
14 "add",
15 "get",
16 "is",
17 "del",
18 "thaw",
19 "freeze",
20 "save",
21 "wait",
22 "eject",
23 "raise",
24 "lower",
25 "load",
26 "dup",
27 "reset",
28 "unload",
29 "close",
30 "set",
31 "interpolate",
32 "has",
33 "grab",
34 "check",
35 "find",
36 "ungrab",
37 "unset",
38 "clear",
39 "pop",
40 "new",
41 "peek",
42 "push",
43 "update",
44 "show",
45 "move",
46 "hide",
47 "calculate",
48 "resize",
49 "attach",
50 "pack",
51 "unpack",
52 "emit",
53 "call",
54 "append"
55}
56
57local not_verbs = {
58 "below",
59 "above",
60 "name",
61 "unfreezable",
62 "value",
63 "r",
64 "g",
65 "b",
66 "a",
67 "finalize",
68 "destructor",
69 "to",
70 "circle",
71 "rect",
72 "path",
73 "commands",
74 "type",
75 "colorspace",
76 "op",
77 "type",
78 "properties",
79 "status",
80 "status",
81 "relative",
82 "ptr",
83 "pair",
84 "pos",
85 "end"
86}
87
88local get_class_name = function(cls)
89 local words = {}
90 local klass = cls:full_name_get()
91 for word in string.gmatch(klass, "%a+") do
92 words[#words+1] = word
93 end
94 for i = 1, #words -1 do
95 words[i] = string.lower(words[i])
96 end
97 return table.concat(words, '.')
98end
99
100local get_mono_type
101get_mono_type = function(tp)
102 if not tp then
103 return "void "
104 end
105
106 tpt = tp:type_get()
107 tpdecl = tp:typedecl_get()
108
109 if tpt == tp.REGULAR then
110 if tp:full_name_get() == "string" then
111 return "System.String"
112 elseif tp:full_name_get() == "list" then
113 ntp = tp:base_type_get()
114 --assert(btp ~= nil)
115 --ntp = btp:next_type_get()
116 return "eina.List<" .. get_mono_type(ntp) .. ">"
117 elseif tpdecl then
118 --print("typedecl type is ", tp:full_name_get())
119 tpt = tpdecl:type_get()
120 return get_class_name(tp) --tp:full_name_get()
121 else
122 --print("regular type is ", tp:full_name_get())
123 return tp:full_name_get()
124 end
125 elseif tpt == tp.CLASS then
126 return get_class_name(tp)
127 else
128 return "unknown"
129 end
130end
131
132
133local is_verb = function(word)
134 for i = 1, #verbs do
135 if verbs[i] == word then
136 return true
137 end
138 end
139 return false
140end
141
142local mono_method_name_get = function(f, ftype)
143 local cn = f:name_get(ftype)
144
145 local words = {}
146
147 for word in string.gmatch(cn, "%a+") do
148 words[#words+1] = word
149 end
150
151 if #words > 1 and is_verb(words[#words]) then
152 local tmp = words[#words]
153 words[#words] = words[1]
154 words[1] = tmp
155 end
156
157 for i = 1, #words do
158 words[i] = words[i]:gsub("^%l", string.upper)
159 end
160
161 if ftype == f.PROP_GET then
162 table.insert(words, 1, "Get")
163 elseif ftype == f.PROP_SET then
164 table.insert(words, 1, "Set")
165 end
166
167 return table.concat(words)
168end
169
170local gen_mono_param = function(par, out)
171 local part = par:type_get()
172 out = out or (par:direction_get() == par.OUT)
173 if out then
174 out = "out "
175 else
176 out = ""
177 end
178
179 return out .. get_mono_type(par:type_get()) .. ' ' .. par:name_get()
180 --local tstr = part:c_type_get()
181 --return out .. dtree.type_cstr_get(tstr, par:name_get())
182end
183
184local get_func_mono_sig_part = function(cn, tp)
185 return get_mono_type(tp) .. " " .. cn
186end
187
188local find_parent_impl
189find_parent_impl = function(fulln, cl)
190 for i, pcl in ipairs(cl:inherits_get()) do
191 for j, impl in ipairs(pcl:implements_get()) do
192 if impl:full_name_get() == fulln then
193 --if get_class_name(impl) == fulln then
194 return impl, pcl
195 end
196 end
197 local pimpl, pcl = find_parent_impl(fulln, pcl)
198 if pimpl then
199 return pimpl, pcl
200 end
201 end
202 return nil, cl
203end
204
205local find_parent_briefdoc
206find_parent_briefdoc = function(fulln, cl)
207 local pimpl, pcl = find_parent_impl(fulln, cl)
208 if not pimpl then
209 return dtree.Doc():brief_get()
210 end
211 local pdoc = pimpl:doc_get(dtree.Function.METHOD, true)
212 local pdocf = pimpl:fallback_doc_get(true)
213 if not pdoc:exists() and (not pdocf or not pdocf:exists()) then
214 return find_parent_briefdoc(fulln, pcl)
215 end
216 return pdoc:brief_get(pdocf)
217end
218
219
220local write_description = function(f, impl, func, cl)
221 local over = impl:is_overridden(cl)
222 local bdoc
223
224 local doc = impl:doc_get(func.METHOD, true)
225 local docf = impl:fallback_doc_get(true)
226 if over and (not doc:exists() and (not docf or not docf:exists())) then
227 bdoc = find_parent_briefdoc(impl:full_name_get(), cl)
228 else
229 bdoc = doc:brief_get(docf)
230 end
231 if bdoc ~= "No description supplied." then
232 f:write_raw(bdoc)
233 end
234end
235
236local write_scope = function(f, func)
237 local ftt = {
238 [func.scope.PROTECTED] = "protected",
239 [func.scope.PRIVATE] = "private"
240 }
241 if func:is_class() then
242 f:write_raw(" ")
243 f:write_m("class")
244 end
245 if func:type_get() == func.PROPERTY then
246 local ft1, ft2 = ftt[func:scope_get(func.PROP_GET)],
247 ftt[func:scope_get(func.PROP_SET)]
248 if ft1 and ft1 == ft2 then
249 f:write_raw(" ")
250 f:write_m(ft1)
251 elseif ft1 or ft2 then
252 local s = ""
253 if ft1 then
254 s = s .. ft1 .. " get" .. (ft2 and ", " or "")
255 end
256 if ft2 then
257 s = s .. ft2 .. " set"
258 end
259 f:write_raw(" ")
260 f:write_m(s)
261 end
262 else
263 local ft = ftt[func:scope_get(func:type_get())]
264 if ft then
265 f:write_raw(" ")
266 f:write_m(ft)
267 end
268 end
269end
270
271local write_function = function(f, func, cl)
272 local llbuf = writer.Buffer()
273 llbuf:write_link(func:nspaces_get(cl, true), func:name_get())
274 f:write_b(llbuf:finish())
275
276 local pt = propt_to_type[func:type_get()]
277 if pt then
278 f:write_raw(" ")
279 local llbuf = writer.Buffer()
280 llbuf:write_b(pt)
281 f:write_i(llbuf:finish())
282 end
283end
284
285local gen_func_mono_sig = function(f, ftype)
286 ftype = ftype or f.METHOD
287 assert(ftype ~= f.PROPERTY)
288
289 local cn = mono_method_name_get(f, ftype)
290 local rtype = f:return_type_get(ftype)
291 local prefix = ""
292 local suffix = ""
293
294 if f:is_class() then
295 prefix = "static "
296 elseif f:is_const() or ftype == f.PROP_GET then
297 suffix = " const"
298 end
299
300 if f:type_get() == f.METHOD then
301 local pars = f:parameters_get()
302 local cnrt = get_func_mono_sig_part(cn, rtype)
303 for i = 1, #pars do
304 pars[i] = gen_mono_param(pars[i])
305 end
306 return prefix .. cnrt .. "(" .. table.concat(pars, ", ") .. ")" .. suffix .. ";"
307 end
308
309 local keys = f:property_keys_get(ftype)
310 local vals = f:property_values_get(ftype)
311
312 if ftype == f.PROP_SET then
313 local cnrt = get_func_mono_sig_part(cn, rtype)
314 local pars = {}
315 for i, par in ipairs(keys) do
316 pars[#pars + 1] = gen_mono_param(par)
317 end
318 for i, par in ipairs(vals) do
319 pars[#pars + 1] = gen_mono_param(par)
320 end
321 return cnrt .. "(" .. table.concat(pars, ", ") .. ");"
322 end
323
324 -- getters
325 local cnrt
326 if not rtype then
327 if #vals == 1 then
328 cnrt = get_func_mono_sig_part(cn, vals[1]:type_get())
329 table.remove(vals, 1)
330 else
331 cnrt = get_func_mono_sig_part(cn)
332 end
333 else
334 cnrt = get_func_mono_sig_part(cn, rtype)
335 end
336 local pars = {}
337 for i, par in ipairs(keys) do
338 pars[#pars + 1] = gen_mono_param(par)
339 end
340 for i, par in ipairs(vals) do
341 print('parameter is value for get, so out')
342 pars[#pars + 1] = gen_mono_param(par, true)
343 end
344
345 return cnrt .. "(" .. table.concat(pars, ", ") .. ");"
346end
347
348local build_functable = function(f, tcl, tbl)
349 if #tbl == 0 then
350 return
351 end
352 local nt = {}
353 for i, implt in ipairs(tbl) do
354 local lbuf = writer.Buffer()
355
356 local cl, impl = unpack(implt)
357 local func = impl:function_get()
358
359 local wt = {}
360 wt[0] = cl
361 wt[1] = func
362 wt[2] = impl
363
364 nt[#nt + 1] = wt
365 end
366
367 local get_best_scope = function(f)
368 local ft = f:type_get()
369 if ft == f.PROPERTY then
370 local fs1, fs2 = f:scope_get(f.PROP_GET), f:scope_get(f.PROP_SET)
371 if fs1 == f.scope.PUBLIC or fs2 == f.scope.PUBLIC then
372 return f.scope.PUBLIC
373 elseif fs1 == f.scope.PROTECTED or fs2 == f.scope.PROTECTED then
374 return f.scope.PROTECTED
375 else
376 return f.scope.PRIVATE
377 end
378 else
379 return f:scope_get(ft)
380 end
381 end
382 table.sort(nt, function(v1, v2)
383 local cl1, cl2 = v1[0], v2[0]
384 if cl1 ~= cl2 then
385 return cl1:full_name_get() < cl2:full_name_get()
386 end
387
388 local f1, f2 = v1[1], v2[1]
389 local f1s, f2s = get_best_scope(f1), get_best_scope(f2)
390 if f1s ~= f2s then
391 if f1s ~= f1.scope.PROTECED then
392 -- public funcs go first, private funcs go last
393 return f1s == f1.scope.PUBLIC
394 else
395 -- protected funcs go second
396 return f2s == f2.scope.PRIVATE
397 end
398 end
399 return f1:name_get() < f2:name_get()
400 end)
401
402 return nt
403end
404
405local find_callables
406find_callables = function(cl, omeths, events, written)
407 for i, pcl in ipairs(cl:inherits_get()) do
408 for j, impl in ipairs(pcl:implements_get()) do
409 local func = impl:function_get()
410 local fid = func:id_get()
411 if not written[fid] then
412 omeths[#omeths + 1] = { pcl, impl }
413 written[fid] = true
414 end
415 end
416 for i, ev in ipairs(pcl:events_get()) do
417 local evid = ev:name_get()
418 if not written[evid] then
419 events[#events + 1] = { pcl, ev }
420 written[evid] = true
421 end
422 end
423 find_callables(pcl, omeths, events, written)
424 end
425end
426
427M.build_inherits = function(cl, t, lvl)
428 t = t or {}
429 lvl = lvl or 0
430 local lbuf = writer.Buffer()
431 if lvl > 0 then
432 local cln = cl:nspaces_get(true)
433 cln[#cln] = nil
434 cln[#cln] = cln[#cln] .. "_mono"
435 cln = ":" .. 'develop:api' .. ":"
436 .. table.concat(cln, ":")
437 lbuf:write_raw("[[", cln, "|", get_class_name(cl), "]]")
438 --lbuf:write_link(cl:nspaces_get(true), cl:full_name_get())
439 lbuf:write_raw(" ")
440 lbuf:write_i("(" .. cl:type_str_get() .. ")")
441
442 t[#t + 1] = { lvl - 1, lbuf:finish() }
443 end
444
445 for i, acl in ipairs(cl:inherits_get()) do
446 M.build_inherits(acl, t, lvl + 1)
447 end
448 return t
449end
450
451M.build_inherit_summary = function(cl, buf)
452 buf = buf or writer.Buffer()
453 buf:write_raw(" => ")
454
455 local cln = cl:nspaces_get(true)
456 cln[#cln] = nil
457 cln[#cln] = cln[#cln] .. "_mono"
458 cln = ":" .. 'develop:api' .. ":"
459 .. table.concat(cln, ":")
460 buf:write_raw("[[", cln, "|", get_class_name(cl), "]]")
461 buf:write_raw(" ")
462 buf:write_i("(" .. cl:type_str_get() .. ")")
463
464 local inherits = cl:inherits_get()
465 if #inherits ~= 0 then
466 M.build_inherit_summary(inherits[1], buf)
467 end
468 return buf
469end
470
471M.write_inherit_functable = function(f, tcl, tbl)
472 if #tbl == 0 then
473 return
474 end
475 local nt = build_functable(t, tcl, tbl)
476
477 local prevcl = tcl
478 for i, wt in ipairs(nt) do
479 local cl = wt[0]
480 local func = wt[1]
481 local impl = wt[2]
482
483 local ocl = impl:class_get()
484 local func = impl:function_get()
485
486 -- class grouping for inheritance
487 if cl ~= prevcl then
488 prevcl = cl
489 f:write_raw("^ ")
490 f:write_link(cl:nspaces_get(true), cl:full_name_get())
491 f:write_raw(" ^^^")
492 f:write_nl()
493 end
494
495 -- scope
496 f:write_raw("| ")
497 write_scope(f, func)
498 f:write_raw(" | ")
499 -- function
500 write_function(f, func, cl)
501 f:write_raw(" | ")
502 -- description
503 write_description(f, impl, func, cl)
504 f:write_raw(" |")
505 f:write_nl()
506 end
507 f:write_nl()
508end
509
510M.write_functable = function(f, tcl, tbl)
511 if #tbl == 0 then
512 return
513 end
514 local nt = build_functable(t, tcl, tbl)
515
516 local wrote = false
517 for i, wt in ipairs(nt) do
518 local cl = wt[0]
519 local func = wt[1]
520 local impl = wt[2]
521
522 local ocl = impl:class_get()
523 local func = impl:function_get()
524 local over = impl:is_overridden(cl)
525
526 -- function
527 write_function(f, func, cl)
528 -- scope
529 write_scope(f, func)
530
531 -- overrides
532 if over then
533 -- TODO: possibly also mention which part of a property was
534 -- overridden and where, get/set override point might differ!
535 -- but we get latest doc every time so it's ok for now
536 local llbuf = writer.Buffer()
537 llbuf:write_raw(" [Overridden from ")
538 llbuf:write_link(ocl:nspaces_get(true), ocl:full_name_get())
539 llbuf:write_raw("]")
540 f:write_i(llbuf:finish())
541 end
542
543 -- description
544 f:write_br(true)
545 f:write_raw("> ")
546 write_description(f, impl, func, cl)
547
548 -- code snippets
549 f:write_nl()
550 local codes = {}
551 if func:type_get() ~= dtree.Function.PROPERTY then
552 codes[#codes + 1] = gen_func_mono_sig(func, func:type_get())
553 else
554 codes[#codes + 1] = gen_func_mono_sig(func, dtree.Function.PROP_GET)
555 codes[#codes + 1] = gen_func_mono_sig(func, dtree.Function.PROP_SET)
556 end
557 f:write_code(table.concat(codes, "\n"), "c")
558 f:write_br(true)
559 end
560 f:write_nl()
561end
562
563M.build_class = function(cl)
564 local cln = cl:nspaces_get()
565 local fulln = cl:full_name_get()
566 --table.insert(cln, "mono")
567 cln[#cln] = cln[#cln] .. "_mono"
568 --printgen("Generating (MONO) class: " .. fulln .. " in ns ", unpack(cln))
569 local f = writer.Writer(cln, fulln .. " (mono)")
570 f:write_h(cl:full_name_get() .. " (" .. cl:type_str_get() .. ")", 1)
571
572 f:write_h("Description", 2)
573 f:write_raw(cl:doc_get():full_get(nil, true))
574 f:write_nl(2)
575
576 f:write_editable(cln, "description")
577 f:write_nl()
578
579 local inherits = cl:inherits_get()
580 if #inherits ~= 0 then
581 f:write_h("Inheritance", 2)
582
583 f:write_raw(M.build_inherit_summary(inherits[1]):finish())
584 f:write_nl()
585
586 f:write_folded("Full hierarchy", function()
587 f:write_list(M.build_inherits(cl))
588 end)
589 f:write_nl()
590 end
591
592 local written = {}
593 local ievs = {}
594 local meths, omeths = {}, {}
595 for i, impl in ipairs(cl:implements_get()) do
596 local func = impl:function_get()
597 written[func:id_get()] = true
598 meths[#meths + 1] = { cl, impl }
599 end
600 find_callables(cl, omeths, ievs, written)
601
602 f:write_h("Members", 2)
603 M.write_functable(f, cl, meths, true)
604 if #omeths ~= 0 then
605 f:write_h("Inherited", 3)
606 end
607 M.write_inherit_functable(f, cl, omeths, false)
608
609 f:finish()
610end
611
612return M
613
614
diff --git a/src/scripts/elua/apps/gendoc.lua b/src/scripts/elua/apps/gendoc.lua
index 6e81595556..36c47e2af3 100644
--- a/src/scripts/elua/apps/gendoc.lua
+++ b/src/scripts/elua/apps/gendoc.lua
@@ -7,6 +7,7 @@ local dutil = require("docgen.util")
7local writer = require("docgen.writer") 7local writer = require("docgen.writer")
8local keyref = require("docgen.keyref") 8local keyref = require("docgen.keyref")
9local dtree = require("docgen.doctree") 9local dtree = require("docgen.doctree")
10local mono = require("docgen.mono")
10 11
11local printgen = function() end 12local printgen = function() end
12 13
@@ -1084,6 +1085,8 @@ local build_class = function(cl)
1084 local f = writer.Writer(cln, fulln) 1085 local f = writer.Writer(cln, fulln)
1085 printgen("Generating class: " .. fulln) 1086 printgen("Generating class: " .. fulln)
1086 1087
1088 mono.build_class(cl)
1089
1087 f:write_h(cl:name_get() .. " (" .. cl:type_str_get() .. ")", 1) 1090 f:write_h(cl:name_get() .. " (" .. cl:type_str_get() .. ")", 1)
1088 1091
1089 f:write_h("Description", 2) 1092 f:write_h("Description", 2)