summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDaniel Kolesa <d.kolesa@samsung.com>2019-05-21 15:43:02 +0200
committerDaniel Kolesa <d.kolesa@samsung.com>2019-05-21 15:44:30 +0200
commit34ef9c313989402d523951b2c20c7141d3bdce78 (patch)
tree04f2a7b1d285ad6f008791784dd89c3e6532ca7c /src
parentb5a7ee2ae4466e87d0e3a62aa7885ecda9e30aea (diff)
docs: remove obsolete docgen from the tree
This has long been replaced with tools/edocgen.git and most likely does not even work.
Diffstat (limited to 'src')
-rw-r--r--src/Makefile_Elua.am15
-rw-r--r--src/scripts/elua/apps/README-docgen.md9
-rw-r--r--src/scripts/elua/apps/docgen/doctree.lua1427
-rw-r--r--src/scripts/elua/apps/docgen/keyref.lua41
-rw-r--r--src/scripts/elua/apps/docgen/mono.lua614
-rw-r--r--src/scripts/elua/apps/docgen/stats.lua274
-rw-r--r--src/scripts/elua/apps/docgen/util.lua50
-rw-r--r--src/scripts/elua/apps/docgen/writer.lua397
-rw-r--r--src/scripts/elua/apps/gendoc.lua1804
-rwxr-xr-xsrc/scripts/elua/apps/gendoc.sh38
10 files changed, 1 insertions, 4668 deletions
diff --git a/src/Makefile_Elua.am b/src/Makefile_Elua.am
index 069a33c0ef..f172a228b9 100644
--- a/src/Makefile_Elua.am
+++ b/src/Makefile_Elua.am
@@ -57,21 +57,10 @@ include Makefile_Elua_Helper.am
57 57
58endif 58endif
59eluaapps_files = \ 59eluaapps_files = \
60 scripts/elua/apps/lualian.lua \ 60 scripts/elua/apps/lualian.lua
61 scripts/elua/apps/gendoc.lua \
62 scripts/elua/apps/gendoc.sh \
63 scripts/elua/apps/README-docgen.md
64 61
65EXTRA_DIST2 += $(eluaapps_files) 62EXTRA_DIST2 += $(eluaapps_files)
66 63
67eluadocgen_files = \
68 scripts/elua/apps/docgen/doctree.lua \
69 scripts/elua/apps/docgen/keyref.lua \
70 scripts/elua/apps/docgen/stats.lua \
71 scripts/elua/apps/docgen/util.lua \
72 scripts/elua/apps/docgen/writer.lua
73
74EXTRA_DIST2 += $(eluadocgen_files)
75eluamodules_files = \ 64eluamodules_files = \
76 scripts/elua/modules/benchmark.lua \ 65 scripts/elua/modules/benchmark.lua \
77 scripts/elua/modules/getopt.lua \ 66 scripts/elua/modules/getopt.lua \
@@ -108,8 +97,6 @@ eluaappsdir = $(datadir)/elua/apps
108eluaapps_DATA = $(eluaapps_files) 97eluaapps_DATA = $(eluaapps_files)
109eluamodulesdir = $(datadir)/elua/modules 98eluamodulesdir = $(datadir)/elua/modules
110eluamodules_DATA = $(eluamodules_files) 99eluamodules_DATA = $(eluamodules_files)
111eluadocgendir = $(datadir)/elua/apps/docgen
112eluadocgen_DATA = $(eluadocgen_files)
113eluaeinadir = $(eluamodulesdir)/eina 100eluaeinadir = $(eluamodulesdir)/eina
114eluaeina_DATA = $(eluaeina_files) 101eluaeina_DATA = $(eluaeina_files)
115eluacoredir = $(datadir)/elua/core 102eluacoredir = $(datadir)/elua/core
diff --git a/src/scripts/elua/apps/README-docgen.md b/src/scripts/elua/apps/README-docgen.md
deleted file mode 100644
index 9b501ddfc2..0000000000
--- a/src/scripts/elua/apps/README-docgen.md
+++ /dev/null
@@ -1,9 +0,0 @@
1# docgen
2
3This is the upcoming documentation generator for EFL. It takes documentation
4described in Eo files and turns it into a DokuWiki structure (with possibility
5of adapting it to other systems later on).
6
7Use the supplied build.sh script to generate. By default, it assumes that a
8directory called "dokuwiki" is present in the current directory, so symlink
9your dokuwiki setup into it (or change the path).
diff --git a/src/scripts/elua/apps/docgen/doctree.lua b/src/scripts/elua/apps/docgen/doctree.lua
deleted file mode 100644
index 45171ca255..0000000000
--- a/src/scripts/elua/apps/docgen/doctree.lua
+++ /dev/null
@@ -1,1427 +0,0 @@
1local util = require("util")
2
3local eolian = require("eolian")
4
5local keyref = require("docgen.keyref")
6local dutil = require("docgen.util")
7
8-- writer has to be loaded late to prevent cycles
9local writer
10
11local M = {}
12local eos = eolian:new()
13
14local get_cache = function(o, nm)
15 local ret = o[nm]
16 if not ret then
17 ret = {}
18 o[nm] = ret
19 return ret, false
20 end
21 return ret, true
22end
23
24local matches_filter = function(obj)
25 local ns = obj:nspaces_get()
26 if #ns and (ns[1] == "efl" or ns[1] == "eina") then
27 return true
28 end
29
30 return false
31end
32
33M.Node = util.Object:clone {
34 scope = {
35 UNKNOWN = eolian.object_scope.UNKNOWN,
36 PUBLIC = eolian.object_scope.PUBLIC,
37 PRIVATE = eolian.object_scope.PRIVATE,
38 PROTECTED = eolian.object_scope.PROTECTED
39 },
40
41 __ctor = function(self, obj)
42 self._obj = obj
43 assert(self._obj)
44 end,
45
46 name_get = function(self)
47 return self._obj:name_get()
48 end,
49
50 short_name_get = function(self)
51 return self._obj:short_name_get()
52 end,
53
54 namespaces_get = function(self)
55 return self._obj:namespaces_get():to_array()
56 end,
57
58 nspaces_get = function(self, root)
59 local tbl = self:namespaces_get()
60 -- temporary workaround
61 if type(tbl) ~= "table" then
62 tbl = tbl:to_array()
63 end
64 for i = 1, #tbl do
65 tbl[i] = tbl[i]:lower()
66 end
67
68 tbl[#tbl + 1] = self:short_name_get():lower()
69 if root ~= nil then
70 tbl[#tbl + 1] = not not root
71 end
72 return tbl
73 end
74}
75local Node = M.Node
76
77local gen_doc_refd = function(str)
78 if not writer then
79 writer = require("docgen.writer")
80 end
81 if not str then
82 return nil
83 end
84 local pars = eolian.documentation_string_split(str)
85 for i = 1, #pars do
86 pars[i] = writer.Buffer():write_par(pars[i]):finish()
87 end
88 return table.concat(pars, "\n\n")
89end
90
91local add_since = function(str, since)
92 if not writer then
93 writer = require("docgen.writer")
94 end
95 if not since then
96 return str
97 end
98 local buf = writer.Buffer()
99 if not str then
100 buf:write_i("Since " .. since)
101 return buf:finish()
102 end
103 buf:write_raw(str)
104 buf:write_nl(2)
105 buf:write_i("Since " .. since)
106 return buf:finish()
107end
108
109M.Doc = Node:clone {
110 -- duplicate ctor to disable assertion
111 __ctor = function(self, obj)
112 self._obj = obj
113 end,
114
115 summary_get = function(self)
116 if not self._obj then
117 return nil
118 end
119 return self._obj:summary_get()
120 end,
121
122 description_get = function(self)
123 if not self._obj then
124 return nil
125 end
126 return self._obj:description_get()
127 end,
128
129 since_get = function(self)
130 if not self._obj then
131 return nil
132 end
133 return self._obj:since_get()
134 end,
135
136 brief_get = function(self, doc2)
137 if not self._obj and (not doc2 or not doc2._obj) then
138 return "No description supplied."
139 end
140 local doc1, doc2 = self._obj, doc2 and doc2._obj or nil
141 if not doc1 then
142 doc1, doc2 = doc2, doc1
143 end
144 return gen_doc_refd(doc1:summary_get())
145 end,
146
147 full_get = function(self, doc2, write_since)
148 if not self._obj and (not doc2 or not doc2._obj) then
149 return "No description supplied."
150 end
151 local doc1, doc2 = self._obj, doc2 and doc2._obj or nil
152 if not doc1 then
153 doc1, doc2 = doc2, doc1
154 end
155 local sum1 = doc1:summary_get()
156 local desc1 = doc1:description_get()
157 local edoc = ""
158 local since
159 if doc2 then
160 local sum2 = doc2:summary_get()
161 local desc2 = doc2:description_get()
162 if not desc2 then
163 if sum2 then edoc = "\n\n" .. sum2 end
164 else
165 edoc = "\n\n" .. sum2 .. "\n\n" .. desc2
166 end
167 if write_since then
168 since = doc2:since_get()
169 end
170 end
171 if not since and write_since then
172 since = doc1:since_get()
173 end
174 if not desc1 then
175 return add_since(gen_doc_refd(sum1 .. edoc), since)
176 end
177 return add_since(gen_doc_refd(sum1 .. "\n\n" .. desc1 .. edoc), since)
178 end,
179
180 exists = function(self)
181 return not not self._obj
182 end
183}
184
185local revh = {}
186
187local class_type_str = {
188 [eolian.class_type.REGULAR] = "class",
189 [eolian.class_type.ABSTRACT] = "class",
190 [eolian.class_type.MIXIN] = "mixin",
191 [eolian.class_type.INTERFACE] = "interface"
192}
193
194M.Class = Node:clone {
195 -- class types
196 UNKNOWN = eolian.class_type.UNKNOWN,
197 REGULAR = eolian.class_type.REGULAR,
198 ABSTRACT = eolian.class_type.ABSTRACT,
199 MIXIN = eolian.class_type.MIXIN,
200 INTERFACE = eolian.class_type.INTERFACE,
201
202 type_get = function(self)
203 return self._obj:type_get()
204 end,
205
206 type_str_get = function(self)
207 return class_type_str[self:type_get()]
208 end,
209
210 theme_str_get = function(self)
211 return ({
212 [eolian.class_type.REGULAR] = "regular",
213 [eolian.class_type.ABSTRACT] = "abstract",
214 [eolian.class_type.MIXIN] = "mixin",
215 [eolian.class_type.INTERFACE] = "interface"
216 })[self:type_get()]
217 end,
218
219 doc_get = function(self)
220 return M.Doc(self._obj:documentation_get())
221 end,
222
223 legacy_prefix_get = function(self)
224 return self._obj:legacy_prefix_get()
225 end,
226
227 eo_prefix_get = function(self)
228 return self._obj:eo_prefix_get()
229 end,
230
231 inherits_get = function(self)
232 local ret = self._cache_inhc
233 if ret then
234 return ret
235 end
236 ret = {}
237 for cl in self._obj:inherits_get() do
238 ret[#ret + 1] = M.Class(cl)
239 end
240 self._cache_inhc = ret
241 return ret
242 end,
243
244 children_get = function(self)
245 return revh[self:name_get()] or {}
246 end,
247
248 functions_get = function(self, ft)
249 local ret = self._cache_funcs
250 if ret then
251 return ret
252 end
253 ret = {}
254 self._cache_funcs = ret
255 for fn in self._obj:functions_get(ft) do
256 ret[#ret + 1] = M.Function(fn)
257 end
258 return ret
259 end,
260
261 function_by_name_get = function(self, fn, ft)
262 local fun = self._cache_func
263 if fun then
264 return fun
265 end
266 fun = M.Function(self._obj:function_by_name_get(fn, ft))
267 self._cache_func = fun
268 return fun
269 end,
270
271 events_get = function(self)
272 local ret = {}
273 for ev in self._obj:events_get() do
274 ret[#ret + 1] = M.Event(ev)
275 end
276 return ret
277 end,
278
279 implements_get = function(self)
280 local ret = {}
281 for impl in self._obj:implements_get() do
282 ret[#ret + 1] = M.Implement(impl)
283 end
284 return ret
285 end,
286
287 c_get_function_name_get = function(self)
288 return self._obj:c_get_function_name_get()
289 end,
290
291 nspaces_get = function(self, root)
292 return M.Node.nspaces_get(self, root)
293 end,
294
295 is_same = function(self, other)
296 return self._obj == other._obj
297 end,
298
299 -- static getters
300
301 by_name_get = function(name)
302 local stor = get_cache(M.Class, "_cache_bn")
303 local ret = stor[name]
304 if ret then
305 return ret
306 end
307 local v = eos:class_by_name_get(name)
308 if not v then
309 return nil
310 end
311 ret = M.Class(v)
312 stor[name] = ret
313 return ret
314 end,
315
316 by_file_get = function(name)
317 local stor = get_cache(M.Class, "_cache_bf")
318 local ret = stor[name]
319 if ret then
320 return ret
321 end
322 local v = eos:class_by_file_get(name)
323 if not v then
324 return nil
325 end
326 ret = M.Class(v)
327 stor[name] = ret
328 return ret
329 end,
330
331 all_get = function()
332 local ret, had = get_cache(M.Class, "_cache_all")
333 if not had then
334 -- FIXME: unit
335 for cl in eos:classes_get() do
336 local cls = M.Class(cl)
337 if matches_filter(cls) then
338 ret[#ret + 1] = cls
339 end
340 end
341 end
342 return ret
343 end
344}
345
346local func_type_str = {
347 [eolian.function_type.PROPERTY] = "property",
348 [eolian.function_type.PROP_GET] = "property",
349 [eolian.function_type.PROP_SET] = "property",
350 [eolian.function_type.METHOD] = "method"
351}
352
353local ffi = require("ffi")
354
355M.Function = Node:clone {
356 -- function types
357 UNRESOLVED = eolian.function_type.UNRESOLVED,
358 PROPERTY = eolian.function_type.PROPERTY,
359 PROP_SET = eolian.function_type.PROP_SET,
360 PROP_GET = eolian.function_type.PROP_GET,
361 METHOD = eolian.function_type.METHOD,
362 FUNCTION_POINTER = eolian.function_type.FUNCTION_POINTER,
363
364 type_get = function(self)
365 return self._obj:type_get()
366 end,
367
368 type_str_get = function(self)
369 return func_type_str[self:type_get()]
370 end,
371
372 scope_get = function(self, ft)
373 return self._obj:scope_get(ft)
374 end,
375
376 full_c_name_get = function(self, ft, legacy)
377 return self._obj:full_c_name_get(ft, legacy)
378 end,
379
380 legacy_get = function(self, ft)
381 return self._obj:legacy_get(ft)
382 end,
383
384 implement_get = function(self)
385 return M.Implement(self._obj:implement_get())
386 end,
387
388 is_legacy_only = function(self, ft)
389 return self._obj:is_legacy_only(ft)
390 end,
391
392 is_class = function(self)
393 return self._obj:is_class()
394 end,
395
396 is_beta = function(self)
397 return self._obj:is_beta()
398 end,
399
400 is_constructor = function(self, klass)
401 return self._obj:is_constructor(klass.class)
402 end,
403
404 is_function_pointer = function(self)
405 return self._obj:is_function_pointer()
406 end,
407
408 property_keys_get = function(self, ft)
409 local ret = {}
410 for par in self._obj:property_keys_get(ft) do
411 ret[#ret + 1] = M.Parameter(par)
412 end
413 return ret
414 end,
415
416 property_values_get = function(self, ft)
417 local ret = {}
418 for par in self._obj:property_values_get(ft) do
419 ret[#ret + 1] = M.Parameter(par)
420 end
421 return ret
422 end,
423
424 parameters_get = function(self)
425 local ret = {}
426 for par in self._obj:parameters_get() do
427 ret[#ret + 1] = M.Parameter(par)
428 end
429 return ret
430 end,
431
432 return_type_get = function(self, ft)
433 local v = self._obj:return_type_get(ft)
434 if not v then
435 return nil
436 end
437 return M.Type(v)
438 end,
439
440 return_default_value_get = function(self, ft)
441 local v = self._obj:return_default_value_get(ft)
442 if not v then
443 return nil
444 end
445 return M.Expression(v)
446 end,
447
448 return_doc_get = function(self, ft)
449 return M.Doc(self._obj:return_documentation_get(ft))
450 end,
451
452 return_is_warn_unused = function(self, ft)
453 return self._obj:return_is_warn_unused(ft)
454 end,
455
456 is_const = function(self)
457 return self._obj:is_const()
458 end,
459
460 nspaces_get = function(self, cl, root)
461 local tbl = cl:nspaces_get()
462 tbl[#tbl + 1] = self:type_str_get()
463 tbl[#tbl + 1] = self:name_get():lower()
464 if root ~= nil then
465 tbl[#tbl + 1] = not not root
466 end
467 return tbl
468 end,
469
470 is_same = function(self, other)
471 return self._obj == other._obj
472 end,
473
474 id_get = function(self)
475 return tonumber(ffi.cast("uintptr_t", self._obj))
476 end
477}
478
479M.Parameter = Node:clone {
480 UNKNOWN = eolian.parameter_dir.UNKNOWN,
481 IN = eolian.parameter_dir.IN,
482 OUT = eolian.parameter_dir.OUT,
483 INOUT = eolian.parameter_dir.INOUT,
484
485 direction_get = function(self)
486 return self._obj:direction_get()
487 end,
488
489 direction_name_get = function(self)
490 local dir_to_str = {
491 [self.IN] = "in",
492 [self.OUT] = "out",
493 [self.INOUT] = "inout"
494 }
495 return assert(dir_to_str[self:direction_get()],
496 "unknown parameter direction")
497 end,
498
499 type_get = function(self)
500 local v = self._obj:type_get()
501 if not v then
502 return nil
503 end
504 return M.Type(v)
505 end,
506
507 default_value_get = function(self)
508 local v = self._obj:default_value_get()
509 if not v then
510 return nil
511 end
512 return M.Expression(v)
513 end,
514
515 doc_get = function(self)
516 return M.Doc(self._obj:documentation_get())
517 end,
518
519 is_nonull = function(self)
520 return self._obj:is_nonull()
521 end,
522
523 is_nullable = function(self)
524 return self._obj:is_nullable()
525 end,
526
527 is_optional = function(self)
528 return self._obj:is_optional()
529 end,
530
531 is_same = function(self, other)
532 return self._obj == other._obj
533 end
534}
535
536M.Event = Node:clone {
537 type_get = function(self)
538 local v = self._obj:type_get()
539 if not v then
540 return nil
541 end
542 return M.Type(v)
543 end,
544
545 doc_get = function(self)
546 return M.Doc(self._obj:documentation_get())
547 end,
548
549 scope_get = function(self)
550 return self._obj:scope_get()
551 end,
552
553 c_name_get = function(self)
554 return self._obj:c_name_get()
555 end,
556
557 is_beta = function(self)
558 return self._obj:is_beta()
559 end,
560
561 is_hot = function(self)
562 return self._obj:is_hot()
563 end,
564
565 is_restart = function(self)
566 return self._obj:is_restart()
567 end,
568
569 nspaces_get = function(self, cl, root)
570 local tbl = cl:nspaces_get()
571 tbl[#tbl + 1] = "event"
572 tbl[#tbl + 1] = self:name_get():lower():gsub(",", "_")
573 if root ~= nil then
574 tbl[#tbl + 1] = not not root
575 end
576 return tbl
577 end
578}
579
580M.StructField = Node:clone {
581 doc_get = function(self)
582 return M.Doc(self._obj:documentation_get())
583 end,
584
585 type_get = function(self)
586 local v = self._obj:type_get()
587 if not v then
588 return nil
589 end
590 return M.Type(v)
591 end
592}
593
594M.EnumField = Node:clone {
595 c_name_get = function(self)
596 return self._obj:c_name_get()
597 end,
598
599 doc_get = function(self)
600 return M.Doc(self._obj:documentation_get())
601 end,
602
603 value_get = function(self, force)
604 local v = self._obj:value_get(force)
605 if not v then
606 return nil
607 end
608 return M.Expression(v)
609 end
610}
611
612local wrap_type_attrs = function(tp, str)
613 if tp:is_const() then
614 str = "const(" .. str .. ")"
615 end
616 -- TODO: implement new ownership system into docs
617 --if tp:is_own() then
618 -- str = "own(" .. str .. ")"
619 --end
620 local ffunc = tp:free_func_get()
621 if ffunc then
622 str = "free(" .. str .. ", " .. ffunc .. ")"
623 end
624 if tp:is_ptr() then
625 str = "ptr(" .. str .. ")"
626 end
627 return str
628end
629
630M.Type = Node:clone {
631 UNKNOWN = eolian.type_type.UNKNOWN,
632 VOID = eolian.type_type.VOID,
633 REGULAR = eolian.type_type.REGULAR,
634 CLASS = eolian.type_type.CLASS,
635 UNDEFINED = eolian.type_type.UNDEFINED,
636
637 type_get = function(self)
638 return self._obj:type_get()
639 end,
640
641 file_get = function(self)
642 return self._obj:file_get()
643 end,
644
645 base_type_get = function(self)
646 local v = self._obj:base_type_get()
647 if not v then
648 return nil
649 end
650 return M.Type(v)
651 end,
652
653 next_type_get = function(self)
654 local v = self._obj:next_type_get()
655 if not v then
656 return nil
657 end
658 return M.Type(v)
659 end,
660
661 typedecl_get = function(self)
662 local v = self._obj:typedecl_get()
663 if not v then
664 return nil
665 end
666 return M.Typedecl(v)
667 end,
668
669 aliased_base_get = function(self)
670 local v = self._obj:aliased_base_get()
671 if not v then
672 return nil
673 end
674 return M.Type(v)
675 end,
676
677 class_get = function(self)
678 return self._obj:class_get()
679 end,
680
681 is_owned = function(self)
682 return self._obj:is_owned()
683 end,
684
685 is_const = function(self)
686 return self._obj:is_const()
687 end,
688
689 is_ptr = function(self)
690 return self._obj:is_ptr()
691 end,
692
693 c_type_get = function(self)
694 return self._obj:c_type_get(eolian.c_type_type.DEFAULT)
695 end,
696
697 free_func_get = function(self)
698 return self._obj:free_func_get()
699 end,
700
701 -- utils
702
703 serialize = function(self)
704 local tpt = self:type_get()
705 if tpt == self.UNKNOWN then
706 error("unknown type: " .. self:name_get())
707 elseif tpt == self.VOID then
708 return wrap_type_attrs(self, "void")
709 elseif tpt == self.UNDEFINED then
710 return wrap_type_attrs(self, "__undefined_type")
711 elseif tpt == self.REGULAR or tpt == self.CLASS then
712 local stp = self:base_type_get()
713 if stp then
714 local stypes = {}
715 while stp do
716 stypes[#stypes + 1] = stp:serialize()
717 stp = stp:next_type_get()
718 end
719 return wrap_type_attrs(self, self:name_get() .. "<"
720 .. table.concat(stypes, ", ") .. ">")
721 end
722 return wrap_type_attrs(self, self:name_get())
723 end
724 error("unhandled type type: " .. tpt)
725 end
726}
727
728M.type_cstr_get = function(tp, suffix)
729 tp = tp or "void"
730 local ct = (type(tp) == "string") and tp or tp:c_type_get()
731 if not suffix then
732 return ct
733 end
734 if ct:sub(#ct) == "*" then
735 return ct .. suffix
736 else
737 return ct .. " " .. suffix
738 end
739end
740
741local add_typedecl_attrs = function(tp, buf)
742 if tp:is_extern() then
743 buf[#buf + 1] = "@extern "
744 end
745 local ffunc = tp:free_func_get()
746 if ffunc then
747 buf[#buf + 1] = "@free("
748 buf[#buf + 1] = ffunc
749 buf[#buf + 1] = ") "
750 end
751end
752
753M.Typedecl = Node:clone {
754 UNKNOWN = eolian.typedecl_type.UNKNOWN,
755 STRUCT = eolian.typedecl_type.STRUCT,
756 STRUCT_OPAQUE = eolian.typedecl_type.STRUCT_OPAQUE,
757 ENUM = eolian.typedecl_type.ENUM,
758 ALIAS = eolian.typedecl_type.ALIAS,
759 FUNCTION_POINTER = eolian.typedecl_type.FUNCTION_POINTER,
760
761 type_get = function(self)
762 return self._obj:type_get()
763 end,
764
765 type_str_get = function(self)
766 local strs = {
767 [eolian.typedecl_type.STRUCT] = "struct",
768 [eolian.typedecl_type.STRUCT_OPAQUE] = "struct",
769 [eolian.typedecl_type.ENUM] = "enum",
770 [eolian.typedecl_type.ALIAS] = "alias"
771 }
772 return strs[self:type_get()]
773 end,
774
775 struct_fields_get = function(self)
776 local ret = {}
777 for fl in self._obj:struct_fields_get() do
778 ret[#ret + 1] = M.StructField(fl)
779 end
780 return ret
781 end,
782
783 struct_field_get = function(self, name)
784 local v = self._obj:struct_field_get(name)
785 if not v then
786 return nil
787 end
788 return M.StructField(v)
789 end,
790
791 enum_fields_get = function(self)
792 local ret = {}
793 for fl in self._obj:enum_fields_get() do
794 ret[#ret + 1] = M.EnumField(fl)
795 end
796 return ret
797 end,
798
799 enum_field_get = function(self, name)
800 local v = self._obj:enum_field_get(name)
801 if not v then
802 return nil
803 end
804 return M.EnumField(v)
805 end,
806
807 enum_legacy_prefix_get = function(self)
808 return self._obj:enum_legacy_prefix_get()
809 end,
810
811 doc_get = function(self)
812 return M.Doc(self._obj:documentation_get())
813 end,
814
815 file_get = function(self)
816 return self._obj:file_get()
817 end,
818
819 base_type_get = function(self)
820 local v = self._obj:base_type_get()
821 if not v then
822 return nil
823 end
824 return M.Type(v)
825 end,
826
827 aliased_base_get = function(self)
828 local v = self._obj:aliased_base_get()
829 if not v then
830 return nil
831 end
832 return M.Type(v)
833 end,
834
835 is_extern = function(self)
836 return self._obj:is_extern()
837 end,
838
839 c_type_get = function(self)
840 return self._obj:c_type_get()
841 end,
842
843 free_func_get = function(self)
844 return self._obj:free_func_get()
845 end,
846
847 function_pointer_get = function(self)
848 local v = self._obj:function_pointer_get()
849 if not v then
850 return nil
851 end
852 return M.Function(v)
853 end,
854
855 nspaces_get = function(self, root)
856 return M.Node.nspaces_get(self, root)
857 end,
858
859 -- static getters
860
861 all_aliases_get = function()
862 local ret = {}
863 for tp in eos:aliases_get() do
864 local tpo = M.Typedecl(tp)
865 if matches_filter(tpo) then
866 ret[#ret + 1] = tpo
867 end
868 end
869 return ret
870 end,
871
872 all_structs_get = function()
873 local ret = {}
874 for tp in eos:structs_get() do
875 local tpo = M.Typedecl(tp)
876 if matches_filter(tpo) then
877 ret[#ret + 1] = tpo
878 end
879 end
880 return ret
881 end,
882
883 all_enums_get = function()
884 local ret = {}
885 for tp in eos:enums_get() do
886 local tpo = M.Typedecl(tp)
887 local tpn = tpo:nspaces_get()
888 if matches_filter(tpo) then
889 ret[#ret + 1] = tpo
890 end
891 end
892 return ret
893 end,
894
895 aliases_by_file_get = function(fn)
896 local ret = {}
897 for tp in eos:aliases_by_file_get(fn) do
898 ret[#ret + 1] = M.Typedecl(tp)
899 end
900 return ret
901 end,
902
903 structs_by_file_get = function(fn)
904 local ret = {}
905 for tp in eos:struts_by_file_get(fn) do
906 ret[#ret + 1] = M.Typedecl(tp)
907 end
908 return ret
909 end,
910
911 enums_by_file_get = function(fn)
912 local ret = {}
913 for tp in eeos:enums_by_file_get(fn) do
914 ret[#ret + 1] = M.Typedecl(tp)
915 end
916 return ret
917 end,
918
919 alias_by_name_get = function(tn)
920 local v = eos:alias_by_name_get(tn)
921 if not v then
922 return nil
923 end
924 return M.Typedecl(v)
925 end,
926
927 struct_by_name_get = function(tn)
928 local v = eos:struct_by_name_get(tn)
929 if not v then
930 return nil
931 end
932 return M.Typedecl(v)
933 end,
934
935 enum_by_name_get = function(tn)
936 local v = eos:enum_by_name_get(tn)
937 if not v then
938 return nil
939 end
940 return M.Typedecl(v)
941 end,
942
943 -- utils
944
945 serialize = function(self)
946 local tpt = self:type_get()
947 if tpt == self.UNKNOWN then
948 error("unknown typedecl: " .. self:name_get())
949 elseif tpt == self.STRUCT or
950 tpt == self.STRUCT_OPAQUE then
951 local buf = { "struct " }
952 add_typedecl_attrs(self, buf)
953 buf[#buf + 1] = self:name_get()
954 if tpt == self.STRUCT_OPAQUE then
955 buf[#buf + 1] = ";"
956 return table.concat(buf)
957 end
958 local fields = self:struct_fields_get()
959 if #fields == 0 then
960 buf[#buf + 1] = " {}"
961 return table.concat(buf)
962 end
963 buf[#buf + 1] = " {\n"
964 for i, fld in ipairs(fields) do
965 buf[#buf + 1] = " "
966 buf[#buf + 1] = fld:name_get()
967 buf[#buf + 1] = ": "
968 buf[#buf + 1] = fld:type_get():serialize()
969 buf[#buf + 1] = ";\n"
970 end
971 buf[#buf + 1] = "}"
972 return table.concat(buf)
973 elseif tpt == self.ENUM then
974 local buf = { "enum " }
975 add_typedecl_attrs(self, buf)
976 buf[#buf + 1] = self:name_get()
977 local fields = self:enum_fields_get()
978 if #fields == 0 then
979 buf[#buf + 1] = " {}"
980 return table.concat(buf)
981 end
982 buf[#buf + 1] = " {\n"
983 for i, fld in ipairs(fields) do
984 buf[#buf + 1] = " "
985 buf[#buf + 1] = fld:name_get()
986 local val = fld:value_get()
987 if val then
988 buf[#buf + 1] = ": "
989 buf[#buf + 1] = val:serialize()
990 end
991 if i == #fields then
992 buf[#buf + 1] = "\n"
993 else
994 buf[#buf + 1] = ",\n"
995 end
996 end
997 buf[#buf + 1] = "}"
998 return table.concat(buf)
999 elseif tpt == self.ALIAS then
1000 local buf = { "type " }
1001 add_typedecl_attrs(self, buf)
1002 buf[#buf + 1] = self:name_get()
1003 buf[#buf + 1] = ": "
1004 buf[#buf + 1] = self:base_type_get():serialize()
1005 buf[#buf + 1] = ";"
1006 return table.concat(buf)
1007 elseif tpt == self.FUNCTION_POINTER then
1008 return "TODO"
1009 end
1010 error("unhandled typedecl type: " .. tpt)
1011 end,
1012
1013 serialize_c = function(self, ns)
1014 local tpt = self:type_get()
1015 if tpt == self.UNKNOWN then
1016 error("unknown typedecl: " .. self:name_get())
1017 elseif tpt == self.STRUCT or
1018 tpt == self.STRUCT_OPAQUE then
1019 local buf = { "typedef struct " }
1020 local fulln = self:name_get():gsub("%.", "_");
1021 keyref.add(fulln, ns, "c")
1022 buf[#buf + 1] = "_" .. fulln;
1023 if tpt == self.STRUCT_OPAQUE then
1024 buf[#buf + 1] = " " .. fulln .. ";"
1025 return table.concat(buf)
1026 end
1027 local fields = self:struct_fields_get()
1028 if #fields == 0 then
1029 buf[#buf + 1] = " {} " .. fulln .. ";"
1030 return table.concat(buf)
1031 end
1032 buf[#buf + 1] = " {\n"
1033 for i, fld in ipairs(fields) do
1034 buf[#buf + 1] = " "
1035 buf[#buf + 1] = M.type_cstr_get(fld:type_get(), fld:name_get())
1036 buf[#buf + 1] = ";\n"
1037 end
1038 buf[#buf + 1] = "} " .. fulln .. ";"
1039 return table.concat(buf)
1040 elseif tpt == self.ENUM then
1041 local buf = { "typedef enum" }
1042 local fulln = self:name_get():gsub("%.", "_");
1043 keyref.add(fulln, ns, "c")
1044 local fields = self:enum_fields_get()
1045 if #fields == 0 then
1046 buf[#buf + 1] = " {} " .. fulln .. ";"
1047 return table.concat(buf)
1048 end
1049 buf[#buf + 1] = " {\n"
1050 for i, fld in ipairs(fields) do
1051 buf[#buf + 1] = " "
1052 local cn = fld:c_name_get()
1053 buf[#buf + 1] = cn
1054 keyref.add(cn, ns, "c")
1055 local val = fld:value_get()
1056 if val then
1057 buf[#buf + 1] = " = "
1058 local ev = val:eval_enum()
1059 local lit = ev:to_literal()
1060 buf[#buf + 1] = lit
1061 local ser = val:serialize()
1062 if ser and ser ~= lit then
1063 buf[#buf + 1] = " /* " .. ser .. " */"
1064 end
1065 end
1066 if i == #fields then
1067 buf[#buf + 1] = "\n"
1068 else
1069 buf[#buf + 1] = ",\n"
1070 end
1071 end
1072 buf[#buf + 1] = "} " .. fulln .. ";"
1073 return table.concat(buf)
1074 elseif tpt == self.ALIAS then
1075 local fulln = self:name_get():gsub("%.", "_");
1076 keyref.add(fulln, ns, "c")
1077 return "typedef "
1078 .. M.type_cstr_get(self:base_type_get(), fulln) .. ";"
1079 elseif tpt == self.FUNCTION_POINTER then
1080 return "TODO"
1081 end
1082 error("unhandled typedecl type: " .. tpt)
1083 end
1084}
1085
1086M.Variable = Node:clone {
1087 UNKNOWN = eolian.variable_type.UNKNOWN,
1088 CONSTANT = eolian.variable_type.CONSTANT,
1089 GLOBAL = eolian.variable_type.GLOBAL,
1090
1091 type_get = function(self)
1092 return self._obj:type_get()
1093 end,
1094
1095 type_str_get = function(self)
1096 local strs = {
1097 [eolian.variable_type.CONSTANT] = "constant",
1098 [eolian.variable_type.GLOBAL] = "global"
1099 }
1100 return strs[self:type_get()]
1101 end,
1102
1103 doc_get = function(self)
1104 return M.Doc(self._obj:documentation_get())
1105 end,
1106
1107 file_get = function(self)
1108 return self._obj:file_get()
1109 end,
1110
1111 base_type_get = function(self)
1112 local v = self._obj:base_type_get()
1113 if not v then
1114 return nil
1115 end
1116 return M.Type(v)
1117 end,
1118
1119 value_get = function(self)
1120 local v = self._obj:value_get()
1121 if not v then
1122 return nil
1123 end
1124 return M.Expression(v)
1125 end,
1126
1127 is_extern = function(self)
1128 return self._obj:is_extern()
1129 end,
1130
1131 nspaces_get = function(self, root)
1132 return M.Node.nspaces_get(self, root)
1133 end,
1134
1135 serialize = function(self)
1136 local buf = {}
1137 if self:type_get() == self.GLOBAL then
1138 buf[#buf + 1] = "var "
1139 else
1140 buf[#buf + 1] = "const "
1141 end
1142 if self:is_extern() then
1143 buf[#buf + 1] = "@extern "
1144 end
1145 buf[#buf + 1] = self:name_get()
1146 buf[#buf + 1] = ": "
1147 buf[#buf + 1] = self:base_type_get():serialize()
1148 local val = self:value_get()
1149 if val then
1150 buf[#buf + 1] = " = "
1151 buf[#buf + 1] = val:serialize()
1152 end
1153 buf[#buf + 1] = ";"
1154 return table.concat(buf)
1155 end,
1156
1157 serialize_c = function(self, ns)
1158 local buf = {}
1159 local bt = self:base_type_get()
1160 local fulln = self:name_get():gsub("%.", "_"):upper()
1161 keyref.add(fulln, ns, "c")
1162 if self:type_get() == self.GLOBAL then
1163 local ts = bt:c_type_get()
1164 buf[#buf + 1] = ts
1165 if ts:sub(#ts) ~= "*" then
1166 buf[#buf + 1] = " "
1167 end
1168 buf[#buf + 1] = fulln
1169 local val = self:value_get()
1170 if val then
1171 buf[#buf + 1] = " = "
1172 local vt = val:eval_type(bt)
1173 local lv = vt:to_literal()
1174 local sv = val:serialize()
1175 buf[#buf + 1] = lv
1176 if lv ~= sv then
1177 buf[#buf + 1] = "/* " .. sv .. " */"
1178 end
1179 end
1180 buf[#buf + 1] = ";"
1181 else
1182 buf[#buf + 1] = "#define "
1183 buf[#buf + 1] = fulln
1184 buf[#buf + 1] = " "
1185 local val = self:value_get()
1186 local vt = val:eval_type(bt)
1187 local lv = vt:to_literal()
1188 local sv = val:serialize()
1189 buf[#buf + 1] = lv
1190 if lv ~= sv then
1191 buf[#buf + 1] = "/* " .. sv .. " */"
1192 end
1193 end
1194 return table.concat(buf)
1195 end,
1196
1197 -- static getters
1198
1199 all_globals_get = function()
1200 local ret = {}
1201 for v in eos:globals_get() do
1202 ret[#ret + 1] = M.Variable(v)
1203 end
1204 return ret
1205 end,
1206
1207 all_constants_get = function()
1208 local ret = {}
1209 for v in eos:constants_get() do
1210 ret[#ret + 1] = M.Variable(v)
1211 end
1212 return ret
1213 end,
1214
1215 globals_by_file_get = function(fn)
1216 local ret = {}
1217 for v in eos:globals_by_file_get(fn) do
1218 ret[#ret + 1] = M.Variable(v)
1219 end
1220 return ret
1221 end,
1222
1223 constants_by_file_get = function(fn)
1224 local ret = {}
1225 for v in eos:constants_by_file_get(fn) do
1226 ret[#ret + 1] = M.Variable(v)
1227 end
1228 return ret
1229 end,
1230
1231 global_by_name_get = function(vn)
1232 local v = eos:global_by_name_get(vn)
1233 if not v then
1234 return nil
1235 end
1236 return M.Variable(v)
1237 end,
1238
1239 constant_by_name_get = function(vn)
1240 local v = eos:constant_by_name_get(vn)
1241 if not v then
1242 return nil
1243 end
1244 return M.Variable(v)
1245 end
1246}
1247
1248M.Expression = Node:clone {
1249 eval_enum = function(self)
1250 return self._obj:eval(eolian.expression_mask.INT)
1251 end,
1252
1253 eval_type = function(self, tp)
1254 return self._obj:eval_type(tp.type)
1255 end,
1256
1257 serialize = function(self)
1258 return self._obj:serialize()
1259 end
1260}
1261
1262M.Implement = Node:clone {
1263 class_get = function(self)
1264 local ccl = self._cache_cl
1265 if ccl then
1266 return ccl
1267 end
1268 -- so that we don't re-instantiate, it gets cached over there too
1269 ccl = M.Class.by_name_get(self._obj:class_get():name_get())
1270 self._cache_cl = ccl
1271 return ccl
1272 end,
1273
1274 function_get = function(self)
1275 local func, tp = self._cache_func, self._cache_tp
1276 if func then
1277 return func, tp
1278 end
1279 func, tp = self._obj:function_get()
1280 func = M.Function(func)
1281 self._cache_func, self._cache_tp = func, tp
1282 return func, tp
1283 end,
1284
1285 doc_get = function(self, ftype, inh)
1286 return M.Doc(self._obj:documentation_get(ftype))
1287 end,
1288
1289 fallback_doc_get = function(self, inh)
1290 local ig, is = self:is_prop_get(), self:is_prop_set()
1291 if ig and not is then
1292 return self:doc_get(M.Function.PROP_GET, inh)
1293 elseif is and not ig then
1294 return self:doc_get(M.Function.PROP_SET, inh)
1295 end
1296 return nil
1297 end,
1298
1299 is_auto = function(self, ftype)
1300 return self._obj:is_auto(ftype)
1301 end,
1302
1303 is_empty = function(self, ftype)
1304 return self._obj:is_empty(ftype)
1305 end,
1306
1307 is_pure_virtual = function(self, ftype)
1308 return self._obj:is_pure_virtual(ftype)
1309 end,
1310
1311 is_prop_get = function(self)
1312 return self._obj:is_prop_get()
1313 end,
1314
1315 is_prop_set = function(self)
1316 return self._obj:is_prop_set()
1317 end,
1318
1319 is_overridden = function(self, cl)
1320 return cl.class ~= self._obj:class_get()
1321 end
1322}
1323
1324M.DocTokenizer = util.Object:clone {
1325 UNKNOWN = eolian.doc_token_type.UNKNOWN,
1326 TEXT = eolian.doc_token_type.TEXT,
1327 REF = eolian.doc_token_type.REF,
1328 MARK_NOTE = eolian.doc_token_type.MARK_NOTE,
1329 MARK_WARNING = eolian.doc_token_type.MARK_WARNING,
1330 MARK_REMARK = eolian.doc_token_type.MARK_REMARK,
1331 MARK_TODO = eolian.doc_token_type.MARK_TODO,
1332 MARKUP_MONOSPACE = eolian.doc_token_type.MARKUP_MONOSPACE,
1333
1334 __ctor = function(self, str)
1335 self.tok = eolian.doc_token_init()
1336 self.str = str
1337 assert(self.str)
1338 assert(self.tok)
1339 end,
1340
1341 tokenize = function(self)
1342 self.str = eolian.documentation_tokenize(self.str, self.tok)
1343 return not not self.str
1344 end,
1345
1346 text_get = function(self)
1347 return self.tok:text_get()
1348 end,
1349
1350 type_get = function(self)
1351 return self.tok:type_get()
1352 end,
1353
1354 ref_resolve = function(self, root)
1355 -- FIXME: unit
1356 local tp, d1, d2 = self.tok:ref_resolve(eos)
1357 local reft = eolian.object_type
1358 local ret = {}
1359 if tp == reft.CLASS or tp == reft.FUNCTION or tp == reft.EVENT then
1360 if not class_type_str[d1:type_get()] then
1361 error("unknown class type for class '"
1362 .. d1:name_get() .. "'")
1363 end
1364 elseif tp == reft.TYPEDECL then
1365 elseif tp == reft.ENUM_FIELD or tp == reft.STRUCT_FIELD then
1366 -- TODO: point to field
1367 elseif tp == reft.VARIABLE then
1368 else
1369 error("invalid reference '" .. self:text_get() .. "'")
1370 end
1371 for tok in d1:name_get():gmatch("[^%.]+") do
1372 ret[#ret + 1] = tok:lower()
1373 end
1374 if tp == reft.FUNCTION then
1375 ret[#ret + 1] = func_type_str[d2:type_get()]
1376 ret[#ret + 1] = d2:name_get():lower()
1377 elseif tp == reft.EVENT then
1378 ret[#ret + 1] = "event"
1379 ret[#ret + 1] = d2:name_get():lower()
1380 end
1381 if root ~= nil then
1382 ret[#ret + 1] = not not root
1383 end
1384 return ret
1385 end
1386}
1387
1388M.scan_directory = function(dir)
1389 if not dir then
1390 if not eos:system_directory_add() then
1391 error("failed scanning system directory")
1392 end
1393 return
1394 end
1395 if not eos:directory_add(dir) then
1396 error("failed scanning directory: " .. dir)
1397 end
1398end
1399
1400M.parse = function(st)
1401 if not eos:all_eot_files_parse() then
1402 error("failed parsing eo type files")
1403 end
1404 if st and st:match("%.") then
1405 if not eos:file_parse(st:gsub("%.", "_"):lower() .. ".eo") then
1406 error("failed parsing eo file")
1407 end
1408 else
1409 if not eos:all_eo_files_parse() then
1410 error("failed parsing eo files")
1411 end
1412 end
1413 -- build reverse inheritance hierarchy
1414 for cl in eos:classes_get() do
1415 local cln = cl:name_get()
1416 for icl in cl:inherits_get() do
1417 local t = revh[icl]
1418 if not t then
1419 t = {}
1420 revh[icl] = t
1421 end
1422 t[#t + 1] = M.Class.by_name_get(cl:name_get())
1423 end
1424 end
1425end
1426
1427return M
diff --git a/src/scripts/elua/apps/docgen/keyref.lua b/src/scripts/elua/apps/docgen/keyref.lua
deleted file mode 100644
index 56311d9742..0000000000
--- a/src/scripts/elua/apps/docgen/keyref.lua
+++ /dev/null
@@ -1,41 +0,0 @@
1local M = {}
2
3local key_refs = {}
4
5M.add = function(key, link, lang)
6 local rfs = key_refs[lang]
7 if not rfs then
8 key_refs[lang] = {}
9 rfs = key_refs[lang]
10 end
11 rfs[key] = link
12end
13
14M.build = function()
15 local writer = require("docgen.writer")
16 local dutil = require("docgen.util")
17 for lang, rfs in pairs(key_refs) do
18 local f = writer.Writer({ "ref", lang, "keyword-list" })
19 local arr = {}
20 for refn, v in pairs(rfs) do
21 arr[#arr + 1] = refn
22 local rf = writer.Writer({ "ref", lang, "key", refn })
23 v[#v + 1] = true
24 rf:write_include(rf.INCLUDE_PAGE, v)
25 rf:finish()
26 end
27 table.sort(arr)
28 f:write_raw(table.concat(arr, "\n"))
29 f:write_nl()
30 f:finish()
31 local lf = writer.Writer({ "ref", lang, "keyword-link" })
32 lf:write_raw("/", dutil.path_join(
33 dutil.nspace_to_path(dutil.get_root_ns()),
34 "ref", lang, "key", "{FNAME}"
35 ))
36 lf:write_nl()
37 lf:finish()
38 end
39end
40
41return M
diff --git a/src/scripts/elua/apps/docgen/mono.lua b/src/scripts/elua/apps/docgen/mono.lua
deleted file mode 100644
index dbe98de171..0000000000
--- a/src/scripts/elua/apps/docgen/mono.lua
+++ /dev/null
@@ -1,614 +0,0 @@
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: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:name_get() == "string" then
111 return "System.String"
112 elseif tp: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:name_get())
119 tpt = tpdecl:type_get()
120 return get_class_name(tp) --tp:name_get()
121 else
122 --print("regular type is ", tp:name_get())
123 return tp: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: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: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:name_get() < cl2: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: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: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: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: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: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/docgen/stats.lua b/src/scripts/elua/apps/docgen/stats.lua
deleted file mode 100644
index 9659f86dcd..0000000000
--- a/src/scripts/elua/apps/docgen/stats.lua
+++ /dev/null
@@ -1,274 +0,0 @@
1local is_verbose = false
2
3local M = {}
4
5local stats = {}
6
7local stats_pd = function(n)
8 local ret = 0
9 if n == 0 then
10 return 1
11 end
12 while (n ~= 0) do
13 n = math.floor(n / 10)
14 ret = ret + 1
15 end
16 return ret
17end
18
19local fcol = 30
20local ncol = 0
21
22local get_percent = function(sv, svu)
23 return (sv == 0) and 100 or math.floor(((sv - svu) / sv) * 100 + 0.5)
24end
25
26local print_stat = function(printname, statname)
27 local sv = stats[statname] or 0
28 local svu = stats[statname .. "_undoc"] or 0
29 local percent = get_percent(sv, svu)
30 local tb = (" "):rep(math.max(0, fcol - #printname - 1) + ncol - stats_pd(sv))
31 local dtb = (" "):rep(ncol - stats_pd(sv - svu))
32 local ptb = (" "):rep(3 - stats_pd(percent))
33 print(("%s:%s%d (documented: %s%d or %s%d%%)")
34 :format(printname, tb, sv, dtb, sv - svu, ptb, percent))
35end
36
37local get_secstats = function(...)
38 local sv, svu = 0, 0
39 for i, v in ipairs({ ... }) do
40 sv = sv + (stats[v] or 0)
41 svu = svu + (stats[v .. "_undoc"] or 0)
42 end
43 return sv - svu, sv, get_percent(sv, svu)
44end
45
46M.print = function()
47 for k, v in pairs(stats) do
48 ncol = math.max(ncol, stats_pd(v))
49 end
50
51 print(("=== CLASS SECTION: %d out of %d (%d%%) ===\n")
52 :format(get_secstats("class", "interface", "mixin", "event")))
53 print_stat("Classes", "class")
54 print_stat("Interfaces", "interface")
55 print_stat("Mixins", "mixin")
56 print_stat("Events", "event")
57
58 print(("\n=== FUNCTION SECTION: %d out of %d (%d%%) ===\n")
59 :format(get_secstats("method", "param", "mret",
60 "getter", "gret", "gkey", "gvalue",
61 "setter", "sret", "skey", "svalue")))
62 print_stat("Methods", "method")
63 print_stat(" Method params", "param")
64 print_stat(" Method returns", "mret")
65 print_stat("Getters", "getter")
66 print_stat(" Getter returns", "gret")
67 print_stat(" Getter keys", "gkey")
68 print_stat(" Getter values", "gvalue")
69 print_stat("Setters", "setter")
70 print_stat(" Setter returns", "sret")
71 print_stat(" Setter keys", "skey")
72 print_stat(" Setter values", "svalue")
73
74 print(("\n=== TYPE SECTION: %d out of %d (%d%%) ===\n")
75 :format(get_secstats("alias", "struct", "sfield", "enum", "efield")))
76 print_stat("Aliases", "alias")
77 print_stat("Structs", "struct")
78 print_stat("Struct fields", "sfield")
79 print_stat("Enums", "enum")
80 print_stat("Enum fields", "efield")
81
82 print(("\n=== VARIABLE SECTION: %d out of %d (%d%%) ===\n")
83 :format(get_secstats("constant", "global")))
84 print_stat("Constants", "constant")
85 print_stat("Globals", "global")
86
87 local sv, svu = 0, 0
88 for k, v in pairs(stats) do
89 if k:match(".*_undoc$") then
90 svu = svu + v
91 else
92 sv = sv + v
93 end
94 end
95 print(("\n=== TOTAL: %d out of %d (%d%%) ===")
96 :format(sv - svu, sv, get_percent(sv, svu)))
97end
98
99local stat_incr = function(name, missing)
100 if not stats[name] then
101 stats[name], stats[name .. "_undoc"] = 0, 0
102 end
103 stats[name] = stats[name] + 1
104 if missing then
105 stats[name .. "_undoc"] = stats[name .. "_undoc"] + 1
106 end
107end
108
109local print_missing = function(name, tp)
110 if not is_verbose then
111 return
112 end
113 print(tp .. " '" .. name .. "'" .. " missing documentation")
114end
115
116M.check_class = function(cl)
117 local ct = cl:type_str_get()
118 if not ct then
119 return
120 end
121 if not cl:doc_get():exists() then
122 print_missing(cl:name_get(), ct)
123 stat_incr(ct, true)
124 else
125 stat_incr(ct, false)
126 end
127
128 for i, ev in ipairs(cl:events_get()) do
129 if not ev:doc_get():exists() then
130 print_missing(cl:name_get() .. "." .. ev:name_get(), "event")
131 stat_incr("event", true)
132 else
133 stat_incr("event", false)
134 end
135 end
136end
137
138M.check_method = function(fn, cl)
139 local fulln = cl:name_get() .. "." .. fn:name_get()
140 if fn:return_type_get(fn.METHOD) then
141 if not fn:return_doc_get(fn.METHOD):exists() then
142 print_missing(fulln, "method return")
143 stat_incr("mret", true)
144 else
145 stat_incr("mret", false)
146 end
147 end
148 if not fn:implement_get():doc_get(fn.METHOD):exists() then
149 print_missing(fulln, "method")
150 stat_incr("method", true)
151 else
152 stat_incr("method", false)
153 end
154 for i, p in ipairs(fn:parameters_get()) do
155 if not p:doc_get():exists() then
156 print_missing(fulln .. "." .. p:name_get(), "method parameter")
157 stat_incr("param", true)
158 else
159 stat_incr("param", false)
160 end
161 end
162end
163
164M.check_property = function(fn, cl, ft)
165 local pfxs = {
166 [fn.PROP_GET] = "g",
167 [fn.PROP_SET] = "s",
168 }
169 local pfx = pfxs[ft]
170
171 local fulln = cl:name_get() .. "." .. fn:name_get()
172 if fn:return_type_get(ft) then
173 if not fn:return_doc_get(ft):exists() then
174 print_missing(fulln, pfx .. "etter return")
175 stat_incr(pfx .. "ret", true)
176 else
177 stat_incr(pfx .. "ret", false)
178 end
179 end
180
181 local pimp = fn:implement_get()
182
183 if not pimp:doc_get(fn.PROPERTY):exists() and not pimp:doc_get(ft):exists() then
184 print_missing(fulln, pfx .. "etter")
185 stat_incr(pfx .. "etter", true)
186 else
187 stat_incr(pfx .. "etter", false)
188 end
189
190 for i, p in ipairs(fn:property_keys_get(ft)) do
191 if not p:doc_get():exists() then
192 print_missing(fulln .. "." .. p:name_get(), pfx .. "etter key")
193 stat_incr(pfx .. "key", true)
194 else
195 stat_incr(pfx .. "key", false)
196 end
197 end
198
199 for i, p in ipairs(fn:property_values_get(ft)) do
200 if not p:doc_get():exists() then
201 print_missing(fulln .. "." .. p:name_get(), pfx .. "etter value")
202 stat_incr(pfx .. "value", true)
203 else
204 stat_incr(pfx .. "value", false)
205 end
206 end
207end
208
209M.check_alias = function(v)
210 if not v:doc_get():exists() then
211 print_missing(v:name_get(), "alias")
212 stat_incr("alias", true)
213 else
214 stat_incr("alias", false)
215 end
216end
217
218M.check_struct = function(v)
219 if not v:doc_get():exists() then
220 print_missing(v:name_get(), "struct")
221 stat_incr("struct", true)
222 else
223 stat_incr("struct", false)
224 end
225 for i, fl in ipairs(v:struct_fields_get()) do
226 if not fl:doc_get():exists() then
227 print_missing(v:name_get() .. "." .. fl:name_get(), "struct field")
228 stat_incr("sfield", true)
229 else
230 stat_incr("sfield", false)
231 end
232 end
233end
234
235M.check_enum = function(v)
236 if not v:doc_get():exists() then
237 print_missing(v:name_get(), "enum")
238 stat_incr("enum", true)
239 else
240 stat_incr("enum", false)
241 end
242 for i, fl in ipairs(v:enum_fields_get()) do
243 if not fl:doc_get():exists() then
244 print_missing(v:name_get() .. "." .. fl:name_get(), "enum field")
245 stat_incr("efield", true)
246 else
247 stat_incr("efield", false)
248 end
249 end
250end
251
252M.check_constant = function(v)
253 if not v:doc_get():exists() then
254 print_missing(v:name_get(), "constant")
255 stat_incr("constant", true)
256 else
257 stat_incr("constant", false)
258 end
259end
260
261M.check_global = function(v)
262 if not v:doc_get():exists() then
263 print_missing(v:name_get(), "global")
264 stat_incr("global", true)
265 else
266 stat_incr("global", false)
267 end
268end
269
270M.init = function(verbose)
271 is_verbose = verbose
272end
273
274return M
diff --git a/src/scripts/elua/apps/docgen/util.lua b/src/scripts/elua/apps/docgen/util.lua
deleted file mode 100644
index 65968ac3e7..0000000000
--- a/src/scripts/elua/apps/docgen/util.lua
+++ /dev/null
@@ -1,50 +0,0 @@
1local cutil = require("cutil")
2local ffi = require("ffi")
3
4local M = {}
5
6local doc_root, root_ns
7
8local path_sep, rep_sep = "/", "\\"
9if ffi.os == "Windows" then
10 path_sep, rep_sep = rep_sep, path_sep
11end
12
13M.path_join = function(...)
14 return (table.concat({ ... }, path_sep):gsub(rep_sep, path_sep))
15end
16
17M.path_to_nspace = function(p)
18 return p:gsub(rep_sep, ":"):gsub(path_sep, ":"):lower()
19end
20
21M.nspace_to_path = function(ns)
22 return ns:gsub(":", path_sep):gsub(rep_sep, path_sep):lower()
23end
24
25M.make_page = function(path, ext)
26 return M.path_join(doc_root, path .. "." .. ext)
27end
28
29M.get_root_ns = function()
30 return root_ns
31end
32
33M.mkdir_r = function(dirn)
34 assert(cutil.file_mkpath(M.path_join(doc_root, dirn)))
35end
36
37M.mkdir_p = function(path)
38 M.mkdir_r(path:match("(.+)" .. path_sep .. "([^" .. path_sep .. "]+)"))
39end
40
41M.rm_root = function()
42 cutil.file_rmrf(doc_root)
43end
44
45M.init = function(root, rns)
46 doc_root = root:gsub(rep_sep, path_sep)
47 root_ns = rns
48end
49
50return M
diff --git a/src/scripts/elua/apps/docgen/writer.lua b/src/scripts/elua/apps/docgen/writer.lua
deleted file mode 100644
index 2aeadf8da7..0000000000
--- a/src/scripts/elua/apps/docgen/writer.lua
+++ /dev/null
@@ -1,397 +0,0 @@
1local util = require("util")
2
3local dutil = require("docgen.util")
4local dtree = require("docgen.doctree")
5
6local M = {}
7
8local root_nspace, features
9
10M.has_feature = function(fname)
11 if not features then
12 return false
13 end
14 return not not features[fname]
15end
16
17local allowed_incflags = {
18 noheader = { "noheader", "showheader" },
19 firstseconly = { "firstseconly", "fullpage" },
20 readmore = { "readmore", "noreadmore" },
21 footer = { "footer", "nofooter" },
22 link = { "link", "nolink" },
23 permalink = { "permalink", "nopermalink" },
24 date = { "date", "nodate" },
25 mdate = { "mdate", "nomdate" },
26 user = { "user", "nouser" },
27 comments = { "comments", "nocomments" },
28 linkbacks = { "linkbacks", "nolinkbacks" },
29 tags = { "tags", "notags" },
30 editbutton = { "editbtn", "noeditbtn" },
31 redirect = { "redirect", "noredirect" },
32 indent = { "indent", "noindent" },
33 linkonly = { "linkonly", "nolinkonly" },
34 title = { "title", "notitle" },
35 pageexists = { "pageexists", "nopageexists" },
36 parlink = { "parlink", "noparlink" },
37 order = { { "id", "title", "created", "modified", "indexmenu", "custom" } },
38 rsort = { "rsort", "sort" },
39 depth = 0,
40 inline = true,
41 beforeeach = "",
42 aftereach = ""
43}
44
45local writers = {}
46
47local Buffer = {
48 __ctor = function(self)
49 self.buf = {}
50 end,
51
52 write_raw = function(self, ...)
53 for i, v in ipairs({ ... }) do
54 self.buf[#self.buf + 1] = v
55 end
56 return self
57 end,
58
59 finish = function(self)
60 self.result = table.concat(self.buf)
61 self.buf = {}
62 return self.result
63 end
64}
65
66local write_include = function(self, tp, name, flags)
67 local it_to_tp = {
68 [self.INCLUDE_PAGE] = "page",
69 [self.INCLUDE_SECTION] = "section",
70 [self.INCLUDE_NAMESPACE] = "namespace",
71 [self.INCLUDE_TAG] = "tagtopic"
72 }
73 if type(name) == "table" then
74 if name[#name] == true then
75 name[#name] = nil
76 name = ":" .. root_nspace .. ":"
77 .. table.concat(name, ":")
78 elseif name[#name] == false then
79 name[#name] = nil
80 name = ":" .. root_nspace .. "-include:"
81 .. table.concat(name, ":")
82 else
83 name = table.concat(name, ":")
84 end
85 end
86 self:write_raw("{{", it_to_tp[tp], ">", name);
87 if flags then
88 if tp == self.INCLUDE_SECTION and flags.section then
89 self:write_raw("#", flags.section)
90 end
91 flags.section = nil
92 local flstr = {}
93 for k, v in pairs(flags) do
94 local allow = allowed_incflags[k]
95 if allow ~= nil then
96 if type(allow) == "boolean" then
97 flstr[#flstr + 1] = k
98 elseif type(allow) == "number" or type(allow) == "string" then
99 if type(v) ~= type(allow) then
100 error("invalid value type for flag " .. k)
101 end
102 flstr[#flstr + 1] = k .. "=" .. v
103 elseif type(allow) == "table" then
104 if type(allow[1]) == "table" then
105 local valid = false
106 for i, vv in ipairs(allow[1]) do
107 if v == vv then
108 flstr[#flstr + 1] = k .. "=" .. v
109 valid = true
110 break
111 end
112 end
113 if not valid then
114 error("invalid value " .. v .. " for flag " .. k)
115 end
116 elseif type(allow[1]) == "string" and
117 type(allow[2]) == "string" then
118 if v then
119 flstr[#flstr + 1] = allow[1]
120 else
121 flstr[#flstr + 1] = allow[2]
122 end
123 end
124 end
125 else
126 error("invalid include flag: " .. tostring(k))
127 end
128 end
129 flstr = table.concat(flstr, "&")
130 if #flstr > 0 then
131 self:write_raw("&", flstr)
132 end
133 end
134 self:write_raw("}}")
135 self:write_nl()
136 return self
137end
138
139M.set_backend = function(bend)
140 M.Writer = assert(writers[bend], "invalid generation backend")
141 M.Buffer = M.Writer:clone(Buffer)
142end
143
144writers["dokuwiki"] = util.Object:clone {
145 INCLUDE_PAGE = 0,
146 INCLUDE_SECTION = 1,
147 INCLUDE_NAMESPACE = 2,
148 INCLUDE_TAG = 3,
149
150 __ctor = function(self, path, title)
151 local subs
152 if type(path) == "table" then
153 subs = dutil.path_join(unpack(path))
154 else
155 subs = dutil.nspace_to_path(path)
156 end
157 dutil.mkdir_p(subs)
158 self.file = assert(io.open(dutil.make_page(subs, "txt"), "w"))
159 if title then
160 if M.has_feature("title") then
161 self:write_raw("~~Title: ", title, "~~")
162 self:write_nl()
163 else
164 self:write_h(title, 1)
165 end
166 end
167 end,
168
169 write_raw = function(self, ...)
170 self.file:write(...)
171 return self
172 end,
173
174 write_nl = function(self, n)
175 self:write_raw(("\n"):rep(n or 1))
176 return self
177 end,
178
179 write_h = function(self, heading, level, nonl)
180 local s = ("="):rep(7 - level)
181 self:write_raw(s, " ", heading, " ", s, "\n")
182 if not nonl then
183 self:write_nl()
184 end
185 return self
186 end,
187
188 write_include = function(self, tp, name, flags)
189 return write_include(self, tp, name, flags)
190 end,
191
192 write_editable = function(self, ns, name)
193 ns[#ns + 1] = name
194 ns[#ns + 1] = false
195 self:write_include(self.INCLUDE_PAGE, ns, {
196 date = false, user = false, link = false
197 })
198 -- restore the table for later reuse
199 -- the false gets deleted by write_include
200 ns[#ns] = nil
201 end,
202
203 write_inherited = function(self, ns)
204 ns[#ns + 1] = true
205 self:write_include(self.INCLUDE_PAGE, ns, {
206 editbutton = false, date = false, user = false, link = false
207 })
208 end,
209
210 write_fmt = function(self, fmt1, fmt2, ...)
211 self:write_raw(fmt1, ...)
212 self:write_raw(fmt2)
213 return self
214 end,
215
216 write_b = function(self, ...)
217 self:write_fmt("**", "**", ...)
218 return self
219 end,
220
221 write_i = function(self, ...)
222 self:write_fmt("//", "//", ...)
223 return self
224 end,
225
226 write_u = function(self, ...)
227 self:write_fmt("__", "__", ...)
228 return self
229 end,
230
231 write_s = function(self, ...)
232 self:write_fmt("<del>", "</del>", ...)
233 return self
234 end,
235
236 write_m = function(self, ...)
237 self:write_fmt("''", "''", ...)
238 return self
239 end,
240
241 write_sub = function(self, ...)
242 self:write_fmt("<sub>", "</sub>", ...)
243 return self
244 end,
245
246 write_sup = function(self, ...)
247 self:write_fmt("<sup>", "</sup>", ...)
248 return self
249 end,
250
251 write_br = function(self, nl)
252 self:write_raw("\\\\", nl and "\n" or " ")
253 return self
254 end,
255
256 write_pre_inline = function(self, ...)
257 self:write_fmt("%%", "%%", ...)
258 return self
259 end,
260
261 write_pre = function(self, ...)
262 self:write_fmt("<nowiki>\n", "\n</nowiki>", ...)
263 return self
264 end,
265
266 write_code = function(self, str, lang)
267 lang = lang and (" " .. lang) or ""
268 self:write_raw("<code" .. lang .. ">\n", str, "\n</code>\n")
269 end,
270
271 write_link = function(self, target, title)
272 if type(target) == "table" then
273 if target[#target] == false then
274 target[#target] = nil
275 target = ":" .. root_nspace .. "-include:"
276 .. table.concat(target, ":")
277 else
278 target[#target] = nil
279 target = ":" .. root_nspace .. ":"
280 .. table.concat(target, ":")
281 end
282 end
283 if not title then
284 self:write_raw("[[", target:lower(), "|", target, "]]")
285 return
286 end
287 target = target:lower()
288 if type(title) == "string" then
289 self:write_raw("[[", target, "|", title, "]]")
290 return self
291 end
292 self:write_raw("[[", target, "|")
293 title(self)
294 self:write_raw("]]")
295 return self
296 end,
297
298 write_table = function(self, titles, tbl)
299 if titles then
300 self:write_raw("^ ", table.concat(titles, " ^ "), " ^\n")
301 end
302 for i, v in ipairs(tbl) do
303 self:write_raw("| ", table.concat(v, " | "), " |\n")
304 end
305 return self
306 end,
307
308 write_list = function(self, tbl, ord)
309 local prec = ord and "-" or "*"
310 for i, v in ipairs(tbl) do
311 local lvl, str = 1, v
312 if type(v) == "table" then
313 lvl, str = v[1] + 1, v[2]
314 end
315 local pbeg, pend = str:match("([^\n]+)\n(.+)")
316 if not pbeg then
317 pbeg = str
318 end
319 self:write_raw((" "):rep(lvl), prec, " ", str, "\n")
320 if pend then
321 self:write_raw(pend, "\n")
322 end
323 end
324 return self
325 end,
326
327 write_par = function(self, str)
328 local tokp = dtree.DocTokenizer(str)
329 local notetypes = M.has_feature("notes") and {
330 [tokp.MARK_NOTE] = "<note>\n",
331 [tokp.MARK_WARNING] = "<note warning>\n",
332 [tokp.MARK_REMARK] = "<note tip>\n",
333 [tokp.MARK_TODO] = "<note>\n**TODO:** "
334 } or {}
335 local hasraw, hasnote = false, false
336 while tokp:tokenize() do
337 local tp = tokp:type_get()
338 local tag = notetypes[tp]
339 if tag then
340 self:write_raw(tag)
341 hasnote = true
342 else
343 if not hasraw then
344 self:write_raw("%%")
345 hasraw = true
346 end
347 if tp == tokp.REF then
348 local reft = tokp:ref_resolve(true)
349 local str = tokp:text_get()
350 if str:sub(1, 1) == "[" then
351 str = str:sub(2, #str - 1)
352 end
353 self:write_raw("%%")
354 self:write_link(reft, str)
355 self:write_raw("%%")
356 else
357 local str = tokp:text_get()
358 assert(str, "internal tokenizer error")
359 -- replace possible %% chars
360 str = str:gsub("%%%%", "%%%%<nowiki>%%%%</nowiki>%%%%")
361 if tp == tokp.MARKUP_MONOSPACE then
362 self:write_raw("%%''" .. str .. "''%%")
363 else
364 self:write_raw(str)
365 end
366 end
367 end
368 end
369 self:write_raw("%%")
370 if hasnote then
371 self:write_raw("\n</note>")
372 end
373 return self
374 end,
375
376 write_folded = function(self, title, func)
377 if M.has_feature("folds") then
378 self:write_raw("++++ ", title, " |\n\n")
379 end
380 func(self)
381 if M.has_feature("folds") then
382 self:write_raw("\n\n++++")
383 end
384 return self
385 end,
386
387 finish = function(self)
388 self.file:close()
389 end
390}
391
392M.init = function(root_ns, ftrs)
393 root_nspace = root_ns
394 features = ftrs
395end
396
397return M
diff --git a/src/scripts/elua/apps/gendoc.lua b/src/scripts/elua/apps/gendoc.lua
deleted file mode 100644
index 36c47e2af3..0000000000
--- a/src/scripts/elua/apps/gendoc.lua
+++ /dev/null
@@ -1,1804 +0,0 @@
1local getopt = require("getopt")
2
3local serializer = require("serializer")
4
5local stats = require("docgen.stats")
6local dutil = require("docgen.util")
7local writer = require("docgen.writer")
8local keyref = require("docgen.keyref")
9local dtree = require("docgen.doctree")
10local mono = require("docgen.mono")
11
12local printgen = function() end
13
14local propt_to_type = {
15 [dtree.Function.PROPERTY] = "(get, set)",
16 [dtree.Function.PROP_GET] = "(get)",
17 [dtree.Function.PROP_SET] = "(set)",
18}
19
20local gen_cparam = function(par, out)
21 local part = par:type_get()
22 out = out or (par:direction_get() == par.OUT)
23 local tstr = part:c_type_get()
24 if out then
25 tstr = dtree.type_cstr_get(tstr, "*")
26 end
27 return dtree.type_cstr_get(tstr, par:name_get())
28end
29
30local get_func_csig_part = function(cn, tp)
31 if not tp then
32 return "void " .. cn
33 end
34 return dtree.type_cstr_get(tp, cn)
35end
36
37local gen_func_csig = function(f, ftype)
38 ftype = ftype or f.METHOD
39 assert(ftype ~= f.PROPERTY)
40
41 local cn = f:full_c_name_get(ftype)
42 local rtype = f:return_type_get(ftype)
43
44 local fparam = "Eo *obj"
45 if f:is_class() then
46 fparam = "Efl_Class *klass"
47 elseif f:is_const() or ftype == f.PROP_GET then
48 fparam = "const Eo *obj"
49 end
50
51 if f:type_get() == f.METHOD then
52 local pars = f:parameters_get()
53 local cnrt = get_func_csig_part(cn, rtype)
54 for i = 1, #pars do
55 pars[i] = gen_cparam(pars[i])
56 end
57 table.insert(pars, 1, fparam);
58 return cnrt .. "(" .. table.concat(pars, ", ") .. ");"
59 end
60
61 local keys = f:property_keys_get(ftype)
62 local vals = f:property_values_get(ftype)
63
64 if ftype == f.PROP_SET then
65 local cnrt = get_func_csig_part(cn, rtype)
66 local pars = {}
67 for i, par in ipairs(keys) do
68 pars[#pars + 1] = gen_cparam(par)
69 end
70 for i, par in ipairs(vals) do
71 pars[#pars + 1] = gen_cparam(par)
72 end
73 table.insert(pars, 1, fparam);
74 return cnrt .. "(" .. table.concat(pars, ", ") .. ");"
75 end
76
77 -- getters
78 local cnrt
79 if not rtype then
80 if #vals == 1 then
81 cnrt = get_func_csig_part(cn, vals[1]:type_get())
82 table.remove(vals, 1)
83 else
84 cnrt = get_func_csig_part(cn)
85 end
86 else
87 cnrt = get_func_csig_part(cn, rtype)
88 end
89 local pars = {}
90 for i, par in ipairs(keys) do
91 pars[#pars + 1] = gen_cparam(par)
92 end
93 for i, par in ipairs(vals) do
94 pars[#pars + 1] = gen_cparam(par, true)
95 end
96 table.insert(pars, 1, fparam);
97 return cnrt .. "(" .. table.concat(pars, ", ") .. ");"
98end
99
100local gen_func_namesig = function(fn, cl, buf, isprop, isget, isset)
101 if isprop then
102 buf[#buf + 1] = "@property "
103 end
104 buf[#buf + 1] = fn:name_get()
105 buf[#buf + 1] = " "
106 if fn:is_beta() then
107 buf[#buf + 1] = "@beta "
108 end
109 if not isprop then
110 if fn:scope_get(fn.METHOD) == fn.scope.PROTECTED then
111 buf[#buf + 1] = "@protected "
112 end
113 elseif isget and isset then
114 if fn:scope_get(fn.PROP_GET) == fn.scope.PROTECTED and
115 fn:scope_get(fn.PROP_SET) == fn.scope.PROTECTED then
116 buf[#buf + 1] = "@protected "
117 end
118 end
119 if fn:is_class() then
120 buf[#buf + 1] = "@class "
121 end
122 if fn:is_const() then
123 buf[#buf + 1] = "@const "
124 end
125end
126
127local gen_func_param = function(fp, buf, nodir)
128 -- TODO: default value
129 buf[#buf + 1] = " "
130 local dirs = {
131 [dtree.Parameter.IN] = "@in ",
132 [dtree.Parameter.OUT] = "@out ",
133 [dtree.Parameter.INOUT] = "@inout ",
134 }
135 if not nodir then buf[#buf + 1] = dirs[fp:direction_get()] end
136 buf[#buf + 1] = fp:name_get()
137 buf[#buf + 1] = ": "
138 buf[#buf + 1] = fp:type_get():serialize()
139 local dval = fp:default_value_get()
140 if dval then
141 buf[#buf + 1] = " ("
142 buf[#buf + 1] = dval:serialize()
143 buf[#buf + 1] = ")"
144 end
145 if fp:is_nonull() then
146 buf[#buf + 1] = " @nonull"
147 end
148 if fp:is_nullable() then
149 buf[#buf + 1] = " @nullable"
150 end
151 if fp:is_optional() then
152 buf[#buf + 1] = " @optional"
153 end
154 buf[#buf + 1] = ";\n"
155end
156
157local gen_func_return = function(fp, ftype, buf, indent)
158 local rett = fp:return_type_get(ftype)
159 if not rett then
160 return
161 end
162 buf[#buf + 1] = indent and (" "):rep(indent) or " "
163 buf[#buf + 1] = "return: "
164 buf[#buf + 1] = rett:serialize()
165 local dval = fp:return_default_value_get(ftype)
166 if dval then
167 buf[#buf + 1] = " ("
168 buf[#buf + 1] = dval:serialize()
169 buf[#buf + 1] = ")"
170 end
171 if fp:return_is_warn_unused(ftype) then
172 buf[#buf + 1] = " @warn_unused"
173 end
174 buf[#buf + 1] = ";\n"
175end
176
177local gen_method_sig = function(fn, cl)
178 local buf = {}
179 gen_func_namesig(fn, cl, buf, false, false, false)
180
181 local fimp = fn:implement_get()
182
183 if fimp:is_pure_virtual(fn.METHOD) then
184 buf[#buf + 1] = "@pure_virtual "
185 end
186 buf[#buf + 1] = "{"
187 local params = fn:parameters_get()
188 local rtp = fn:return_type_get(fn.METHOD)
189 if #params == 0 and not rtp then
190 buf[#buf + 1] = "}"
191 return table.concat(buf)
192 end
193 buf[#buf + 1] = "\n"
194 if #params > 0 then
195 buf[#buf + 1] = " params {\n"
196 for i, fp in ipairs(params) do
197 gen_func_param(fp, buf)
198 end
199 buf[#buf + 1] = " }\n"
200 end
201 gen_func_return(fn, fn.METHOD, buf)
202 buf[#buf + 1] = "}"
203 return table.concat(buf)
204end
205
206local eovals_check_same = function(a1, a2)
207 if #a1 ~= #a2 then return false end
208 for i, v in ipairs(a1) do
209 if v ~= a2[i] then return false end
210 end
211 return true
212end
213
214local gen_prop_keyvals = function(tbl, kword, buf, indent)
215 local ind = indent and (" "):rep(indent) or " "
216 if #tbl == 0 then return end
217 buf[#buf + 1] = " "
218 buf[#buf + 1] = ind
219 buf[#buf + 1] = kword
220 buf[#buf + 1] = " {\n"
221 for i, v in ipairs(tbl) do
222 buf[#buf + 1] = ind
223 gen_func_param(v, buf, true)
224 end
225 buf[#buf + 1] = " "
226 buf[#buf + 1] = ind
227 buf[#buf + 1] = "}\n"
228end
229
230local gen_prop_sig = function(fn, cl)
231 local buf = {}
232 local fnt = fn:type_get()
233 local isget = (fnt == fn.PROPERTY or fnt == fn.PROP_GET)
234 local isset = (fnt == fn.PROPERTY or fnt == fn.PROP_SET)
235 gen_func_namesig(fn, cl, buf, true, isget, isset)
236
237 local pimp = fn:implement_get()
238
239 local gvirt = pimp:is_pure_virtual(fn.PROP_GET)
240 local svirt = pimp:is_pure_virtual(fn.PROP_SET)
241
242 if (not isget or gvirt) and (not isset or svirt) then
243 buf[#buf + 1] = "@pure_virtual "
244 end
245
246 local gkeys = isget and fn:property_keys_get(fn.PROP_GET) or {}
247 local skeys = isset and fn:property_keys_get(fn.PROP_SET) or {}
248 local gvals = isget and fn:property_values_get(fn.PROP_GET) or {}
249 local svals = isget and fn:property_values_get(fn.PROP_SET) or {}
250 local grtt = isget and fn:return_type_get(fn.PROP_GET) or nil
251 local srtt = isset and fn:return_type_get(fn.PROP_SET) or nil
252
253 local keys_same = eovals_check_same(gkeys, skeys)
254 local vals_same = eovals_check_same(gvals, svals)
255
256 buf[#buf + 1] = "{\n"
257
258 if isget then
259 buf[#buf + 1] = " get "
260 if fn:scope_get(fn.PROP_GET) == fn.scope.PROTECTED and
261 fn:scope_get(fn.PROP_SET) ~= fn.scope.PROTECTED then
262 buf[#buf + 1] = "@protected "
263 end
264 buf[#buf + 1] = "{"
265 if (#gkeys == 0 or keys_same) and (#gvals == 0 or vals_same) and
266 (not grtt or grtt == srtt) then
267 buf[#buf + 1] = "}\n"
268 else
269 buf[#buf + 1] = "\n"
270 if not keys_same then gen_prop_keyvals(gkeys, "keys", buf) end
271 if not vals_same then gen_prop_keyvals(gvals, "values", buf) end
272 if grtt ~= srtt then
273 gen_func_return(fn, fn.PROP_GET, buf, 2)
274 end
275 buf[#buf + 1] = " }\n"
276 end
277 end
278
279 if isset then
280 buf[#buf + 1] = " set "
281 if fn:scope_get(fn.PROP_SET) == fn.scope.PROTECTED and
282 fn:scope_get(fn.PROP_GET) ~= fn.scope.PROTECTED then
283 buf[#buf + 1] = "@protected "
284 end
285 buf[#buf + 1] = "{"
286 if (#skeys == 0 or keys_same) and (#svals == 0 or vals_same) and
287 (not srtt or grtt == srtt) then
288 buf[#buf + 1] = "}\n"
289 else
290 buf[#buf + 1] = "\n"
291 if not keys_same then gen_prop_keyvals(skeys, "keys", buf) end
292 if not vals_same then gen_prop_keyvals(svals, "values", buf) end
293 if grtt ~= srtt then
294 gen_func_return(fn, fn.PROP_SET, buf, 2)
295 end
296 buf[#buf + 1] = " }\n"
297 end
298 end
299
300 if keys_same then gen_prop_keyvals(gkeys, "keys", buf, 0) end
301 if vals_same then gen_prop_keyvals(gvals, "values", buf, 0) end
302
303 buf[#buf + 1] = "}"
304 return table.concat(buf)
305end
306
307-- builders
308
309local nspaces_group = function(ns)
310 if #ns <= 2 then
311 return ns[1]
312 end
313
314 if ns[1] == "efl" and (ns[2] == "class" or ns[2] == "interface" or
315 ns[2] == "object" or ns[2] == "promise") then
316 return ns[1]
317 end
318
319 return ns[1] .. "." .. ns[2]
320end
321
322local nspaces_filter = function(items, ns)
323 local out = {}
324
325 for _, item in ipairs(items) do
326 local group = nspaces_group(item:nspaces_get())
327 if group == ns then out[#out + 1] = item end
328 end
329
330 return out
331end
332
333local build_method, build_property, build_event
334
335local build_reftable = function(f, title, ctype, t, iscl)
336 if not t or #t == 0 then
337 return
338 end
339
340 local nt = {}
341 for i, v in ipairs(t) do
342 nt[#nt + 1] = {
343 writer.Buffer():write_link(
344 iscl and v:nspaces_get(true)
345 or dtree.Node.nspaces_get(v, true),
346 v:name_get()
347 ):finish(),
348 v:doc_get():brief_get()
349 }
350 end
351 table.sort(nt, function(v1, v2) return v1[1] < v2[1] end)
352 f:write_table({ title, "Brief description" }, nt)
353end
354
355local build_ref_group = function(f, ns, classlist, aliases, structs, enums, consts, globals)
356 local classes = {}
357 local ifaces = {}
358 local mixins = {}
359
360 for i, cl in ipairs(classlist) do
361 local tp = cl:type_get()
362 if tp == dtree.Class.REGULAR or tp == dtree.Class.ABSTRACT then
363 classes[#classes + 1] = cl
364 elseif tp == dtree.Class.MIXIN then
365 mixins[#mixins + 1] = cl
366 elseif tp == dtree.Class.INTERFACE then
367 ifaces[#ifaces + 1] = cl
368 end
369 end
370
371 local title = ns:gsub("(%l)(%w*)", function(a,b) return a:upper()..b end) --string.sub(ns, 1, 1):upper() .. string.sub(ns, 2):lower()
372 f:write_h(title, 2)
373
374 build_reftable(f, "Classes", "class", classes, true)
375 build_reftable(f, "Interfaces", "interface", ifaces, true)
376 build_reftable(f, "Mixins", "mixin", mixins, true)
377
378 build_reftable(f, "Aliases", "alias", aliases)
379 build_reftable(f, "Structures", "struct", structs)
380 build_reftable(f, "Enums", "enum", enums)
381 build_reftable(f, "Constants", "constant", consts)
382 build_reftable(f, "Globals", "global", globals)
383
384 f:write_nl()
385end
386
387local build_ref = function()
388 local f = writer.Writer("start", "EFL Reference")
389 printgen("Generating reference...")
390
391 f:write_editable({ "reference" }, "general")
392 f:write_nl()
393
394 local classlist = dtree.Class.all_get()
395 local aliases = dtree.Typedecl.all_aliases_get()
396 local structs = dtree.Typedecl.all_structs_get()
397 local enums = dtree.Typedecl.all_enums_get()
398 local consts = dtree.Variable.all_constants_get()
399 local globals = dtree.Variable.all_globals_get()
400
401 grouped = {}
402 groups = {}
403 for i, cl in ipairs(classlist) do
404 local ns = cl:nspaces_get()
405 local name = nspaces_group(cl:nspaces_get())
406
407 local group = grouped[name]
408 if not group then
409 group = {}
410 grouped[name] = group
411 groups[#groups + 1] = name
412 end
413
414 group[#group + 1] = cl
415 end
416 table.sort(groups)
417
418 for _, ns in ipairs(groups) do
419 build_ref_group(f, ns, grouped[ns], nspaces_filter(aliases, ns), nspaces_filter(structs, ns),
420 nspaces_filter(enums, ns), nspaces_filter(consts, ns), nspaces_filter(globals, ns))
421 end
422
423 f:finish()
424end
425
426local build_inherits
427build_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 lbuf:write_link(cl:nspaces_get(true), cl:name_get())
433 lbuf:write_raw(" ")
434 lbuf:write_i("(" .. cl:type_str_get() .. ")")
435
436 t[#t + 1] = { lvl - 1, lbuf:finish() }
437 end
438
439 for i, acl in ipairs(cl:inherits_get()) do
440 build_inherits(acl, t, lvl + 1)
441 end
442 return t
443end
444
445local build_inherit_summary
446build_inherit_summary = function(cl, buf)
447 buf = buf or writer.Buffer()
448 buf:write_raw(" => ")
449
450 buf:write_link(cl:nspaces_get(true), cl:name_get())
451 buf:write_raw(" ")
452 buf:write_i("(" .. cl:type_str_get() .. ")")
453
454 local inherits = cl:inherits_get()
455 if #inherits ~= 0 then
456 build_inherit_summary(inherits[1], buf)
457 end
458 return buf
459end
460
461local default_theme_light = {
462 classes = {
463 regular = {
464 style = "filled",
465 color = "black",
466 fill_color = "white",
467 font_color = "black",
468 primary_color = "black",
469 primary_fill_color = "gray",
470 primary_font_color = "black"
471 },
472 abstract = {
473 style = "filled",
474 color = "black",
475 fill_color = "white",
476 font_color = "black",
477 primary_color = "black",
478 primary_fill_color = "gray",
479 primary_font_color = "black"
480 },
481 mixin = {
482 style = "filled",
483 color = "blue",
484 fill_color = "white",
485 font_color = "black",
486 primary_color = "blue",
487 primary_fill_color = "skyblue",
488 primary_font_color = "black"
489 },
490 interface = {
491 style = "filled",
492 color = "cornflowerblue",
493 fill_color = "white",
494 font_color = "black",
495 primary_color = "cornflowerblue",
496 primary_fill_color = "azure",
497 primary_font_color = "black"
498 }
499 },
500 node = {
501 shape = "box"
502 },
503 edge = {
504 color = "black"
505 },
506 bg_color = "transparent",
507 rank_dir = "TB",
508 size = "6"
509}
510
511local default_theme_dark = {
512 classes = {
513 regular = {
514 style = "filled",
515 color = "gray15",
516 fill_color = "gray15",
517 font_color = "white",
518 primary_color = "gray15",
519 primary_fill_color = "black",
520 primary_font_color = "white"
521 },
522 abstract = {
523 style = "filled",
524 color = "gray15",
525 fill_color = "gray15",
526 font_color = "white",
527 primary_color = "gray15",
528 primary_fill_color = "black",
529 primary_font_color = "white"
530 },
531 mixin = {
532 style = "filled",
533 color = "deepskyblue",
534 fill_color = "gray15",
535 font_color = "white",
536 primary_color = "deepskyblue",
537 primary_fill_color = "deepskyblue4",
538 primary_font_color = "white"
539 },
540 interface = {
541 style = "filled",
542 color = "cornflowerblue",
543 fill_color = "gray15",
544 font_color = "white",
545 primary_color = "cornflowerblue",
546 primary_fill_color = "dodgerblue4",
547 primary_font_color = "white"
548 }
549 },
550 node = {
551 shape = "box"
552 },
553 edge = {
554 color = "gray35"
555 },
556 bg_color = "transparent",
557 rank_dir = "TB",
558 size = "6"
559}
560
561local current_theme = default_theme_dark
562
563local validate_ctheme = function(tb, name)
564 if type(tb.classes[name]) ~= "table" then
565 return false
566 end
567 local t = tb.classes[name]
568 if type(t.style) ~= "string" then
569 return false
570 end
571 if type(t.color) ~= "string" then
572 return false
573 end
574 if type(t.fill_color) ~= "string" then
575 return false
576 end
577 if type(t.font_color) ~= "string" then
578 return false
579 end
580 if not t.primary_color then
581 t.primary_color = t.color
582 end
583 if not t.primary_fill_color then
584 t.primary_fill_color = t.fill_color
585 end
586 if not t.primary_font_color then
587 t.primary_font_color = t.font_color
588 end
589 if type(t.primary_color) ~= "string" then
590 return false
591 end
592 if type(t.primary_fill_color) ~= "string" then
593 return false
594 end
595 if type(t.primary_font_color) ~= "string" then
596 return false
597 end
598 return true
599end
600
601local validate_theme = function(tb)
602 if type(tb) ~= "table" then
603 return false
604 end
605 if type(tb.classes) ~= "table" then
606 return false
607 end
608 if not tb.node then
609 tb.node = current_theme.node
610 end
611 if not tb.edge then
612 tb.edge = current_theme.edge
613 end
614 if not tb.bg_color then
615 tb.bg_color = current_theme.bg_color
616 end
617 if not tb.rank_dir then
618 tb.rank_dir = current_theme.rank_dir
619 end
620 if not tb.size then
621 tb.size = current_theme.size
622 end
623 if type(tb.node) ~= "table" then
624 return false
625 end
626 if type(tb.edge) ~= "table" then
627 return false
628 end
629 if type(tb.bg_color) ~= "string" then
630 return false
631 end
632 if type(tb.rank_dir) ~= "string" then
633 return false
634 end
635 if type(tb.size) ~= "string" then
636 return false
637 end
638 if not validate_ctheme(tb, "regular") then
639 return false
640 end
641 if not validate_ctheme(tb, "abstract") then
642 return false
643 end
644 if not validate_ctheme(tb, "mixin") then
645 return false
646 end
647 if not validate_ctheme(tb, "interface") then
648 return false
649 end
650 return true
651end
652
653local set_theme = function(tname)
654 local tf = io.open(tname)
655 if tf then
656 local cont = tf:read("*all")
657 tf:close()
658 local tb, err = serializer.deserialize(cont)
659 if not tb then
660 error("error parsing theme '" .. tname .. "': " .. err)
661 end
662 if not validate_theme(tb) then
663 error("invalid theme '" .. tname .. "'")
664 end
665 current_theme = tb
666 else
667 error("theme '" .. tname .. "' does not exist")
668 end
669end
670
671local find_parent_impl
672find_parent_impl = function(fulln, cl)
673 for i, pcl in ipairs(cl:inherits_get()) do
674 for j, impl in ipairs(pcl:implements_get()) do
675 if impl:name_get() == fulln then
676 return impl, pcl
677 end
678 end
679 local pimpl, pcl = find_parent_impl(fulln, pcl)
680 if pimpl then
681 return pimpl, pcl
682 end
683 end
684 return nil, cl
685end
686
687local find_parent_briefdoc
688find_parent_briefdoc = function(fulln, cl)
689 local pimpl, pcl = find_parent_impl(fulln, cl)
690 if not pimpl then
691 return dtree.Doc():brief_get()
692 end
693 local pdoc = pimpl:doc_get(dtree.Function.METHOD, true)
694 local pdocf = pimpl:fallback_doc_get(true)
695 if not pdoc:exists() and (not pdocf or not pdocf:exists()) then
696 return find_parent_briefdoc(fulln, pcl)
697 end
698 return pdoc:brief_get(pdocf)
699end
700
701local build_functable = function(f, tcl, tbl)
702 if #tbl == 0 then
703 return
704 end
705 local nt = {}
706 for i, implt in ipairs(tbl) do
707 local lbuf = writer.Buffer()
708
709 local cl, impl = unpack(implt)
710 local func = impl:function_get()
711
712 local wt = {}
713 wt[0] = cl
714 wt[1] = func
715 wt[2] = impl
716
717 nt[#nt + 1] = wt
718 end
719
720 local get_best_scope = function(f)
721 local ft = f:type_get()
722 if ft == f.PROPERTY then
723 local fs1, fs2 = f:scope_get(f.PROP_GET), f:scope_get(f.PROP_SET)
724 if fs1 == f.scope.PUBLIC or fs2 == f.scope.PUBLIC then
725 return f.scope.PUBLIC
726 elseif fs1 == f.scope.PROTECTED or fs2 == f.scope.PROTECTED then
727 return f.scope.PROTECTED
728 else
729 return f.scope.PRIVATE
730 end
731 else
732 return f:scope_get(ft)
733 end
734 end
735 table.sort(nt, function(v1, v2)
736 local cl1, cl2 = v1[0], v2[0]
737 if cl1 ~= cl2 then
738 return cl1:name_get() < cl2:name_get()
739 end
740
741 local f1, f2 = v1[1], v2[1]
742 local f1s, f2s = get_best_scope(f1), get_best_scope(f2)
743 if f1s ~= f2s then
744 if f1s ~= f1.scope.PROTECED then
745 -- public funcs go first, private funcs go last
746 return f1s == f1.scope.PUBLIC
747 else
748 -- protected funcs go second
749 return f2s == f2.scope.PRIVATE
750 end
751 end
752 return f1:name_get() < f2:name_get()
753 end)
754
755 return nt
756end
757
758local write_description = function(f, impl, func, cl)
759 local over = impl:is_overridden(cl)
760 local bdoc
761
762 local doc = impl:doc_get(func.METHOD, true)
763 local docf = impl:fallback_doc_get(true)
764 if over and (not doc:exists() and (not docf or not docf:exists())) then
765 bdoc = find_parent_briefdoc(impl:name_get(), cl)
766 else
767 bdoc = doc:brief_get(docf)
768 end
769 if bdoc ~= "No description supplied." then
770 f:write_raw(bdoc)
771 end
772end
773
774local write_function = function(f, func, cl)
775 local llbuf = writer.Buffer()
776 llbuf:write_link(func:nspaces_get(cl, true), func:name_get())
777 f:write_b(llbuf:finish())
778
779 local pt = propt_to_type[func:type_get()]
780 if pt then
781 f:write_raw(" ")
782 local llbuf = writer.Buffer()
783 llbuf:write_b(pt)
784 f:write_i(llbuf:finish())
785 end
786end
787
788local write_scope = function(f, func)
789 local ftt = {
790 [func.scope.PROTECTED] = "protected",
791 [func.scope.PRIVATE] = "private"
792 }
793 if func:is_class() then
794 f:write_raw(" ")
795 f:write_m("class")
796 end
797 if func:type_get() == func.PROPERTY then
798 local ft1, ft2 = ftt[func:scope_get(func.PROP_GET)],
799 ftt[func:scope_get(func.PROP_SET)]
800 if ft1 and ft1 == ft2 then
801 f:write_raw(" ")
802 f:write_m(ft1)
803 elseif ft1 or ft2 then
804 local s = ""
805 if ft1 then
806 s = s .. ft1 .. " get" .. (ft2 and ", " or "")
807 end
808 if ft2 then
809 s = s .. ft2 .. " set"
810 end
811 f:write_raw(" ")
812 f:write_m(s)
813 end
814 else
815 local ft = ftt[func:scope_get(func:type_get())]
816 if ft then
817 f:write_raw(" ")
818 f:write_m(ft)
819 end
820 end
821end
822
823local write_functable = function(f, tcl, tbl)
824 if #tbl == 0 then
825 return
826 end
827 local nt = build_functable(t, tcl, tbl)
828
829 local wrote = false
830 for i, wt in ipairs(nt) do
831 local cl = wt[0]
832 local func = wt[1]
833 local impl = wt[2]
834
835 local ocl = impl:class_get()
836 local func = impl:function_get()
837 local over = impl:is_overridden(cl)
838
839 -- function
840 write_function(f, func, cl)
841 -- scope
842 write_scope(f, func)
843
844 -- overrides
845 if over then
846 -- TODO: possibly also mention which part of a property was
847 -- overridden and where, get/set override point might differ!
848 -- but we get latest doc every time so it's ok for now
849 local llbuf = writer.Buffer()
850 llbuf:write_raw(" [Overridden from ")
851 llbuf:write_link(ocl:nspaces_get(true), ocl:name_get())
852 llbuf:write_raw("]")
853 f:write_i(llbuf:finish())
854 end
855
856 -- description
857 f:write_br(true)
858 f:write_raw("> ")
859 write_description(f, impl, func, cl)
860
861 -- code snippets
862 f:write_nl()
863 local codes = {}
864 if func:type_get() ~= dtree.Function.PROPERTY then
865 codes[#codes + 1] = gen_func_csig(func, func:type_get())
866 else
867 codes[#codes + 1] = gen_func_csig(func, dtree.Function.PROP_GET)
868 codes[#codes + 1] = gen_func_csig(func, dtree.Function.PROP_SET)
869 end
870 f:write_code(table.concat(codes, "\n"), "c")
871 f:write_br(true)
872
873 if cl == tcl then
874 if impl:is_prop_get() or impl:is_prop_set() then
875 build_property(impl, cl)
876 else
877 build_method(impl, cl)
878 end
879 end
880 end
881 f:write_nl()
882end
883
884local write_inherit_functable = function(f, tcl, tbl)
885 if #tbl == 0 then
886 return
887 end
888 local nt = build_functable(t, tcl, tbl)
889
890 local prevcl = tcl
891 for i, wt in ipairs(nt) do
892 local cl = wt[0]
893 local func = wt[1]
894 local impl = wt[2]
895
896 local ocl = impl:class_get()
897 local func = impl:function_get()
898
899 -- class grouping for inheritance
900 if cl ~= prevcl then
901 prevcl = cl
902 f:write_raw("^ ")
903 f:write_link(cl:nspaces_get(true), cl:name_get())
904 f:write_raw(" ^^^")
905 f:write_nl()
906 end
907
908 -- scope
909 f:write_raw("| ")
910 write_scope(f, func)
911 f:write_raw(" | ")