1 # $Id: module.rb,v 1.31 2012/04/17 02:49:40 machan Exp $
2
3 require 'tmdoc/tmstd'
4 require 'tmdoc/tmstd/docbook'
5 require 'tmdoc/constant'
6 require 'tmdoc/model/document'
7 require 'tmdoc/model/docbook'
8 require 'tmdoc/transformer/document-into-docbook/module-infobox'
9 require 'tmdoc/transformer/document-into-docbook/node'
10 require 'tmdoc/transformer/document-into-docbook/link'
11 require 'tmdoc/transformer/localizable-string'
12
13
14 module TmDoc
15
16 module Transformer::DocumentIntoDocBook
17
18 module Module
19
20 module_function
21
22 def transform_modules(md_modules, title, id, show_code)
23 ASSERT.kind_of md_modules, MDM::SeqOfModule
24 ASSERT.kind_of title, String
25 ASSERT.kind_of id, String
26 ASSERT.boolean show_code
27
28 return nil if md_modules.empty?
29
30 mb_documents = MBD::SeqOfDocument.new(
31 md_modules.map { |md_module|
32 ASSERT.kind_of md_module, MDM::Module
33
34 LOG::Progress.log("\t\t%s", md_module.path.to_s)
35
36 transform md_module, show_code
37 }.compact
38 )
39 return nil if mb_documents.empty?
40
41 MBD::Node.new(
42 id,
43
44 DBOOK.chapter(:id => id) {
45 [
46 DBOOK.chapter_info {
47 [ DBOOK.title(title) ]
48 }
49 ] + mb_documents.map { |mb_document|
50 ASSERT.kind_of mb_document, MBD::Leaf
51
52 DBOOK.include(mb_document.name, OUTPUT_FILE_SUFFIX)
53 }
54 },
55
56 mb_documents
57 )
58 end
59
60
61 def transform(md_module, show_code)
62 ASSERT.kind_of md_module, MDM::Module
63 ASSERT.boolean show_code
64
65 name = md_module.name
66 display_name = transform_display_name md_module, name
67 id = Id.transform_module md_module.above_path, name
68
69 md_link = md_module.a_link_to_above_module
70 title = format(
71 "%s: %s",
72 if md_module.kind_of?(MDM::Class)
73 TLS::DIV_CLASS
74 else
75 TLS::DIV_MODULE
76 end,
77
78 if md_link
79 format(
80 "%s (%s)",
81 display_name,
82 Link.display_name_of_module(
83 md_link,
84 (md_link.above_path << md_link.name).join('::')
85 )
86 )
87 else
88 display_name
89 end
90 )
91
92 contents = [
93 Module::InfoBox.transform(
94 md_module.a_infobox, id, false, show_code
95 ),
96
97 transform_overview(id, md_module, show_code),
98
99 if md_module.property_sections
100 md_module.property_sections.map { |property_section|
101 transform_property_section(
102 property_section.tag,
103 property_section.properties,
104 id, title, display_name, show_code
105 )
106 }
107 else
108 nil
109 end
110 ].flatten.compact
111 return nil if contents.empty?
112
113 mb_section_info = transform_section_info(
114 title,
115
116 display_name,
117
118 if md_module.kind_of?(MDM::Class)
119 TLS::CLASS
120 else
121 TLS::MODULE
122 end
123 )
124 MBD::Leaf.new(
125 id,
126
127 DBOOK.section(:id => id) {
128 [ mb_section_info ] + contents
129 }
130 )
131 end
132
133
134 def transform_overview(module_id, md_module, show_code)
135 ASSERT.kind_of module_id, String
136 ASSERT.kind_of md_module, MDM::Module
137 ASSERT.boolean show_code
138
139 contents = [
140 if md_module.a_module_structure
141 Node.transform_logical_structure(
142 md_module.a_module_structure,
143 TLS::DIV_M_STRUCTURE,
144 Id.transform_module_section(
145 module_id, Id::DIV_NAME_OF_M_STRUCTURE
146 ),
147 Id::DIV_NAME_OF_M_STRUCTURE,
148 :show_type_label => true,
149 :show_code => show_code
150 )
151 else
152 nil
153 end,
154
155 if md_module.a_class_hierarchy
156 Node.transform_logical_structure(
157 md_module.a_class_hierarchy,
158 TLS::DIV_C_HIERARCHY,
159 Id.transform_module_section(
160 module_id, Id::DIV_NAME_OF_C_HIERARCHY
161 ),
162 Id::DIV_NAME_OF_C_HIERARCHY,
163 :show_above_link => true,
164 :show_code => show_code
165 )
166 else
167 nil
168 end
169 ].compact
170 return nil if contents.empty?
171
172 DBOOK.section {
173 [
174 DBOOK.section_info {
175 [ DBOOK.title(TLS::DIV_OVERVIEW) ]
176 }
177 ] + contents
178 }
179 end
180
181
182 def transform_property_section(
183 tag, md_properties,
184 module_id, module_title, module_display_name, show_code
185 )
186 ASSERT.kind_of md_properties, MDA::Module::SeqOfProperty
187 ASSERT.kind_of module_id, String
188 ASSERT.kind_of module_title, String
189 ASSERT.kind_of module_display_name, String
190 ASSERT.boolean show_code
191
192 title = TLS::HASH_OF_TAG_TO_TITLE[tag]
193 ASSERT.kind_of(title, String,
194 "Unknown tag: <%s> in module: <%s>", tag, module_title
195 )
196
197 mb_contents = md_properties.map { |md_property|
198 ASSERT.kind_of md_property, MDA::Module::Property
199
200 case md_property
201 when MDM::Constant
202 transform_constant(
203 md_property, module_id,
204 module_title, module_display_name,
205 show_code
206 )
207 when MDM::Alias
208 transform_alias(
209 md_property, module_id,
210 module_title, module_display_name,
211 show_code, tag
212 )
213 when MDM::Attribute
214 transform_attribute(
215 md_property, module_id,
216 module_title, module_display_name,
217 show_code, tag
218 )
219 when MDM::Method
220 transform_method(
221 md_property, module_id,
222 module_title, module_display_name,
223 show_code, tag
224 )
225 else
226 ASSERT.abort(
227 "Unknown md_property: %s", md_property.to_s
228 )
229 end
230 }
231
232 DBOOK.section {
233 [
234 DBOOK.section_info {
235 [ DBOOK.title(title) ]
236 }
237 ] + mb_contents
238 }
239 end
240
241
242 def transform_constant(
243 md_constant, module_id, module_title, module_display_name, show_code
244 )
245 ASSERT.kind_of md_constant, MDM::Constant
246 ASSERT.kind_of module_id, String
247 ASSERT.kind_of module_display_name, String
248 ASSERT.boolean show_code
249
250 name = md_constant.name
251 uniq_num = transform_uniq_num(
252 md_constant.uniq_num, md_constant.max_uniq_num
253 )
254 title = format("%s::%s%s",
255 module_display_name,
256 name,
257 if uniq_num then format(" %s", uniq_num) else '' end
258 )
259
260 mb_synopsys = DBOOKEX.informal_table('lll', :frame => 'none') {
261 [
262 DBOOK.row {
263 [
264 DBOOK.entry {
265 [
266 DBOOK.constant(name),
267 DBOOK.text('='),
268 DBOOK.literal(md_constant.value)
269 ]
270 }
271 ]
272 }
273 ]
274 }
275
276 id = Id.transform_property module_id, name, md_constant.uniq_num
277 DBOOK.section(:id => id) {
278 [
279 transform_section_info(
280 title, name, TLS::CONSTANT, module_title
281 ),
282
283 transform_location(md_constant, show_code),
284
285 mb_synopsys
286 ]
287 }
288 end
289
290
291 def transform_alias(
292 md_alias, module_id,
293 module_title, module_display_name,
294 show_code, tag
295 )
296 ASSERT.kind_of md_alias, MDM::Alias
297 ASSERT.kind_of module_id, String
298 ASSERT.kind_of module_title, String
299 ASSERT.kind_of module_display_name, String
300 ASSERT.boolean show_code
301 ASSERT.kind_of tag, Symbol
302
303 name = md_alias.name
304 uniq_num = transform_uniq_num(
305 md_alias.uniq_num, md_alias.max_uniq_num
306 )
307
308 pair = {
309 :module_alias => [ "%s.%s%s", TLS::MODULE_ALIAS ],
310 :class_alias => [ "%s.%s%s", TLS::CLASS_ALIAS ],
311 :instance_alias => [ "%s#%s%s", TLS::INSTANCE_ALIAS ]
312 }[tag]
313 ASSERT.tuple_of(pair, [String, String],
314 "Unknown alias tag: %s", tag
315 )
316 title_format, alias_type = pair
317
318 title = format(title_format,
319 module_display_name,
320 name,
321 if uniq_num then format(" %s", uniq_num) else '' end
322 )
323
324 mb_synopsys = DBOOKEX.informal_table('lll', :frame => 'none') {
325 [
326 DBOOK.row {
327 [
328 DBOOK.entry {
329 [
330 DBOOK.var_name(name),
331 DBOOK.raw_text('⇐'),
332 DBOOK.literal(md_alias.orig_name)
333 ]
334 }
335 ]
336 }
337 ]
338 }
339
340 id = Id.transform_property module_id, name, md_alias.uniq_num
341 DBOOK.section(:id => id) {
342 [
343 transform_section_info(
344 title, name, alias_type, module_title
345 ),
346
347 transform_location(md_alias, show_code),
348
349 mb_synopsys
350 ]
351 }
352 end
353
354
355 def transform_attribute(
356 md_attribute, module_id,
357 module_title, module_display_name,
358 show_code, tag
359 )
360 ASSERT.kind_of md_attribute, MDM::Attribute
361 ASSERT.kind_of module_id, String
362 ASSERT.kind_of module_title, String
363 ASSERT.kind_of module_display_name, String
364 ASSERT.boolean show_code
365 ASSERT.kind_of tag, Symbol
366
367 name = md_attribute.name
368 uniq_num = transform_uniq_num(
369 md_attribute.uniq_num, md_attribute.max_uniq_num
370 )
371
372 pair = {
373 :module_attribute => [
374 "%s.%s [%s]%s", TLS::MODULE_ATTRIBUTE
375 ],
376 :class_attribute => [
377 "%s.%s [%s]%s", TLS::CLASS_ATTRIBUTE
378 ],
379 :instance_attribute => [
380 "%s#%s [%s]%s", TLS::INSTANCE_ATTRIBUTE
381 ]
382 }[tag]
383 ASSERT.tuple_of(pair, [String, String],
384 "Unknown attribute tag: %s", tag
385 )
386 title_format, attribute_type = pair
387
388 title = format(title_format,
389 module_display_name,
390 name,
391 md_attribute.accessor,
392 if uniq_num then format(" %s", uniq_num) else '' end
393 )
394
395 id = Id.transform_property module_id, name, md_attribute.uniq_num
396 DBOOK.section(:id => id) {
397 [
398 transform_section_info(
399 title, name, attribute_type, module_title
400 ),
401
402 transform_location(md_attribute, show_code),
403 ]
404 }
405 end
406
407
408 def transform_method(
409 md_method, module_id,
410 module_title, module_display_name,
411 show_code, tag
412 )
413 ASSERT.kind_of md_method, MDM::Method
414 ASSERT.kind_of module_id, String
415 ASSERT.kind_of module_title, String
416 ASSERT.kind_of module_display_name, String
417 ASSERT.boolean show_code
418 ASSERT.kind_of tag, Symbol
419
420 ASSERT.assert(show_code, "show_code")
421
422 name = md_method.name
423 args = md_method.args
424 nargs = args.length
425 uniq_num = transform_uniq_num(
426 md_method.uniq_num, md_method.max_uniq_num
427 )
428
429 pair = {
430 :module_function => [ "%s.%s%s%s", TLS::MODULE_FUNCTION ],
431 :module_method => [ "%s.%s%s%s", TLS::MODULE_METHOD ],
432 :class_method => [ "%s.%s%s%s", TLS::CLASS_METHOD ],
433 :instance_method => [ "%s#%s%s%s", TLS::INSTANCE_METHOD ]
434 }[tag]
435 ASSERT.tuple_of(pair, [String, String],
436 "Unknown method tag: %s", tag
437 )
438 title_format, method_type = pair
439
440 title = format(title_format,
441 module_display_name,
442 name,
443 if uniq_num then format(" %s", uniq_num) else '' end,
444 if nargs > 0 then format(" / %d", nargs) else '' end
445 )
446
447 mb_location = DBOOK.para {
448 [
449 Link.transform_line(
450 md_method.a_link_to_line, show_code
451 ),
452
453 DBOOK.text( ' in '),
454
455 Link.transform_file(md_method.a_link_to_file, show_code)
456 ]
457 }
458
459 mb_synopsys = DBOOK.para {
460 [
461 if args.empty?
462 DBOOK.function(name)
463 else
464 last_index_of_args = args.length - 1
465
466 DBOOKEX.informal_table('rl', :frame => 'none') {
467 args.map_with_index { |arg, index|
468 ASSERT.kind_of arg, String
469
470 is_first = index <= 0
471 is_last = index >= last_index_of_args
472
473 transform_method_arg(
474 name, arg, is_first, is_last
475 )
476 }
477 }
478 end
479 ]
480 }
481
482 id = Id.transform_property module_id, name, md_method.uniq_num
483 DBOOK.section(:id => id) {
484 [
485 transform_section_info(
486 title, name, method_type, module_title
487 ),
488
489 transform_location(md_method, show_code),
490
491 mb_synopsys
492 ]
493 }
494 end
495
496
497 def transform_method_arg(name, arg, is_first, is_last)
498 ASSERT.kind_of name, String
499 ASSERT.kind_of arg, String
500 ASSERT.boolean is_first
501 ASSERT.boolean is_last
502
503 DBOOK.row {
504 [
505 if is_first
506 [
507 DBOOK.function(name),
508
509 DBOOK.text('(')
510 ]
511 else
512 []
513 end,
514
515 [
516 DBOOK.var_name(arg),
517
518 DBOOK.text(
519 if is_last then ')' else ',' end
520 )
521 ]
522 ].map { |entry| DBOOK.entry { entry } }
523 }
524 end
525
526
527 def transform_uniq_num(uniq_num, max_uniq_num)
528 ASSERT.kind_of uniq_num, Integer
529 ASSERT.kind_of max_uniq_num, Integer
530
531 return nil if uniq_num == 0
532
533 str_uniq_num = format(
534 "(%d/%s)",
535
536 uniq_num,
537
538 if max_uniq_num == uniq_num
539 'E'
540 else
541 max_uniq_num.to_s
542 end
543 )
544
545 ASSERT.kind_of str_uniq_num, String
546 end
547
548
549 def transform_display_name(md_module, opt_name = nil)
550 ASSERT.kind_of md_module, MDM::Module
551 ASSERT.opt_kind_of opt_name, String
552
553 display_name =
554 case md_module
555 when MDM::ToplevelModule
556 TLS::TOPLEVEL_MODULE
557 when MDM::BuiltinModule
558 TLS::BUILTIN_MODULE
559 when MDM::UnknownModule
560 TLS::UNKNOWN_MODULE
561 when MDM::UnknownClass
562 TLS::UNKNOWN_CLASS
563 else
564 opt_name
565 end
566
567 ASSERT.kind_of display_name, String
568 end
569
570
571 def transform_section_info(title, primary, secondary, tertiary = nil)
572 ASSERT.kind_of title, String
573 ASSERT.kind_of primary, String
574 ASSERT.kind_of secondary, String
575 ASSERT.opt_kind_of tertiary, String
576
577 DBOOK.section_info {
578 [
579 DBOOK.title(title),
580
581 DBOOK.index_term {
582 [
583 DBOOK.primary(primary),
584
585 DBOOK.secondary(secondary)
586 ] + (
587 if tertiary
588 [ DBOOK.tertiary(tertiary) ]
589 else
590 []
591 end
592 )
593 }
594 ]
595 }
596 end
597
598
599 def transform_location(md_property, show_code)
600 ASSERT.kind_of md_property, MDA::Module::Property
601 ASSERT.boolean show_code
602
603 DBOOK.para {
604 [
605 Link.transform_line(
606 md_property.a_link_to_line, show_code
607 ),
608
609 DBOOK.text( ' in '),
610
611 Link.transform_file(md_property.a_link_to_file, show_code)
612 ]
613 }
614 end
615 end
616
617 end # TmDoc::Transformer::DocumentIntoDocBook
618
619 end # TmDoc