1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2008 Jean Privat <jean@pryen.org>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # The main module of the nitdoc program
25 # Store knowledge and facilities to generate files
27 super AbstractCompiler
28 # Destination directory
29 readable writable var _dir
: String = "."
31 # Content of a generated file
32 var _stage_context
: StageContext = new StageContext(null)
34 # Add a string in the content
36 _stage_context
.content
.add
(s
)
37 _stage_context
.validate
= true
40 # Add a string in the content iff some other string are added
41 fun stage
(s
: String) do _stage_context
.content
.add
(s
)
43 # Create a new stage in the content
44 fun open_stage
do _stage_context
= new StageContext(_stage_context
)
46 # Close the current stage in the content
49 var s
= _stage_context
.parent
50 if _stage_context
.validate
then
51 s
.content
.add_all
(_stage_context
.content
)
58 # Write the content to a new file
59 fun write_to
(filename
: String)
61 var f
= new OFStream.open
(filename
)
62 for s
in _stage_context
.content
do
68 # Currently computed mmmodule
69 readable var _mmmodule
: nullable MMSrcModule
71 # Is the current directory module computed as a simple modude ?
72 readable writable var _inside_mode
: Bool = false
74 # Is the current module computed as a intruded one ?
75 readable writable var _intrude_mode
: Bool = false
77 # Compued introducing entities (for the index)
78 var _entities
: Array[MMEntity] = new Array[MMEntity]
80 # Register an entity (for the index)
81 fun register
(e
: MMEntity)
83 if not _entities
.has
(e
) then
85 if e
isa MMSrcModule then
94 _stage_context
= new StageContext(null)
97 # Generate common files (frames, index, overview)
100 info
("Generating other files",1)
105 add
("<html><body>\n")
106 add
("<a href=\"overview
.html\
" target=\"mainFrame\
">Overview</a><br/>\n")
107 add
("<a href=\"index-1
.html\
" target=\"mainFrame\
">Index</a><br/>\n")
108 var modules
= modules
.to_a
111 var rootdirs
= new Array[MMDirectory]
114 if md
.parent
== null and not rootdirs
.has
(md
) then
119 var done
= new Array[MMModule]
120 for root
in rootdirs
do
121 var dirstack
= [root
]
123 add
("{root.name}<br/>\n")
124 var indent
= " "
125 while not dirstack
.is_empty
do
128 if done
.has
(m
) then continue
130 if md
.owner
== m
and md
.parent
== curdir
then
131 # It's a directory module
132 add
("{indent}<a href=\"{m}.html\
" target=\"mainFrame\
">{m}</a><br/>\n")
134 dirstack
.push
(curdir
)
135 indent
= "  " * dirstack
.length
137 break # restart to preserve alphabetic order
138 else if md
== curdir
then
139 if md
.owner
== m
then
140 add
("{indent}<a href=\"{m}_
.html\
" target=\"mainFrame\
">{m}</a><br/>\n")
142 add
("{indent}<a href=\"{m}.html\
" target=\"mainFrame\
">{m}</a><br/>\n")
150 if not dirstack
.is_empty
then
151 curdir
= dirstack
[dirstack
.length-1
]
152 indent
= "  " * dirstack
.length
157 add
("</body></html>\n")
158 write_to
("{dir}/menu-frame.html")
164 for e
in _entities
do
165 add
("<dt><b>{e.html_link(self)}</b> - {e.prototype_head(self)} <b>{e}</b>{e.prototype_body(self)} {e.locate(self)}<dd>{e.short_doc}\n")
167 add
("</dl></body></html>\n")
168 write_to
("{dir}/index-1.html")
171 add_header
("Overview")
173 var f
= new OFStream.open
("{_dir}/all_.module_hierarchy.dot")
174 f
.write
(module_hierarchy
.to_dot
)
177 sys
.system
("dot -Tpng {_dir}/all_.module_hierarchy.dot -o {_dir}/all_.module_hierarchy.png")
179 add
("<input type=\"button\
" value=\"View/Hide module hierarchy\
" Onclick=\"show_hide
('module_hierarchy');\
" />")
180 add
("<center><img id=\"module_hierarchy\
" src=\"all_
.module_hierarchy
.png\
" alt=\"module hierarchy\
" style=\"display
:none\
" border=\"1\
" /></center><br />\n")
182 add
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
183 add
("<tr bgcolor=\"#CCCCFF\"><th colspan=\"2\"><big>Overview of all Modules</big></th><tr>\n")
185 add
("<tr><td width=\"20%\
" align=\"right\
">{m.html_link(self)}</td><td>{m.short_doc}</td><tr>\n")
187 add
("</table></body></html>\n")
188 write_to
("{dir}/overview.html")
191 add
("<html>\n<frameset cols=\"20%,80%\
">\n<frame src=\"menu-frame
.html\
" name=\"menuFrame\
" title=\"Menu\
">\n<frame src=\"overview
.html\
" name=\"mainFrame\
" title=\"Main\
" scrolling=\"yes\
">\n</frameset></html>\n")
192 write_to
("{dir}/index.html")
195 fun add_header
(title
: String)
197 add
("<html><head><title>{title}</title><script type=\"text
/JavaScript\
">function show_hide(id)\{if (document.getElementById(id).style.display==\"none\")\{document.getElementById(id).style.display=\"block\";\}else \{document.getElementById(id).style.display=\"none\";\}\}</script></head>\n<body>\n")
198 add
("<table border=\"0\
" width=\"100%\
" cellpadding=\"1\
" cellspacing=\"0\
"><tr><td bgcolor=\"#eeeeff\">\n")
199 add
("<a href=\"overview
.html\
"><b>Overview</b></a> <a href=\"index-1
.html\
"><b>Index</b></a> <a href=\"index
.html\
" target=\"_top\
"><b>With Frames</b></a>\n")
200 add
("</td></tr></table>")
203 if (not inside_mode
and not intrude_mode
) or mod
== null then
204 add
("<b>Public</b> ")
206 add
("<a href=\"{mod}.html\
"><b>Public</b></a> ")
208 if inside_mode
or mod
== null then
209 add
("<b>Inside</b> ")
210 else if mod
.directory
.owner
!= mod
then
211 add
("<strike><b>Inside</b></strike> ")
213 add
("<a href=\"{mod}_
.html\
"><b>Inside</b></a> ")
215 if intrude_mode
or mod
== null then
216 add
("<b>Intrude</b> ")
218 add
("<a href=\"{mod}__
.html\
"><b>Intrude</b></a> ")
223 # Sorter of entities in alphabetical order
224 var _sorter
: AlphaSorter[MMEntity] = new AlphaSorter[MMEntity]
226 # Sort entities in the alphabetical order
227 fun sort
(array
: Array[MMEntity])
232 readable writable var _owned_modules
: Array[MMModule] = new Array[MMModule]
234 # Return the known_owner for current module
235 # if inside_mode is set, it could be a different result
236 fun known_owner_of
(m
: MMModule): MMModule
239 if mod
== null then return m
240 var res
= mod
.known_owner_of
(m
)
241 if not inside_mode
and not intrude_mode
and res
.directory
.owner
== mod
then
248 readable var _opt_dir
: OptionString = new OptionString("Directory where doc is generated", "-d", "--dir")
250 redef fun perform_work
(mods
)
254 for mod
in modules
do
255 assert mod
isa MMSrcModule
256 mod
.extract_module_doc
(self)
258 self.extract_other_doc
265 option_context
.add_option
(opt_dir
)
268 redef fun process_options
271 var d
= opt_dir
.value
272 if d
!= null then dir
= d
276 # Conditionnal part of the text content of a DocContext
278 # Content of the current stage
279 readable var _content
: Array[String] = new Array[String]
281 # Is a normal string already added?
282 readable writable var _validate
: Bool = false
284 # Parent stage is any
285 readable var _parent
: nullable StageContext = null
287 init(parent
: nullable StageContext) do _parent
= parent
291 # Efficiently sort object with their to_s method
292 class AlphaSorter[E
: Object]
293 super AbstractSorter[E
]
294 redef fun compare
(a
, b
)
314 # Keep track of to_s values
315 var _dico
: HashMap[Object, String] = new HashMap[Object, String]
320 # Generalization of metamodel entities
323 fun html_link
(dctx
: DocContext): String is abstract
325 # Is the entity should appear in the generaed doc
326 fun need_doc
(dctx
: DocContext): Bool is abstract
328 # Return a one liner description
329 fun short_doc
: String do return " "
331 # The doc node from the AST
332 # Return null is none
333 fun doc
: nullable ADoc do return null
335 # Human redable location of the entity (module/class/property)
336 fun locate
(dctx
: DocContext): String do return ""
338 # Part of the prototype before the name (kind, modifiers, qualifier)
339 fun prototype_head
(dctx
: DocContext): String is abstract
341 # Part of the property after the name (signature, modifiers)
342 fun prototype_body
(dctx
: DocContext): String do return ""
347 redef fun html_link
(dctx
) do
348 if dctx
.mmmodule
== self then
351 return "<a href=\"{self}.html\
">{self}</a>"
354 redef fun need_doc
(dctx
) do return true
355 redef fun prototype_head
(dctx
) do return "module "
357 var _known_owner_of_cache
: Map[MMModule, MMModule] = new HashMap[MMModule, MMModule]
359 # Return the owner of `module` from the point of view of `self`
360 fun known_owner_of
(mod
: MMModule): MMModule
362 if _known_owner_of_cache
.has_key
(mod
) then return _known_owner_of_cache
[mod
]
364 # is module is publicly imported by self?
365 if mhe
< mod
and visibility_for
(mod
) != 0 then
366 res
= known_owner_of_intern
(mod
, self, false)
368 # Return the canonnical owner of module from the point of view of self
369 res
= mod
.owner
(self)
371 _known_owner_of_cache
[mod
] = res
375 # Return the most general module that own self
376 fun owner
(from
: MMModule): MMModule
379 var d
: nullable MMDirectory = directory
380 while d
!= null and d
!= from
.directory
do
382 if o
!= null and o
.mhe
<= res
then res
= o
389 private fun known_owner_of_intern
(mod
: MMModule, from
: MMModule, as_owner
: Bool): MMModule
391 if mod
== self then return self
392 var candidates
= new Array[MMModule]
393 for m
in explicit_imported_modules
do
394 if from
.visibility_for
(m
) == 0 then continue
395 if not m
.mhe
<= mod
then continue
396 candidates
.add
(m
.known_owner_of_intern
(mod
, from
, true))
398 # FIXME: I do not know what this does
399 if candidates
.is_empty
then return mod
.owner
(from
)
400 var max
= candidates
.first
401 for m
in candidates
do
402 if max
.mhe
< m
then max
= m
404 if as_owner
and max
.directory
.owner
== self then
413 redef class MMLocalProperty
415 # Anchor of the property description in the module html file
416 fun html_anchor
: String
418 return "PROP_{local_class}_{cmangle(name)}"
421 redef fun html_link
(dctx
)
424 if not need_doc
(dctx
) then m
= global
.intro
.mmmodule
425 m
= dctx
.known_owner_of
(m
)
426 if m
== dctx
.mmmodule
then
427 return "<a href=\"#{html_anchor}\">{self}</a>"
429 return "<a href=\"{m}.html
#{html_anchor}\">{self}</a>"
433 # Kind of property (fun, attr, etc.)
434 fun kind
: String is abstract
436 redef fun locate
(dctx
)
438 return "in {mmmodule.html_link(dctx)}::{local_class.html_link(dctx)}"
441 fun known_intro_class
(dctx
: DocContext): MMLocalClass
443 var mod
= dctx
.known_owner_of
(global
.intro
.local_class
.mmmodule
)
444 var cla
= mod
[global
.intro
.local_class
.global
]
448 redef fun prototype_head
(dctx
)
451 var intro_class
= known_intro_class
(dctx
)
452 var is_redef
= local_class
!= intro_class
454 if is_redef
then res
.append
("redef ")
455 if global
.visibility_level
== 2 then
456 res
.append
("protected ")
457 else if global
.visibility_level
== 3 then
458 res
.append
("private ")
462 var gp
= global
.intro
463 if intro_class
.global
!= local_class
.global
then
464 res
.append
(" {mmmodule[intro_class.global].html_link(dctx)}::")
465 else if intro_class
.mmmodule
!= mmmodule
then
466 res
.append
(" {intro_class.mmmodule.html_link(dctx)}::")
472 redef fun prototype_body
(dctx
)
475 res
.append
(signature
.to_html
(dctx
, true))
477 if s
isa MMMethod then
478 if s
.is_abstract
then
479 res
.append
(" is abstract")
480 else if s
.is_intern
then
481 res
.append
(" is intern")
487 redef fun need_doc
(dctx
)
489 if global
.visibility_level
>= 3 or self isa MMAttribute then
490 if not dctx
.intrude_mode
then return false
491 if dctx
.mmmodule
.visibility_for
(mmmodule
) == 0 then return false
493 if global
.intro
== self then
504 else if global
.intro
== self then
507 return global
.intro
.short_doc
514 if n
== null or not n
isa APropdef then
521 if d
.n_comment
.is_empty
then
529 redef fun kind
do return if global
.is_init
then "init" else "fun"
531 redef class MMAttribute
532 redef fun kind
do return "var"
534 redef class MMTypeProperty
535 redef fun kind
do return "type"
538 redef class MMSrcModule
539 # Extract and generate html file for the module
540 fun extract_module_doc
(dctx
: DocContext)
542 dctx
.info
("Generating HTML for module {name}",1)
546 extract_module_doc_inside
(dctx
)
547 dctx
.write_to
("{dctx.dir}/{name}.html")
549 dctx
.intrude_mode
= true
551 extract_module_doc_inside
(dctx
)
552 dctx
.write_to
("{dctx.dir}/{name}__.html")
553 dctx
.intrude_mode
= false
555 if directory
.owner
== self then
556 dctx
.inside_mode
= true
558 extract_module_doc_inside
(dctx
)
559 dctx
.write_to
("{dctx.dir}/{name}_.html")
560 dctx
.inside_mode
= false
564 fun extract_module_doc_inside
(dctx
: DocContext)
566 dctx
.add_header
("Module {self}")
567 dctx
.add
("<h1>Module {self}</h1>\n<dl>")
569 var d
: nullable MMDirectory = directory
571 if d
.owner
!= null and (d
.owner
!= self or dctx
.inside_mode
or dctx
.intrude_mode
) then
572 s
= "{d.owner.html_link(dctx)}::{s}"
576 dctx
.add
("{s}<br/>{prototype_head(dctx)}<b>{self}</b>{prototype_body(dctx)}<br/>\n")
578 var strs
= new Array[String]
579 var intrude_modules
= new Array[MMModule]
580 var public_modules
= new Array[MMModule]
581 var private_modules
= new Array[MMModule]
582 var owned_modules
= dctx
.owned_modules
584 for m
in mhe
.greaters
do
585 var v
= visibility_for
(m
)
586 if not dctx
.inside_mode
and not dctx
.intrude_mode
and m
.directory
.owner
== self then
587 if v
>= 2 then owned_modules
.add
(m
)
591 intrude_modules
.add
(m
)
593 public_modules
.add
(m
)
595 private_modules
.add
(m
)
598 if not intrude_modules
.is_empty
then
599 var mods
= mhe
.order
.select_smallests
(intrude_modules
)
600 for i
in mods
do strs
.add
(i
.html_link
(dctx
))
601 dctx
.add
("<dt>Intruded modules: <dd>{strs.join(", ")}\n")
603 if not public_modules
.is_empty
then
605 var mods
= mhe
.order
.select_smallests
(public_modules
)
606 for i
in mods
do strs
.add
(i
.html_link
(dctx
))
607 dctx
.add
("<dt>Imported modules: <dd>{strs.join(", ")}\n")
609 if not private_modules
.is_empty
then
611 var mods
= mhe
.order
.select_smallests
(private_modules
)
612 for i
in mods
do strs
.add
(i
.html_link
(dctx
))
613 dctx
.add
("<dt>Privatly imported modules: <dd>{strs.join(", ")}\n")
618 if doc
!= null then dctx
.add
("<pre>{doc.to_html}</pre>\n")
620 var new_classes
= new Array[MMLocalClass]
621 for c
in local_classes
do
622 if c
.need_doc
(dctx
) then
624 if c
.global
.intro
== c
then
628 for m
in owned_modules
do
629 if m
.global_classes
.has
(c
.global
) then
631 if mc
.need_doc
(dctx
) then
640 if not new_classes
.is_empty
then
641 dctx
.add
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
642 dctx
.add
("<tr bgcolor=\"#FF6347\"><th colspan=\"2\"><big>Main Summary of {self}</big></th><tr>\n")
643 for c
in new_classes
do
644 if c
.global
.intro
== c
or owned_modules
.has
(c
.global
.intro
.mmmodule
) then
646 for p
in c
.cshe
.direct_greaters
do
647 if p
.global
.intro
.mmmodule
== self or owned_modules
.has
(p
.global
.intro
.mmmodule
) then
652 dctx
.add
("<tr><td width=\"20%\
" align=\"right\
"><u>Introduce</u> {c.prototype_head(dctx)}</td><td><b>{c.html_link(dctx)}</b>{c.prototype_body(dctx)}<br/>{c.short_doc}</td><tr>\n")
655 for p
in c
.local_local_properties
do
656 if p
.global
.is_method
and p
.global
.intro
== p
then
657 dctx
.add
("<tr><td width=\"20%\
" align=\"right\
"><u>Refine</u> <b>{c.html_link(dctx)}</b> <u>Introduce</u> {p.prototype_head(dctx)}</td><td><b>{p.html_link(dctx)}</b>{p.prototype_body(dctx)}<br/> {p.short_doc}</td></tr>\n")
662 dctx
.add
("</table><br/>\n")
665 if not new_classes
.is_empty
then
666 dctx
.sort
(new_classes
)
667 dctx
.add
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
668 dctx
.add
("<tr bgcolor=\"#CCCCFF\"><th colspan=\"2\"><big>Class Summary of {self}</big></th><tr>\n")
669 for c
in new_classes
do
670 dctx
.add
("<tr><td width=\"20%\
" align=\"right\
">{c.prototype_head(dctx)}</td><td><b>{c.html_link(dctx)}</b>{c.prototype_body(dctx)}<br/>{c.short_doc}</td><tr>\n")
672 dctx
.add
("</table><br/>\n")
675 if not new_classes
.is_empty
then
676 dctx
.add
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
677 dctx
.add
("<tr bgcolor=\"#CCCCFF\"><th><big>Class Detail of {self}</big></th><tr>\n")
678 dctx
.add
("</table>\n")
680 for c
in new_classes
do
681 c
.extract_class_doc
(dctx
)
685 dctx
.add
("</body></html>\n")
701 if n
.n_moduledecl
== null then
704 var np
= n
.n_moduledecl
709 if d
.n_comment
.is_empty
then
718 # Html transcription of the doc
722 for c
in n_comment
do
723 res
.append
(c
.text
.substring_from
(1))
728 # Oneliner transcription of the doc
731 return n_comment
.first
.text
.substring_from
(1)
735 redef class MMLocalClass
737 # Anchor of the class description in the module html file
738 fun html_anchor
: String do return "CLASS_{self}"
740 redef fun html_link
(dctx
)
743 if not need_doc
(dctx
) then m
= global
.mmmodule
744 m
= dctx
.known_owner_of
(m
)
745 if m
== dctx
.mmmodule
then
746 return "<a href=\"#{html_anchor}\">{self}</a>"
748 return "<a href=\"{m}.html
#{html_anchor}\">{self}</a>"
752 redef fun short_doc
do return global
.intro
.short_doc
754 redef fun doc
do return global
.intro
.doc
756 redef fun need_doc
(dctx
) do
757 if mmmodule
== dctx
.mmmodule
then
758 for m
in dctx
.owned_modules
do
759 if m
.global_classes
.has
(global
) then
761 if c
.need_doc
(dctx
) then return true
768 redef fun locate
(dctx
) do return "in {mmmodule.html_link(dctx)}"
770 fun known_intro
(dctx
: DocContext): MMLocalClass do return dctx
.known_owner_of
(global
.intro
.mmmodule
)[global
]
772 redef fun prototype_head
(dctx
)
775 var ki
= known_intro
(dctx
)
776 var is_redef
= ki
!= self
777 if is_redef
then res
.append
("redef ")
778 if global
.visibility_level
== 3 then res
.append
("private ")
780 if is_redef
then res
.append
("{ki.mmmodule.html_link(dctx)}::")
784 redef fun prototype_body
(dctx
)
789 for i
in [0..arity
[ do
790 var t
= get_formal
(i
)
791 res
.append
(t
.name
.to_s
)
793 res
.append
(t
.bound
.html_link
(dctx
))
800 # Extract the doc of a class
801 fun extract_class_doc
(dctx
: DocContext)
803 dctx
.add
("<a name=\"{html_anchor}\
"></a><h2>{self}</h2><small>{mmmodule.html_link(dctx)}::</small><br/>{prototype_head(dctx)}<b>{self}</b>{prototype_body(dctx)}\n")
804 dctx
.add
("<blockquote>\n")
807 var sup2
= new Array[String]
808 var intro_module
= dctx
.known_owner_of
(global
.mmmodule
)
809 if intro_module
!= mmmodule
then
810 dctx
.add
("<dt>Refine {self} from: <dd>{intro_module.html_link(dctx)}\n")
812 var mods
= new Array[MMModule]
813 for c
in crhe
.greaters
do
814 if c
.need_doc
(dctx
) then
815 var km
= dctx
.known_owner_of
(c
.mmmodule
)
816 if km
!= mmmodule
and km
!= intro_module
and not mods
.has
(km
) then
821 for c
in crhe
.linear_extension
do
822 if mods
.has
(c
.mmmodule
) then sup2
.add
(c
.mmmodule
.html_link
(dctx
))
824 if not sup2
.is_empty
then dctx
.add
("<dt>Previous refinements in: <dd>{sup2.join(", ")}\n")
826 if not cshe
.greaters
.is_empty
then
828 var clas
= new Array[MMLocalClass]
829 for c
in cshe
.direct_greaters
do
830 sup2
.add
(c
.html_link
(dctx
))
832 dctx
.add
("<dt>Direct superclasses: <dd>{sup2.join(", ")}\n")
834 for c
in cshe
.linear_extension
do
835 if c
!= self then sup2
.add
(c
.html_link
(dctx
))
837 dctx
.add
("<dt>All superclasses: <dd>{sup2.join(", ")}\n")
839 if not cshe
.direct_smallers
.is_empty
then
841 for c
in cshe
.direct_smallers
do
842 sup2
.add
(c
.html_link
(dctx
))
844 dctx
.add
("<dt>Direct subclasses: <dd>{sup2.join(", ")}\n")
847 for c
in crhe
.smallers
do
848 c
.compute_super_classes
849 for c2
in c
.mmmodule
.local_classes
do
850 if not c2
isa MMConcreteClass then continue
851 c2
.compute_super_classes
854 for c2
in c
.cshe
.direct_smallers
do
855 if c2
.global
.intro
== c2
then
856 sup2
.add
("{c2.html_link(dctx)}")
860 if not sup2
.is_empty
then
861 dctx
.add
("<dt>Other direct subclasses in known modules: <dd>{sup2.join(", ")}\n")
864 for c
in crhe
.order
do
865 if not mmmodule
.mhe
<= c
.mmmodule
and c
.need_doc
(dctx
) then
866 sup2
.add
(c
.mmmodule
.html_link
(dctx
))
869 if not sup2
.is_empty
then
870 dctx
.add
("<dt>Refinements in known modules: <dd>{sup2.join(", ")}\n")
876 dctx
.add
("<pre>{doc.to_html}</pre>\n")
879 var details
= new Array[Array[MMLocalProperty]]
880 for i
in [0..4[ do details
.add
(property_summary
(dctx
, i
))
881 for i
in [0..4[ do property_detail
(dctx
, i
, details
[i
])
883 dctx
.add
("</blockquote><hr/>\n")
886 fun pass_name
(pass
: Int): String
888 var names
= once
["Virtual Types", "Consructors", "Methods", "Attributes"]
892 fun accept_prop
(p
: MMLocalProperty, pass
: Int): Bool
895 return p
isa MMTypeProperty
896 else if pass
== 1 then
897 return p
.global
.is_init
898 else if pass
== 2 then
899 return p
isa MMMethod and not p
.global
.is_init
900 else if pass
== 3 then
901 return p
isa MMAttribute
906 fun property_summary
(dctx
: DocContext, pass
: Int): Array[MMLocalProperty]
908 var passname
= pass_name
(pass
)
910 dctx
.stage
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
911 dctx
.stage
("<tr bgcolor=\"#CCCCFF\"><th colspan=\"2\">{passname} Summary of {self}</th></tr>\n")
913 var new_props
= new Array[MMLocalProperty]
914 for g
in global_properties
do
915 if not accept_prop
(g
.intro
, pass
) then continue
916 if mmmodule
.visibility_for
(g
.intro
.mmmodule
) < g
.visibility_level
then continue
918 if p
.local_class
!= self or not p
.need_doc
(dctx
) then
919 var cla
= new Array[MMLocalClass]
920 for m
in dctx
.owned_modules
do
921 if not m
.global_classes
.has
(global
) then continue
923 if not c
isa MMConcreteClass then continue
924 if not c
.has_global_property
(g
) then continue
926 if p2
.local_class
!= c
or not p2
.need_doc
(dctx
) then continue
929 if cla
.is_empty
then continue
930 cla
= crhe
.order
.select_smallests
(cla
)
934 if p
.global
.intro
== p
then
939 for p
in new_props
do
940 dctx
.add
("<tr><td width=\"20%\
" align=\"right\
">{p.prototype_head(dctx)}</td><td><b>{p.html_link(dctx)}</b>{p.prototype_body(dctx)}<br/> {p.short_doc}</td></tr>\n")
942 dctx
.stage
("</table><br/>\n")
945 dctx
.stage
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
947 # skip pass 1 because constructors are not inherited
948 var cmap
= new HashMap[MMLocalClass, Array[MMLocalProperty]]
949 var mmap
= new HashMap[MMModule, Array[MMLocalProperty]]
950 for c
in che
.greaters
do
951 if c
isa MMSrcLocalClass then
952 var km
= dctx
.known_owner_of
(c
.mmmodule
)
953 var kc
= km
[c
.global
]
954 if kc
== self then continue
955 var props
: Array[MMLocalProperty]
956 if km
== mmmodule
then
957 if cmap
.has_key
(kc
) then
960 props
= new Array[MMLocalProperty]
964 if mmap
.has_key
(km
) then
967 props
= new Array[MMLocalProperty]
971 for g
in c
.global_properties
do
973 if p
.local_class
== c
and p
.need_doc
(dctx
) and accept_prop
(p
, pass
) then
980 dctx
.stage
("<tr bgcolor=\"#EEEEFF\"><th colspan=\"2\"><small>Inherited {passname}</small></th><tr>\n")
981 for c
in cshe
.linear_extension
do
982 if not cmap
.has_key
(c
) then continue
984 if props
.is_empty
then continue
986 var properties
= new Array[String]
987 for p
in props
do properties
.add
(p
.html_link
(dctx
))
988 dctx
.add
("<tr><td width=\"20%\
"><small>from {c.html_link(dctx)}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
993 dctx
.stage
("<tr bgcolor=\"#EEEEFF\"><th colspan=\"2\"><small>Imported {passname}</small></th><tr>\n")
994 for m
in mmmodule
.mhe
.linear_extension
do
995 if not mmap
.has_key
(m
) then continue
997 if props
.is_empty
then continue
999 var properties
= new Array[String]
1000 for p
in props
do properties
.add
(p
.html_link
(dctx
))
1001 dctx
.add
("<tr><td width=\"20%\
"><small>from {m.html_link(dctx)}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
1006 var mmap
= new HashMap[MMModule, Array[MMLocalProperty]]
1007 for c
in crhe
.order
do
1008 if mmmodule
.mhe
<= c
.mmmodule
or dctx
.owned_modules
.has
(c
.mmmodule
) or not c
isa MMSrcLocalClass then continue
1009 var km
= dctx
.known_owner_of
(c
.mmmodule
)
1010 if mmmodule
.mhe
<= km
then continue
1011 var kc
= km
[c
.global
]
1012 var props
: Array[MMLocalProperty]
1013 if mmap
.has_key
(km
) then
1016 props
= new Array[MMLocalProperty]
1019 for g
in c
.global_properties
do
1021 if p
.local_class
== c
and p
.need_doc
(dctx
) and accept_prop
(p
, pass
) then
1023 if not props
.has
(kp
) then props
.add
(kp
)
1026 # c.properties_inherited_from(dctx, self, pass)
1029 dctx
.stage
("<tr bgcolor=\"#EEEEFF\"><th colspan=\"2\"><small>Added {passname} in known modules</small></th><tr>\n")
1030 for c
in crhe
.order
do
1032 if not mmap
.has_key
(m
) then continue
1034 if props
.is_empty
then continue
1036 var properties
= new Array[String]
1037 for p
in props
do properties
.add
(p
.html_link
(dctx
))
1038 dctx
.add
("<tr><td width=\"20%\
"><small>in {m.html_link(dctx)}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
1041 dctx
.stage
("</table><br/><br/>\n")
1048 fun property_detail
(dctx
: DocContext, pass
: Int, new_props
: Array[MMLocalProperty])
1050 var passname
= pass_name
(pass
)
1052 dctx
.stage
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
1053 dctx
.stage
("<tr bgcolor=\"#CCCCFF\"><th>{passname} Detail of {self}</th><tr>\n")
1054 dctx
.stage
("</table>\n")
1057 for p
in new_props
do
1058 dctx
.add
("<a name=\"{p.html_anchor}\
"></a><h3>{p}</h3><p><small>{p.mmmodule.html_link(dctx)}::{p.local_class.html_link(dctx)}::</small><br/>{p.prototype_head(dctx)} <b>{p.name}</b>{p.prototype_body(dctx)}</p>\n")
1059 dctx
.add
("<blockquote>")
1062 dctx
.add
("<pre>{doc.to_html}</pre>\n")
1064 dctx
.stage
("</blockquote>\n")
1068 dctx
.stage
("<hr/>\n")
1075 # Add rows for properties inheriterd to some heirs
1076 fun properties_inherited_from
(dctx
: DocContext, heir
: MMLocalClass, pass
: Int)
1078 var properties
= new Array[String]
1079 for g
in global_properties
do
1081 if p
.local_class
== self and p
.need_doc
(dctx
) and accept_prop
(p
, pass
) then
1082 properties
.add
(p
.html_link
(dctx
))
1085 if not properties
.is_empty
then
1087 if heir
.global
== global
then
1088 s
= mmmodule
.html_link
(dctx
)
1090 s
= self.html_link
(dctx
)
1092 dctx
.add
("<tr><td width=\"20%\
"><small>in {s}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
1097 redef class MMSrcLocalClass
1103 else if global
.intro
== self then
1106 var bc
= global
.intro
1114 if not n
isa AStdClassdef then
1121 if d
.n_comment
.is_empty
then
1128 redef fun need_doc
(dctx
)
1130 if global
.visibility_level
>= 3 then
1131 if not dctx
.intrude_mode
then return false
1132 if dctx
.mmmodule
.visibility_for
(mmmodule
) == 0 then return false
1134 if global
.intro
== self then
1137 for p
in src_local_properties
do
1138 if p
.need_doc
(dctx
) then
1146 redef class MMSignature
1147 # Htlm transcription of the signature (with nested links)
1148 fun to_html
(dctx
: DocContext, with_closure
: Bool): String
1150 var res
= new Buffer
1153 res
.append
(self[0].html_link
(dctx
))
1154 for i
in [1..arity
[ do
1156 res
.append
(self[i
].html_link
(dctx
))
1160 if return_type
!= null then
1162 res
.append
(return_type
.html_link
(dctx
))
1164 if with_closure
then
1165 for c
in closures
do
1167 if c
.is_optional
then res
.append
("[")
1168 if c
.is_break
then res
.append
("break ")
1169 res
.append
("!{c.name}")
1170 res
.append
(c
.signature
.to_html
(dctx
, false))
1171 if c
.is_optional
then res
.append
("]")
1179 # Htlm transcription of the type (with nested links)
1180 fun html_link
(dctx
: DocContext): String do return to_s
1183 redef class MMTypeSimpleClass
1184 redef fun html_link
(dctx
) do return local_class
.html_link
(dctx
)
1187 redef class MMTypeGeneric
1188 redef fun html_link
(dctx
)
1190 var res
= new Buffer
1191 res
.append
(local_class
.html_link
(dctx
))
1193 res
.append
(params
[0].html_link
(dctx
))
1194 for i
in [1..params
.length
[ do
1196 res
.append
(params
[i
].html_link
(dctx
))
1203 var c
= new DocContext