diff options
author | Daniel Kolesa <d.kolesa@samsung.com> | 2019-05-21 15:43:02 +0200 |
---|---|---|
committer | Daniel Kolesa <d.kolesa@samsung.com> | 2019-05-21 15:44:30 +0200 |
commit | 34ef9c313989402d523951b2c20c7141d3bdce78 (patch) | |
tree | 04f2a7b1d285ad6f008791784dd89c3e6532ca7c /src/scripts | |
parent | b5a7ee2ae4466e87d0e3a62aa7885ecda9e30aea (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/scripts')
-rw-r--r-- | src/scripts/elua/apps/README-docgen.md | 9 | ||||
-rw-r--r-- | src/scripts/elua/apps/docgen/doctree.lua | 1427 | ||||
-rw-r--r-- | src/scripts/elua/apps/docgen/keyref.lua | 41 | ||||
-rw-r--r-- | src/scripts/elua/apps/docgen/mono.lua | 614 | ||||
-rw-r--r-- | src/scripts/elua/apps/docgen/stats.lua | 274 | ||||
-rw-r--r-- | src/scripts/elua/apps/docgen/util.lua | 50 | ||||
-rw-r--r-- | src/scripts/elua/apps/docgen/writer.lua | 397 | ||||
-rw-r--r-- | src/scripts/elua/apps/gendoc.lua | 1804 | ||||
-rwxr-xr-x | src/scripts/elua/apps/gendoc.sh | 38 |
9 files changed, 0 insertions, 4654 deletions
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 | |||
3 | This is the upcoming documentation generator for EFL. It takes documentation | ||
4 | described in Eo files and turns it into a DokuWiki structure (with possibility | ||
5 | of adapting it to other systems later on). | ||
6 | |||
7 | Use the supplied build.sh script to generate. By default, it assumes that a | ||
8 | directory called "dokuwiki" is present in the current directory, so symlink | ||
9 | your 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 @@ | |||
1 | local util = require("util") | ||
2 | |||
3 | local eolian = require("eolian") | ||
4 | |||
5 | local keyref = require("docgen.keyref") | ||
6 | local dutil = require("docgen.util") | ||
7 | |||
8 | -- writer has to be loaded late to prevent cycles | ||
9 | local writer | ||
10 | |||
11 | local M = {} | ||
12 | local eos = eolian:new() | ||
13 | |||
14 | local 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 | ||
22 | end | ||
23 | |||
24 | local 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 | ||
31 | end | ||
32 | |||
33 | M.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 | } | ||
75 | local Node = M.Node | ||
76 | |||
77 | local 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") | ||
89 | end | ||
90 | |||
91 | local 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() | ||
107 | end | ||
108 | |||
109 | M.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 | |||
185 | local revh = {} | ||
186 | |||
187 | local 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 | |||
194 | M.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 | |||
346 | local 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 | |||
353 | local ffi = require("ffi") | ||
354 | |||
355 | M.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 | |||
479 | M.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 | |||
536 | M.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 | |||
580 | M.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 | |||
594 | M.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 | |||
612 | local 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 | ||
628 | end | ||
629 | |||
630 | M.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 | |||
728 | M.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 | ||
739 | end | ||
740 | |||
741 | local 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 | ||
751 | end | ||
752 | |||
753 | M.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 | |||
1086 | M.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 | |||
1248 | M.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 | |||
1262 | M.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 | |||
1324 | M.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 | |||
1388 | M.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 | ||
1398 | end | ||
1399 | |||
1400 | M.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 | ||
1425 | end | ||
1426 | |||
1427 | return 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 @@ | |||
1 | local M = {} | ||
2 | |||
3 | local key_refs = {} | ||
4 | |||
5 | M.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 | ||
12 | end | ||
13 | |||
14 | M.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 | ||
39 | end | ||
40 | |||
41 | return 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 | |||
2 | local writer = require("docgen.writer") | ||
3 | local dtree = require("docgen.doctree") | ||
4 | |||
5 | local M = {} | ||
6 | |||
7 | local propt_to_type = { | ||
8 | [dtree.Function.PROPERTY] = "(get, set)", | ||
9 | [dtree.Function.PROP_GET] = "(get)", | ||
10 | [dtree.Function.PROP_SET] = "(set)", | ||
11 | } | ||
12 | |||
13 | local 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 | |||
57 | local 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 | |||
88 | local 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, '.') | ||
98 | end | ||
99 | |||
100 | local get_mono_type | ||
101 | get_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 | ||
130 | end | ||
131 | |||
132 | |||
133 | local 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 | ||
140 | end | ||
141 | |||
142 | local 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) | ||
168 | end | ||
169 | |||
170 | local 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()) | ||
182 | end | ||
183 | |||
184 | local get_func_mono_sig_part = function(cn, tp) | ||
185 | return get_mono_type(tp) .. " " .. cn | ||
186 | end | ||
187 | |||
188 | local find_parent_impl | ||
189 | find_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 | ||
203 | end | ||
204 | |||
205 | local find_parent_briefdoc | ||
206 | find_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) | ||
217 | end | ||
218 | |||
219 | |||
220 | local 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 | ||
234 | end | ||
235 | |||
236 | local 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 | ||
269 | end | ||
270 | |||
271 | local 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 | ||
283 | end | ||
284 | |||
285 | local 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, ", ") .. ");" | ||
346 | end | ||
347 | |||
348 | local 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 | ||
403 | end | ||
404 | |||
405 | local find_callables | ||
406 | find_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 | ||
425 | end | ||
426 | |||
427 | M.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 | ||
449 | end | ||
450 | |||
451 | M.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 | ||
469 | end | ||
470 | |||
471 | M.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() | ||
508 | end | ||
509 | |||
510 | M.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() | ||
561 | end | ||
562 | |||
563 | M.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() | ||
610 | end | ||
611 | |||
612 | return 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 @@ | |||
1 | local is_verbose = false | ||
2 | |||
3 | local M = {} | ||
4 | |||
5 | local stats = {} | ||
6 | |||
7 | local 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 | ||
17 | end | ||
18 | |||
19 | local fcol = 30 | ||
20 | local ncol = 0 | ||
21 | |||
22 | local get_percent = function(sv, svu) | ||
23 | return (sv == 0) and 100 or math.floor(((sv - svu) / sv) * 100 + 0.5) | ||
24 | end | ||
25 | |||
26 | local 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)) | ||
35 | end | ||
36 | |||
37 | local 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) | ||
44 | end | ||
45 | |||
46 | M.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))) | ||
97 | end | ||
98 | |||
99 | local 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 | ||
107 | end | ||
108 | |||
109 | local print_missing = function(name, tp) | ||
110 | if not is_verbose then | ||
111 | return | ||
112 | end | ||
113 | print(tp .. " '" .. name .. "'" .. " missing documentation") | ||
114 | end | ||
115 | |||
116 | M.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 | ||
136 | end | ||
137 | |||
138 | M.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 | ||
162 | end | ||
163 | |||
164 | M.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 | ||
207 | end | ||
208 | |||
209 | M.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 | ||
216 | end | ||
217 | |||
218 | M.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 | ||
233 | end | ||
234 | |||
235 | M.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 | ||
250 | end | ||
251 | |||
252 | M.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 | ||
259 | end | ||
260 | |||
261 | M.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 | ||
268 | end | ||
269 | |||
270 | M.init = function(verbose) | ||
271 | is_verbose = verbose | ||
272 | end | ||
273 | |||
274 | return 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 @@ | |||
1 | local cutil = require("cutil") | ||
2 | local ffi = require("ffi") | ||
3 | |||
4 | local M = {} | ||
5 | |||
6 | local doc_root, root_ns | ||
7 | |||
8 | local path_sep, rep_sep = "/", "\\" | ||
9 | if ffi.os == "Windows" then | ||
10 | path_sep, rep_sep = rep_sep, path_sep | ||
11 | end | ||
12 | |||
13 | M.path_join = function(...) | ||
14 | return (table.concat({ ... }, path_sep):gsub(rep_sep, path_sep)) | ||
15 | end | ||
16 | |||
17 | M.path_to_nspace = function(p) | ||
18 | return p:gsub(rep_sep, ":"):gsub(path_sep, ":"):lower() | ||
19 | end | ||
20 | |||
21 | M.nspace_to_path = function(ns) | ||
22 | return ns:gsub(":", path_sep):gsub(rep_sep, path_sep):lower() | ||
23 | end | ||
24 | |||
25 | M.make_page = function(path, ext) | ||
26 | return M.path_join(doc_root, path .. "." .. ext) | ||
27 | end | ||
28 | |||
29 | M.get_root_ns = function() | ||
30 | return root_ns | ||
31 | end | ||
32 | |||
33 | M.mkdir_r = function(dirn) | ||
34 | assert(cutil.file_mkpath(M.path_join(doc_root, dirn))) | ||
35 | end | ||
36 | |||
37 | M.mkdir_p = function(path) | ||
38 | M.mkdir_r(path:match("(.+)" .. path_sep .. "([^" .. path_sep .. "]+)")) | ||
39 | end | ||
40 | |||
41 | M.rm_root = function() | ||
42 | cutil.file_rmrf(doc_root) | ||
43 | end | ||
44 | |||
45 | M.init = function(root, rns) | ||
46 | doc_root = root:gsub(rep_sep, path_sep) | ||
47 | root_ns = rns | ||
48 | end | ||
49 | |||
50 | return 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 @@ | |||
1 | local util = require("util") | ||
2 | |||
3 | local dutil = require("docgen.util") | ||
4 | local dtree = require("docgen.doctree") | ||
5 | |||
6 | local M = {} | ||
7 | |||
8 | local root_nspace, features | ||
9 | |||
10 | M.has_feature = function(fname) | ||
11 | if not features then | ||
12 | return false | ||
13 | end | ||
14 | return not not features[fname] | ||
15 | end | ||
16 | |||
17 | local 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 | |||
45 | local writers = {} | ||
46 | |||
47 | local 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 | |||
66 | local 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 | ||
137 | end | ||
138 | |||
139 | M.set_backend = function(bend) | ||
140 | M.Writer = assert(writers[bend], "invalid generation backend") | ||
141 | M.Buffer = M.Writer:clone(Buffer) | ||
142 | end | ||
143 | |||
144 | writers["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 | |||
392 | M.init = function(root_ns, ftrs) | ||
393 | root_nspace = root_ns | ||
394 | features = ftrs | ||
395 | end | ||
396 | |||
397 | return 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 @@ | |||
1 | local getopt = require("getopt") | ||
2 | |||
3 | local serializer = require("serializer") | ||
4 | |||
5 | local stats = require("docgen.stats") | ||
6 | local dutil = require("docgen.util") | ||
7 | local writer = require("docgen.writer") | ||
8 | local keyref = require("docgen.keyref") | ||
9 | local dtree = require("docgen.doctree") | ||
10 | local mono = require("docgen.mono") | ||
11 | |||
12 | local printgen = function() end | ||
13 | |||
14 | local propt_to_type = { | ||
15 | [dtree.Function.PROPERTY] = "(get, set)", | ||
16 | [dtree.Function.PROP_GET] = "(get)", | ||
17 | [dtree.Function.PROP_SET] = "(set)", | ||
18 | } | ||
19 | |||
20 | local 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()) | ||
28 | end | ||
29 | |||
30 | local 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) | ||
35 | end | ||
36 | |||
37 | local 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, ", ") .. ");" | ||
98 | end | ||
99 | |||
100 | local 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 | ||
125 | end | ||
126 | |||
127 | local 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" | ||
155 | end | ||
156 | |||
157 | local 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" | ||
175 | end | ||
176 | |||
177 | local 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) | ||
204 | end | ||
205 | |||
206 | local 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 | ||
212 | end | ||
213 | |||
214 | local 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" | ||
228 | end | ||
229 | |||
230 | local 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) | ||
305 | end | ||
306 | |||
307 | -- builders | ||
308 | |||
309 | local 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] | ||
320 | end | ||
321 | |||
322 | local 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 | ||
331 | end | ||
332 | |||
333 | local build_method, build_property, build_event | ||
334 | |||
335 | local 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) | ||
353 | end | ||
354 | |||
355 | local 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() | ||
385 | end | ||
386 | |||
387 | local 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() | ||
424 | end | ||
425 | |||
426 | local build_inherits | ||
427 | 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 | 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 | ||
443 | end | ||
444 | |||
445 | local build_inherit_summary | ||
446 | build_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 | ||
459 | end | ||
460 | |||
461 | local 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 | |||
511 | local 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 | |||
561 | local current_theme = default_theme_dark | ||
562 | |||
563 | local 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 | ||
599 | end | ||
600 | |||
601 | local 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 | ||
651 | end | ||
652 | |||
653 | local 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 | ||
669 | end | ||
670 | |||
671 | local find_parent_impl | ||
672 | find_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 | ||
685 | end | ||
686 | |||
687 | local find_parent_briefdoc | ||
688 | find_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) | ||
699 | end | ||
700 | |||
701 | local 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 | ||
756 | end | ||
757 | |||
758 | local 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 | ||
772 | end | ||
773 | |||
774 | local 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 | ||
786 | end | ||
787 | |||
788 | local 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 | ||
821 | end | ||
822 | |||
823 | local 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() | ||
882 | end | ||
883 | |||
884 | local 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(" | ") | ||
912 | -- function | ||
913 | write_function(f, func, cl) | ||
914 | f:write_raw(" | ") | ||
915 | -- description | ||
916 | write_description(f, impl, func, cl) | ||
917 | f:write_raw(" |") | ||
918 | f:write_nl() | ||
919 | end | ||
920 | f:write_nl() | ||
921 | end | ||
922 | |||
923 | -- finds all stuff that is callable on a class, respecting | ||
924 | -- overrides and not duplicating, does a depth-first search | ||
925 | local find_callables | ||
926 | find_callables = function(cl, omeths, events, written) | ||
927 | for i, pcl in ipairs(cl:inherits_get()) do | ||
928 | for j, impl in ipairs(pcl:implements_get()) do | ||
929 | local func = impl:function_get() | ||
930 | local fid = func:id_get() | ||
931 | if not written[fid] then | ||
932 | omeths[#omeths + 1] = { pcl, impl } | ||
933 | written[fid] = true | ||
934 | end | ||
935 | end | ||
936 | for i, ev in ipairs(pcl:events_get()) do | ||
937 | local evid = ev:name_get() | ||
938 | if not written[evid] then | ||
939 | events[#events + 1] = { pcl, ev } | ||
940 | written[evid] = true | ||
941 | end | ||
942 | end | ||
943 | find_callables(pcl, omeths, events, written) | ||
944 | end | ||
945 | end | ||
946 | |||
947 | local build_evcsig = function(ev) | ||
948 | local csbuf = { ev:c_name_get(), "(" } | ||
949 | csbuf[#csbuf + 1] = dtree.type_cstr_get(ev:type_get()) |