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 special 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 print
"Generate {filename}"
62 var f
= new OFStream.open
(filename
)
63 for s
in _stage_context
.content
do
69 # Currently computed module
70 readable var _module
: nullable MMSrcModule
72 # Is the current directory module computed as a simple modude ?
73 readable writable var _inside_mode
: Bool = false
75 # Is the current module computed as a intruded one ?
76 readable writable var _intrude_mode
: Bool = false
78 # Compued introducing entities (for the index)
79 var _entities
: Array[MMEntity] = new Array[MMEntity]
81 # Register an entity (for the index)
82 fun register
(e
: MMEntity)
85 if e
isa MMSrcModule then
93 _stage_context
= new StageContext(null)
96 # Generate common files (frames, index, overview)
103 add
("<html><body>\n")
104 add
("<a href=\"overview
.html\
" target=\"mainFrame\
">Overview</a><br/>\n")
105 add
("<a href=\"index-1
.html\
" target=\"mainFrame\
">Index</a><br/>\n")
106 var modules
= modules
.to_a
109 var rootdirs
= new Array[MMDirectory]
112 if md
.parent
== null and not rootdirs
.has
(md
) then
117 var done
= new Array[MMModule]
118 for root
in rootdirs
do
119 var dirstack
= [root
]
121 add
("{root.name}<br/>\n")
122 var indent
= " "
123 while not dirstack
.is_empty
do
126 if done
.has
(m
) then continue
128 if md
.owner
== m
and md
.parent
== curdir
then
129 # It's a directory module
130 add
("{indent}<a href=\"{m}.html\
" target=\"mainFrame\
">{m}</a><br/>\n")
132 dirstack
.push
(curdir
)
133 indent
= "  " * dirstack
.length
135 break # restart to preserve alphabetic order
136 else if md
== curdir
then
137 if md
.owner
== m
then
138 add
("{indent}<a href=\"{m}_
.html\
" target=\"mainFrame\
">{m}</a><br/>\n")
140 add
("{indent}<a href=\"{m}.html\
" target=\"mainFrame\
">{m}</a><br/>\n")
148 if not dirstack
.is_empty
then
149 curdir
= dirstack
[dirstack
.length-1
]
150 indent
= "  " * dirstack
.length
155 add
("</body></html>\n")
156 write_to
("{dir}/menu-frame.html")
162 for e
in _entities
do
163 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")
165 add
("</dl></body></html>\n")
166 write_to
("{dir}/index-1.html")
169 add_header
("Overview")
170 add
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
171 add
("<tr bgcolor=\"#CCCCFF\"><th colspan=\"2\"><big>Overview of all Modules</big></th><tr>\n")
173 add
("<tr><td width=\"20%\
" align=\"right\
">{m.html_link(self)}</td><td>{m.short_doc}</td><tr>\n")
175 add
("</table></body></html>\n")
176 write_to
("{dir}/overview.html")
179 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")
180 write_to
("{dir}/index.html")
183 fun add_header
(title
: String)
185 add
("<html><head><title>{title}</title></head>\n<body>\n")
186 add
("<table border=\"0\
" width=\"100%\
" cellpadding=\"1\
" cellspacing=\"0\
"><tr><td bgcolor=\"#eeeeff\">\n")
187 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")
188 add
("</td></tr></table>")
190 if (not inside_mode
and not intrude_mode
) or module == null then
191 add
("<b>Public</b> ")
193 add
("<a href=\"{module}.html\
"><b>Public</b></a> ")
195 if inside_mode
or module == null then
196 add
("<b>Inside</b> ")
197 else if module.directory
.owner
!= module then
198 add
("<strike><b>Inside</b></strike> ")
200 add
("<a href=\"{module}_
.html\
"><b>Inside</b></a> ")
202 if intrude_mode
or module == null then
203 add
("<b>Intrude</b> ")
205 add
("<a href=\"{module}__
.html\
"><b>Intrude</b></a> ")
210 # Sorter of entities in alphabetical order
211 var _sorter
: AlphaSorter[MMEntity] = new AlphaSorter[MMEntity]
213 # Sort entities in the alphabetical order
214 fun sort
(array
: Array[MMEntity])
219 readable writable var _owned_modules
: Array[MMModule] = new Array[MMModule]
221 # Return the known_owner for current module
222 # if inside_mode is set, it could be a different result
223 fun known_owner_of
(m
: MMModule): MMModule
226 if module == null then return m
227 var res
= module.known_owner_of
(m
)
228 if not inside_mode
and not intrude_mode
and res
.directory
.owner
== module then
235 readable var _opt_dir
: OptionString = new OptionString("Directory where doc is generated", "-d", "--dir")
237 redef fun perform_work
(mods
)
241 for mod
in modules
do
242 assert mod
isa MMSrcModule
243 mod
.extract_module_doc
(self)
245 self.extract_other_doc
251 option_context
.add_option
(opt_dir
)
254 redef fun process_options
257 var d
= opt_dir
.value
258 if d
!= null then dir
= d
262 # Conditionnal part of the text content of a DocContext
264 # Content of the current stage
265 readable var _content
: Array[String] = new Array[String]
267 # Is a normal string already added?
268 readable writable var _validate
: Bool = false
270 # Parent stage is any
271 readable var _parent
: nullable StageContext = null
273 init(parent
: nullable StageContext) do _parent
= parent
277 # Efficiently sort object with their to_s method
278 class AlphaSorter[E
: Object]
279 special AbstractSorter[E
]
280 redef fun compare
(a
, b
)
300 # Keep track of to_s values
301 var _dico
: HashMap[Object, String] = new HashMap[Object, String]
306 # Generalization of metamodel entities
309 fun html_link
(dctx
: DocContext): String is abstract
311 # Is the entity should appear in the generaed doc
312 fun need_doc
(dctx
: DocContext): Bool is abstract
314 # Return a one liner description
315 fun short_doc
: String do return " "
317 # The doc node from the AST
318 # Return null is none
319 fun doc
: nullable ADoc do return null
321 # Human redable location of the entity (module/class/property)
322 fun locate
(dctx
: DocContext): String do return ""
324 # Part of the prototype before the name (kind, modifiers, qualifier)
325 fun prototype_head
(dctx
: DocContext): String is abstract
327 # Part of the property after the name (signature, modifiers)
328 fun prototype_body
(dctx
: DocContext): String do return ""
333 redef fun html_link
(dctx
) do
334 if dctx
.module == self then
337 return "<a href=\"{self}.html\
">{self}</a>"
340 redef fun need_doc
(dctx
) do return true
341 redef fun prototype_head
(dctx
) do return "module "
343 var _known_owner_of_cache
: Map[MMModule, MMModule] = new HashMap[MMModule, MMModule]
344 fun known_owner_of
(module: MMModule): MMModule
346 if _known_owner_of_cache
.has_key
(module) then return _known_owner_of_cache
[module]
348 if mhe
< module and visibility_for
(module) != 0 then
349 res
= known_owner_of_intern
(module, self, false)
351 res
= module.owner
(self)
353 _known_owner_of_cache
[module] = res
357 # Return the most general module that own self
358 fun owner
(from
: MMModule): MMModule
361 var d
: nullable MMDirectory = directory
362 while d
!= null and d
!= from
.directory
do
364 if o
!= null and o
.mhe
<= res
then res
= o
370 private fun known_owner_of_intern
(module: MMModule, from
: MMModule, as_owner
: Bool): MMModule
372 if module == self then return self
373 var candidates
= new Array[MMModule]
374 for m
in explicit_imported_modules
do
375 if from
.visibility_for
(m
) == 0 then continue
376 if not m
.mhe
<= module then continue
377 candidates
.add
(m
.known_owner_of_intern
(module, from
, true))
379 assert not candidates
.is_empty
380 var max
= candidates
.first
381 for m
in candidates
do
382 if max
.mhe
< m
then max
= m
384 if as_owner
and max
.directory
.owner
== self then
393 redef class MMLocalProperty
395 # Anchor of the property description in the module html file
396 fun html_anchor
: String
398 return "PROP_{local_class}_{cmangle(name)}"
401 redef fun html_link
(dctx
)
404 if not need_doc
(dctx
) then m
= global
.intro
.module
405 var m
= dctx
.known_owner_of
(m
)
406 if m
== dctx
.module then
407 return "<a href=\"#{html_anchor}\">{self}</a>"
409 return "<a href=\"{m}.html
#{html_anchor}\">{self}</a>"
413 # Kind of property (fun, attr, etc.)
414 fun kind
: String is abstract
416 redef fun locate
(dctx
)
418 return "in {module.html_link(dctx)}::{local_class.html_link(dctx)}"
421 fun known_intro_class
(dctx
: DocContext): MMLocalClass
423 var mod
= dctx
.known_owner_of
(global
.intro
.local_class
.module)
424 var cla
= mod
[global
.intro
.local_class
.global
]
428 redef fun prototype_head
(dctx
)
431 var intro_class
= known_intro_class
(dctx
)
432 var is_redef
= local_class
!= intro_class
434 if is_redef
then res
.append
("redef ")
435 if global
.visibility_level
== 2 then
436 res
.append
("protected ")
437 else if global
.visibility_level
== 3 then
438 res
.append
("private ")
442 var gp
= global
.intro
443 if intro_class
.global
!= local_class
.global
then
444 res
.append
(" {module[intro_class.global].html_link(dctx)}::")
445 else if intro_class
.module != module then
446 res
.append
(" {intro_class.module.html_link(dctx)}::")
452 redef fun prototype_body
(dctx
)
455 res
.append
(signature
.to_html
(dctx
))
457 if s
.node
!= null then
458 if s
.node
isa ADeferredMethPropdef then
459 res
.append
(" is abstract")
460 else if s
.node
isa AInternMethPropdef then
461 res
.append
(" is intern")
467 redef fun need_doc
(dctx
)
469 if global
.visibility_level
>= 3 or self isa MMAttribute then
470 if not dctx
.intrude_mode
then return false
471 if dctx
.module.visibility_for
(module) == 0 then return false
473 if global
.intro
== self then
484 else if global
.intro
== self then
487 return global
.intro
.short_doc
494 if n
== null or not node
isa PPropdef then
497 assert n
isa PPropdef
503 if d
.n_comment
.is_empty
then
511 redef fun kind
do return if global
.is_init
then "init" else "meth"
513 redef class MMAttribute
514 redef fun kind
do return "attr"
516 redef class MMTypeProperty
517 redef fun kind
do return "type"
520 redef class MMSrcModule
521 # Extract and generate html file for the module
522 fun extract_module_doc
(dctx
: DocContext)
527 extract_module_doc_inside
(dctx
)
528 dctx
.write_to
("{dctx.dir}/{name}.html")
530 dctx
.intrude_mode
= true
532 extract_module_doc_inside
(dctx
)
533 dctx
.write_to
("{dctx.dir}/{name}__.html")
534 dctx
.intrude_mode
= false
536 if directory
.owner
== self then
537 dctx
.inside_mode
= true
539 extract_module_doc_inside
(dctx
)
540 dctx
.write_to
("{dctx.dir}/{name}_.html")
541 dctx
.inside_mode
= false
545 fun extract_module_doc_inside
(dctx
: DocContext)
547 dctx
.add_header
("Module {self}")
548 dctx
.add
("<h1>Module {self}</h1>\n<dl>")
550 var d
: nullable MMDirectory = directory
552 if d
.owner
!= null and (d
.owner
!= self or dctx
.inside_mode
or dctx
.intrude_mode
) then
553 s
= "{d.owner.html_link(dctx)}::{s}"
557 dctx
.add
("{s}<br/>{prototype_head(dctx)}<b>{self}</b>{prototype_body(dctx)}<br/>\n")
559 var strs
= new Array[String]
560 var intrude_modules
= new Array[MMModule]
561 var public_modules
= new Array[MMModule]
562 var private_modules
= new Array[MMModule]
563 var owned_modules
= dctx
.owned_modules
565 for m
in mhe
.greaters
do
566 var v
= visibility_for
(m
)
567 if not dctx
.inside_mode
and not dctx
.intrude_mode
and m
.directory
.owner
== self then
568 if v
>= 2 then owned_modules
.add
(m
)
572 intrude_modules
.add
(m
)
574 public_modules
.add
(m
)
576 private_modules
.add
(m
)
579 if not intrude_modules
.is_empty
then
580 var mods
= mhe
.order
.select_smallests
(intrude_modules
)
581 for i
in mods
do strs
.add
(i
.html_link
(dctx
))
582 dctx
.add
("<dt>Intruded modules: <dd>{strs.join(", ")}\n")
584 if not public_modules
.is_empty
then
586 var mods
= mhe
.order
.select_smallests
(public_modules
)
587 for i
in mods
do strs
.add
(i
.html_link
(dctx
))
588 dctx
.add
("<dt>Imported modules: <dd>{strs.join(", ")}\n")
590 if not private_modules
.is_empty
then
592 var mods
= mhe
.order
.select_smallests
(private_modules
)
593 for i
in mods
do strs
.add
(i
.html_link
(dctx
))
594 dctx
.add
("<dt>Privatly imported modules: <dd>{strs.join(", ")}\n")
599 if doc
!= null then dctx
.add
("<pre>{doc.to_html}</pre>\n")
601 var new_classes
= new Array[MMLocalClass]
602 for c
in local_classes
do
603 if c
.need_doc
(dctx
) then
605 if c
.global
.intro
== c
then
609 for m
in owned_modules
do
610 if m
.global_classes
.has
(c
.global
) then
612 if mc
.need_doc
(dctx
) then
621 if not new_classes
.is_empty
then
622 dctx
.sort
(new_classes
)
623 dctx
.add
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
624 dctx
.add
("<tr bgcolor=\"#CCCCFF\"><th colspan=\"2\"><big>Class Summary of {self}</big></th><tr>\n")
625 for c
in new_classes
do
626 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")
628 dctx
.add
("</table><br/>\n")
631 if not new_classes
.is_empty
then
632 dctx
.add
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
633 dctx
.add
("<tr bgcolor=\"#CCCCFF\"><th><big>Class Detail of {self}</big></th><tr>\n")
634 dctx
.add
("</table>\n")
636 for c
in new_classes
do
637 c
.extract_class_doc
(dctx
)
641 dctx
.add
("</body></html>\n")
657 if n
.n_packagedecl
== null then
660 var np
= n
.n_packagedecl
661 assert np
isa APackagedecl
667 if d
.n_comment
.is_empty
then
676 # Html transcription of the doc
680 for c
in n_comment
do
681 res
.append
(c
.text
.substring_from
(1))
686 # Oneliner transcription of the doc
689 return n_comment
.first
.text
.substring_from
(1)
693 redef class MMLocalClass
695 # Anchor of the class description in the module html file
696 fun html_anchor
: String do return "CLASS_{self}"
698 redef fun html_link
(dctx
)
701 if not need_doc
(dctx
) then m
= global
.module
702 var m
= dctx
.known_owner_of
(m
)
703 if m
== dctx
.module then
704 return "<a href=\"#{html_anchor}\">{self}</a>"
706 return "<a href=\"{m}.html
#{html_anchor}\">{self}</a>"
710 redef fun short_doc
do return global
.intro
.short_doc
712 redef fun doc
do return global
.intro
.doc
714 redef fun need_doc
(dctx
) do
715 if module == dctx
.module then
716 for m
in dctx
.owned_modules
do
717 if m
.global_classes
.has
(global
) then
719 if c
.need_doc
(dctx
) then return true
726 redef fun locate
(dctx
) do return "in {module.html_link(dctx)}"
728 fun known_intro
(dctx
: DocContext): MMLocalClass do return dctx
.known_owner_of
(global
.intro
.module)[global
]
730 redef fun prototype_head
(dctx
)
733 var ki
= known_intro
(dctx
)
734 var is_redef
= ki
!= self
735 if is_redef
then res
.append
("redef ")
736 if global
.visibility_level
== 3 then res
.append
("private ")
738 if is_redef
then res
.append
("{ki.module.html_link(dctx)}::")
742 redef fun prototype_body
(dctx
)
747 for i
in [0..arity
[ do
748 var t
= get_formal
(i
)
749 res
.append
(t
.name
.to_s
)
751 res
.append
(t
.bound
.html_link
(dctx
))
758 # Extract the doc of a class
759 fun extract_class_doc
(dctx
: DocContext)
761 dctx
.add
("<a name=\"{html_anchor}\
"></a><h2>{self}</h2><small>{module.html_link(dctx)}::</small><br/>{prototype_head(dctx)}<b>{self}</b>{prototype_body(dctx)}\n")
762 dctx
.add
("<blockquote>\n")
765 var sup2
= new Array[String]
766 var intro_module
= dctx
.known_owner_of
(global
.module)
767 if intro_module
!= module then
768 dctx
.add
("<dt>Refine {self} from: <dd>{intro_module.html_link(dctx)}\n")
770 var mods
= new Array[MMModule]
771 for c
in crhe
.greaters
do
772 if c
.need_doc
(dctx
) then
773 var km
= dctx
.known_owner_of
(c
.module)
774 if km
!= module and km
!= intro_module
and not mods
.has
(km
) then
779 for c
in crhe
.linear_extension
do
780 if mods
.has
(c
.module) then sup2
.add
(c
.module.html_link
(dctx
))
782 if not sup2
.is_empty
then dctx
.add
("<dt>Previous refinements in: <dd>{sup2.join(", ")}\n")
784 if not cshe
.greaters
.is_empty
then
786 var clas
= new Array[MMLocalClass]
787 for c
in cshe
.direct_greaters
do
788 sup2
.add
(c
.html_link
(dctx
))
790 dctx
.add
("<dt>Direct superclasses: <dd>{sup2.join(", ")}\n")
792 for c
in cshe
.linear_extension
do
793 if c
!= self then sup2
.add
(c
.html_link
(dctx
))
795 dctx
.add
("<dt>All superclasses: <dd>{sup2.join(", ")}\n")
797 if not cshe
.direct_smallers
.is_empty
then
799 for c
in cshe
.direct_smallers
do
800 sup2
.add
(c
.html_link
(dctx
))
802 dctx
.add
("<dt>Direct subclasses: <dd>{sup2.join(", ")}\n")
805 for c
in crhe
.smallers
do
806 c
.compute_super_classes
807 for c2
in c
.module.local_classes
do
808 if not c2
isa MMConcreteClass then continue
809 c2
.compute_super_classes
811 c2
.inherit_global_properties
813 for c2
in c
.cshe
.direct_smallers
do
814 if c2
.global
.intro
== c2
then
815 sup2
.add
("{c2.html_link(dctx)}")
819 if not sup2
.is_empty
then
820 dctx
.add
("<dt>Other direct subclasses in known modules: <dd>{sup2.join(", ")}\n")
823 for c
in crhe
.order
do
824 if not module.mhe
<= c
.module and c
.need_doc
(dctx
) then
825 sup2
.add
(c
.module.html_link
(dctx
))
828 if not sup2
.is_empty
then
829 dctx
.add
("<dt>Refinements in known modules: <dd>{sup2.join(", ")}\n")
835 dctx
.add
("<pre>{doc.to_html}</pre>\n")
838 var details
= new Array[Array[MMLocalProperty]]
839 for i
in [0..4[ do details
.add
(property_summary
(dctx
, i
))
840 for i
in [0..4[ do property_detail
(dctx
, i
, details
[i
])
842 dctx
.add
("</blockquote><hr/>\n")
845 fun pass_name
(pass
: Int): String
847 var names
= once
["Virtual Types", "Consructors", "Methods", "Attributes"]
851 fun accept_prop
(p
: MMLocalProperty, pass
: Int): Bool
854 return p
isa MMTypeProperty
855 else if pass
== 1 then
856 return p
.global
.is_init
857 else if pass
== 2 then
858 return p
isa MMMethod and not p
.global
.is_init
859 else if pass
== 3 then
860 return p
isa MMAttribute
865 fun property_summary
(dctx
: DocContext, pass
: Int): Array[MMLocalProperty]
867 var passname
= pass_name
(pass
)
869 dctx
.stage
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
870 dctx
.stage
("<tr bgcolor=\"#CCCCFF\"><th colspan=\"2\">{passname} Summary of {self}</th></tr>\n")
872 var new_props
= new Array[MMLocalProperty]
873 for g
in global_properties
do
874 if not accept_prop
(g
.intro
, pass
) then continue
875 if module.visibility_for
(g
.intro
.module) < g
.visibility_level
then continue
877 if p
.local_class
!= self or not p
.need_doc
(dctx
) then
878 var cla
= new Array[MMLocalClass]
879 for m
in dctx
.owned_modules
do
880 if not m
.global_classes
.has
(global
) then continue
882 if not c
isa MMConcreteClass then continue
883 if not c
.has_global_property
(g
) then continue
885 if p2
.local_class
!= c
or not p2
.need_doc
(dctx
) then continue
888 if cla
.is_empty
then continue
889 cla
= crhe
.order
.select_smallests
(cla
)
893 if p
.global
.intro
== p
then
898 for p
in new_props
do
899 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")
901 dctx
.stage
("</table><br/>\n")
904 dctx
.stage
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
906 # skip pass 1 because constructors are not inherited
907 var cmap
= new HashMap[MMLocalClass, Array[MMLocalProperty]]
908 var mmap
= new HashMap[MMModule, Array[MMLocalProperty]]
909 var props
= new Array[MMLocalClass]
910 for c
in che
.greaters
do
911 if c
isa MMSrcLocalClass then
912 var km
= dctx
.known_owner_of
(c
.module)
913 var kc
= km
[c
.global
]
914 if kc
== self then continue
915 var props
: Array[MMLocalProperty]
917 if cmap
.has_key
(kc
) then
920 props
= new Array[MMLocalProperty]
924 if mmap
.has_key
(km
) then
927 props
= new Array[MMLocalProperty]
931 for g
in c
.global_properties
do
933 if p
.local_class
== c
and p
.need_doc
(dctx
) and accept_prop
(p
, pass
) then
940 dctx
.stage
("<tr bgcolor=\"#EEEEFF\"><th colspan=\"2\"><small>Inherited {passname}</small></th><tr>\n")
941 for c
in cshe
.linear_extension
do
942 if not cmap
.has_key
(c
) then continue
944 if props
.is_empty
then continue
946 var properties
= new Array[String]
947 for p
in props
do properties
.add
(p
.html_link
(dctx
))
948 dctx
.add
("<tr><td width=\"20%\
"><small>from {c.html_link(dctx)}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
953 dctx
.stage
("<tr bgcolor=\"#EEEEFF\"><th colspan=\"2\"><small>Imported {passname}</small></th><tr>\n")
954 for m
in module.mhe
.linear_extension
do
955 if not mmap
.has_key
(m
) then continue
957 if props
.is_empty
then continue
959 var properties
= new Array[String]
960 for p
in props
do properties
.add
(p
.html_link
(dctx
))
961 dctx
.add
("<tr><td width=\"20%\
"><small>from {m.html_link(dctx)}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
966 var mmap
= new HashMap[MMModule, Array[MMLocalProperty]]
967 var props
= new Array[MMLocalClass]
968 for c
in crhe
.order
do
969 if module.mhe
<= c
.module or dctx
.owned_modules
.has
(c
.module) or not c
isa MMSrcLocalClass then continue
970 var km
= dctx
.known_owner_of
(c
.module)
971 if module.mhe
<= km
then continue
972 var kc
= km
[c
.global
]
973 var props
: Array[MMLocalProperty]
974 if mmap
.has_key
(km
) then
977 props
= new Array[MMLocalProperty]
980 for g
in c
.global_properties
do
982 if p
.local_class
== c
and p
.need_doc
(dctx
) and accept_prop
(p
, pass
) then
984 if not props
.has
(kp
) then props
.add
(kp
)
987 # c.properties_inherited_from(dctx, self, pass)
990 dctx
.stage
("<tr bgcolor=\"#EEEEFF\"><th colspan=\"2\"><small>Added {passname} in known modules</small></th><tr>\n")
991 for c
in crhe
.order
do
993 if not mmap
.has_key
(m
) then continue
995 if props
.is_empty
then continue
997 var properties
= new Array[String]
998 for p
in props
do properties
.add
(p
.html_link
(dctx
))
999 dctx
.add
("<tr><td width=\"20%\
"><small>in {m.html_link(dctx)}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
1002 dctx
.stage
("</table><br/><br/>\n")
1009 fun property_detail
(dctx
: DocContext, pass
: Int, new_props
: Array[MMLocalProperty])
1011 var passname
= pass_name
(pass
)
1013 dctx
.stage
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
1014 dctx
.stage
("<tr bgcolor=\"#CCCCFF\"><th>{passname} Detail of {self}</th><tr>\n")
1015 dctx
.stage
("</table>\n")
1018 for p
in new_props
do
1019 dctx
.add
("<a name=\"{p.html_anchor}\
"></a><h3>{p}</h3><p><small>{p.module.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")
1020 dctx
.add
("<blockquote>")
1023 dctx
.add
("<pre>{doc.to_html}</pre>\n")
1025 dctx
.stage
("</blockquote>\n")
1029 dctx
.stage
("<hr/>\n")
1036 # Add rows for properties inheriterd to some heirs
1037 fun properties_inherited_from
(dctx
: DocContext, heir
: MMLocalClass, pass
: Int)
1039 var properties
= new Array[String]
1040 for g
in global_properties
do
1042 if p
.local_class
== self and p
.need_doc
(dctx
) and accept_prop
(p
, pass
) then
1043 properties
.add
(p
.html_link
(dctx
))
1046 if not properties
.is_empty
then
1048 if heir
.global
== global
then
1049 s
= module.html_link
(dctx
)
1051 s
= self.html_link
(dctx
)
1053 dctx
.add
("<tr><td width=\"20%\
"><small>in {s}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
1058 redef class MMSrcLocalClass
1064 else if global
.intro
== self then
1067 var bc
= global
.intro
1075 if not n
isa AClassdef then
1078 assert n
isa AClassdef
1084 if d
.n_comment
.is_empty
then
1091 redef fun need_doc
(dctx
)
1093 if global
.visibility_level
>= 3 then
1094 if not dctx
.intrude_mode
then return false
1095 if dctx
.module.visibility_for
(module) == 0 then return false
1097 if global
.intro
== self then
1100 for p
in src_local_properties
do
1101 if p
.need_doc
(dctx
) then
1109 redef class MMSignature
1110 # Htlm transcription of the signature (with nested links)
1111 fun to_html
(dctx
: DocContext): String
1113 var res
= new Buffer
1116 res
.append
(self[0].html_link
(dctx
))
1117 for i
in [1..arity
[ do
1119 res
.append
(self[i
].html_link
(dctx
))
1123 if return_type
!= null then
1125 res
.append
(return_type
.html_link
(dctx
))
1132 # Htlm transcription of the type (with nested links)
1133 fun html_link
(dctx
: DocContext): String do return to_s
1136 redef class MMTypeSimpleClass
1137 redef fun html_link
(dctx
) do return local_class
.html_link
(dctx
)
1140 redef class MMTypeGeneric
1141 redef fun html_link
(dctx
)
1143 var res
= new Buffer
1144 res
.append
(local_class
.html_link
(dctx
))
1146 res
.append
(params
[0].html_link
(dctx
))
1147 for i
in [1..params
.length
[ do
1149 res
.append
(params
[i
].html_link
(dctx
))
1156 var c
= new DocContext