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 var f
= new OFStream.open
(filename
)
62 for s
in _stage_context
.content
do
68 # Currently computed module
69 readable var _module
: 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)
84 if e
isa MMSrcModule then
92 _stage_context
= new StageContext(null)
95 # Generate common files (frames, index, overview)
98 info
("Generating other files",1)
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)
524 dctx
.info
("Generating HTML for module {name}",1)
528 extract_module_doc_inside
(dctx
)
529 dctx
.write_to
("{dctx.dir}/{name}.html")
531 dctx
.intrude_mode
= true
533 extract_module_doc_inside
(dctx
)
534 dctx
.write_to
("{dctx.dir}/{name}__.html")
535 dctx
.intrude_mode
= false
537 if directory
.owner
== self then
538 dctx
.inside_mode
= true
540 extract_module_doc_inside
(dctx
)
541 dctx
.write_to
("{dctx.dir}/{name}_.html")
542 dctx
.inside_mode
= false
546 fun extract_module_doc_inside
(dctx
: DocContext)
548 dctx
.add_header
("Module {self}")
549 dctx
.add
("<h1>Module {self}</h1>\n<dl>")
551 var d
: nullable MMDirectory = directory
553 if d
.owner
!= null and (d
.owner
!= self or dctx
.inside_mode
or dctx
.intrude_mode
) then
554 s
= "{d.owner.html_link(dctx)}::{s}"
558 dctx
.add
("{s}<br/>{prototype_head(dctx)}<b>{self}</b>{prototype_body(dctx)}<br/>\n")
560 var strs
= new Array[String]
561 var intrude_modules
= new Array[MMModule]
562 var public_modules
= new Array[MMModule]
563 var private_modules
= new Array[MMModule]
564 var owned_modules
= dctx
.owned_modules
566 for m
in mhe
.greaters
do
567 var v
= visibility_for
(m
)
568 if not dctx
.inside_mode
and not dctx
.intrude_mode
and m
.directory
.owner
== self then
569 if v
>= 2 then owned_modules
.add
(m
)
573 intrude_modules
.add
(m
)
575 public_modules
.add
(m
)
577 private_modules
.add
(m
)
580 if not intrude_modules
.is_empty
then
581 var mods
= mhe
.order
.select_smallests
(intrude_modules
)
582 for i
in mods
do strs
.add
(i
.html_link
(dctx
))
583 dctx
.add
("<dt>Intruded modules: <dd>{strs.join(", ")}\n")
585 if not public_modules
.is_empty
then
587 var mods
= mhe
.order
.select_smallests
(public_modules
)
588 for i
in mods
do strs
.add
(i
.html_link
(dctx
))
589 dctx
.add
("<dt>Imported modules: <dd>{strs.join(", ")}\n")
591 if not private_modules
.is_empty
then
593 var mods
= mhe
.order
.select_smallests
(private_modules
)
594 for i
in mods
do strs
.add
(i
.html_link
(dctx
))
595 dctx
.add
("<dt>Privatly imported modules: <dd>{strs.join(", ")}\n")
600 if doc
!= null then dctx
.add
("<pre>{doc.to_html}</pre>\n")
602 var new_classes
= new Array[MMLocalClass]
603 for c
in local_classes
do
604 if c
.need_doc
(dctx
) then
606 if c
.global
.intro
== c
then
610 for m
in owned_modules
do
611 if m
.global_classes
.has
(c
.global
) then
613 if mc
.need_doc
(dctx
) then
622 if not new_classes
.is_empty
then
623 dctx
.sort
(new_classes
)
624 dctx
.add
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
625 dctx
.add
("<tr bgcolor=\"#CCCCFF\"><th colspan=\"2\"><big>Class Summary of {self}</big></th><tr>\n")
626 for c
in new_classes
do
627 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")
629 dctx
.add
("</table><br/>\n")
632 if not new_classes
.is_empty
then
633 dctx
.add
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
634 dctx
.add
("<tr bgcolor=\"#CCCCFF\"><th><big>Class Detail of {self}</big></th><tr>\n")
635 dctx
.add
("</table>\n")
637 for c
in new_classes
do
638 c
.extract_class_doc
(dctx
)
642 dctx
.add
("</body></html>\n")
658 if n
.n_packagedecl
== null then
661 var np
= n
.n_packagedecl
662 assert np
isa APackagedecl
668 if d
.n_comment
.is_empty
then
677 # Html transcription of the doc
681 for c
in n_comment
do
682 res
.append
(c
.text
.substring_from
(1))
687 # Oneliner transcription of the doc
690 return n_comment
.first
.text
.substring_from
(1)
694 redef class MMLocalClass
696 # Anchor of the class description in the module html file
697 fun html_anchor
: String do return "CLASS_{self}"
699 redef fun html_link
(dctx
)
702 if not need_doc
(dctx
) then m
= global
.module
703 var m
= dctx
.known_owner_of
(m
)
704 if m
== dctx
.module then
705 return "<a href=\"#{html_anchor}\">{self}</a>"
707 return "<a href=\"{m}.html
#{html_anchor}\">{self}</a>"
711 redef fun short_doc
do return global
.intro
.short_doc
713 redef fun doc
do return global
.intro
.doc
715 redef fun need_doc
(dctx
) do
716 if module == dctx
.module then
717 for m
in dctx
.owned_modules
do
718 if m
.global_classes
.has
(global
) then
720 if c
.need_doc
(dctx
) then return true
727 redef fun locate
(dctx
) do return "in {module.html_link(dctx)}"
729 fun known_intro
(dctx
: DocContext): MMLocalClass do return dctx
.known_owner_of
(global
.intro
.module)[global
]
731 redef fun prototype_head
(dctx
)
734 var ki
= known_intro
(dctx
)
735 var is_redef
= ki
!= self
736 if is_redef
then res
.append
("redef ")
737 if global
.visibility_level
== 3 then res
.append
("private ")
739 if is_redef
then res
.append
("{ki.module.html_link(dctx)}::")
743 redef fun prototype_body
(dctx
)
748 for i
in [0..arity
[ do
749 var t
= get_formal
(i
)
750 res
.append
(t
.name
.to_s
)
752 res
.append
(t
.bound
.html_link
(dctx
))
759 # Extract the doc of a class
760 fun extract_class_doc
(dctx
: DocContext)
762 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")
763 dctx
.add
("<blockquote>\n")
766 var sup2
= new Array[String]
767 var intro_module
= dctx
.known_owner_of
(global
.module)
768 if intro_module
!= module then
769 dctx
.add
("<dt>Refine {self} from: <dd>{intro_module.html_link(dctx)}\n")
771 var mods
= new Array[MMModule]
772 for c
in crhe
.greaters
do
773 if c
.need_doc
(dctx
) then
774 var km
= dctx
.known_owner_of
(c
.module)
775 if km
!= module and km
!= intro_module
and not mods
.has
(km
) then
780 for c
in crhe
.linear_extension
do
781 if mods
.has
(c
.module) then sup2
.add
(c
.module.html_link
(dctx
))
783 if not sup2
.is_empty
then dctx
.add
("<dt>Previous refinements in: <dd>{sup2.join(", ")}\n")
785 if not cshe
.greaters
.is_empty
then
787 var clas
= new Array[MMLocalClass]
788 for c
in cshe
.direct_greaters
do
789 sup2
.add
(c
.html_link
(dctx
))
791 dctx
.add
("<dt>Direct superclasses: <dd>{sup2.join(", ")}\n")
793 for c
in cshe
.linear_extension
do
794 if c
!= self then sup2
.add
(c
.html_link
(dctx
))
796 dctx
.add
("<dt>All superclasses: <dd>{sup2.join(", ")}\n")
798 if not cshe
.direct_smallers
.is_empty
then
800 for c
in cshe
.direct_smallers
do
801 sup2
.add
(c
.html_link
(dctx
))
803 dctx
.add
("<dt>Direct subclasses: <dd>{sup2.join(", ")}\n")
806 for c
in crhe
.smallers
do
807 c
.compute_super_classes
808 for c2
in c
.module.local_classes
do
809 if not c2
isa MMConcreteClass then continue
810 c2
.compute_super_classes
812 c2
.inherit_global_properties
814 for c2
in c
.cshe
.direct_smallers
do
815 if c2
.global
.intro
== c2
then
816 sup2
.add
("{c2.html_link(dctx)}")
820 if not sup2
.is_empty
then
821 dctx
.add
("<dt>Other direct subclasses in known modules: <dd>{sup2.join(", ")}\n")
824 for c
in crhe
.order
do
825 if not module.mhe
<= c
.module and c
.need_doc
(dctx
) then
826 sup2
.add
(c
.module.html_link
(dctx
))
829 if not sup2
.is_empty
then
830 dctx
.add
("<dt>Refinements in known modules: <dd>{sup2.join(", ")}\n")
836 dctx
.add
("<pre>{doc.to_html}</pre>\n")
839 var details
= new Array[Array[MMLocalProperty]]
840 for i
in [0..4[ do details
.add
(property_summary
(dctx
, i
))
841 for i
in [0..4[ do property_detail
(dctx
, i
, details
[i
])
843 dctx
.add
("</blockquote><hr/>\n")
846 fun pass_name
(pass
: Int): String
848 var names
= once
["Virtual Types", "Consructors", "Methods", "Attributes"]
852 fun accept_prop
(p
: MMLocalProperty, pass
: Int): Bool
855 return p
isa MMTypeProperty
856 else if pass
== 1 then
857 return p
.global
.is_init
858 else if pass
== 2 then
859 return p
isa MMMethod and not p
.global
.is_init
860 else if pass
== 3 then
861 return p
isa MMAttribute
866 fun property_summary
(dctx
: DocContext, pass
: Int): Array[MMLocalProperty]
868 var passname
= pass_name
(pass
)
870 dctx
.stage
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
871 dctx
.stage
("<tr bgcolor=\"#CCCCFF\"><th colspan=\"2\">{passname} Summary of {self}</th></tr>\n")
873 var new_props
= new Array[MMLocalProperty]
874 for g
in global_properties
do
875 if not accept_prop
(g
.intro
, pass
) then continue
876 if module.visibility_for
(g
.intro
.module) < g
.visibility_level
then continue
878 if p
.local_class
!= self or not p
.need_doc
(dctx
) then
879 var cla
= new Array[MMLocalClass]
880 for m
in dctx
.owned_modules
do
881 if not m
.global_classes
.has
(global
) then continue
883 if not c
isa MMConcreteClass then continue
884 if not c
.has_global_property
(g
) then continue
886 if p2
.local_class
!= c
or not p2
.need_doc
(dctx
) then continue
889 if cla
.is_empty
then continue
890 cla
= crhe
.order
.select_smallests
(cla
)
894 if p
.global
.intro
== p
then
899 for p
in new_props
do
900 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")
902 dctx
.stage
("</table><br/>\n")
905 dctx
.stage
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
907 # skip pass 1 because constructors are not inherited
908 var cmap
= new HashMap[MMLocalClass, Array[MMLocalProperty]]
909 var mmap
= new HashMap[MMModule, Array[MMLocalProperty]]
910 var props
= new Array[MMLocalClass]
911 for c
in che
.greaters
do
912 if c
isa MMSrcLocalClass then
913 var km
= dctx
.known_owner_of
(c
.module)
914 var kc
= km
[c
.global
]
915 if kc
== self then continue
916 var props
: Array[MMLocalProperty]
918 if cmap
.has_key
(kc
) then
921 props
= new Array[MMLocalProperty]
925 if mmap
.has_key
(km
) then
928 props
= new Array[MMLocalProperty]
932 for g
in c
.global_properties
do
934 if p
.local_class
== c
and p
.need_doc
(dctx
) and accept_prop
(p
, pass
) then
941 dctx
.stage
("<tr bgcolor=\"#EEEEFF\"><th colspan=\"2\"><small>Inherited {passname}</small></th><tr>\n")
942 for c
in cshe
.linear_extension
do
943 if not cmap
.has_key
(c
) then continue
945 if props
.is_empty
then continue
947 var properties
= new Array[String]
948 for p
in props
do properties
.add
(p
.html_link
(dctx
))
949 dctx
.add
("<tr><td width=\"20%\
"><small>from {c.html_link(dctx)}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
954 dctx
.stage
("<tr bgcolor=\"#EEEEFF\"><th colspan=\"2\"><small>Imported {passname}</small></th><tr>\n")
955 for m
in module.mhe
.linear_extension
do
956 if not mmap
.has_key
(m
) then continue
958 if props
.is_empty
then continue
960 var properties
= new Array[String]
961 for p
in props
do properties
.add
(p
.html_link
(dctx
))
962 dctx
.add
("<tr><td width=\"20%\
"><small>from {m.html_link(dctx)}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
967 var mmap
= new HashMap[MMModule, Array[MMLocalProperty]]
968 var props
= new Array[MMLocalClass]
969 for c
in crhe
.order
do
970 if module.mhe
<= c
.module or dctx
.owned_modules
.has
(c
.module) or not c
isa MMSrcLocalClass then continue
971 var km
= dctx
.known_owner_of
(c
.module)
972 if module.mhe
<= km
then continue
973 var kc
= km
[c
.global
]
974 var props
: Array[MMLocalProperty]
975 if mmap
.has_key
(km
) then
978 props
= new Array[MMLocalProperty]
981 for g
in c
.global_properties
do
983 if p
.local_class
== c
and p
.need_doc
(dctx
) and accept_prop
(p
, pass
) then
985 if not props
.has
(kp
) then props
.add
(kp
)
988 # c.properties_inherited_from(dctx, self, pass)
991 dctx
.stage
("<tr bgcolor=\"#EEEEFF\"><th colspan=\"2\"><small>Added {passname} in known modules</small></th><tr>\n")
992 for c
in crhe
.order
do
994 if not mmap
.has_key
(m
) then continue
996 if props
.is_empty
then continue
998 var properties
= new Array[String]
999 for p
in props
do properties
.add
(p
.html_link
(dctx
))
1000 dctx
.add
("<tr><td width=\"20%\
"><small>in {m.html_link(dctx)}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
1003 dctx
.stage
("</table><br/><br/>\n")
1010 fun property_detail
(dctx
: DocContext, pass
: Int, new_props
: Array[MMLocalProperty])
1012 var passname
= pass_name
(pass
)
1014 dctx
.stage
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
1015 dctx
.stage
("<tr bgcolor=\"#CCCCFF\"><th>{passname} Detail of {self}</th><tr>\n")
1016 dctx
.stage
("</table>\n")
1019 for p
in new_props
do
1020 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")
1021 dctx
.add
("<blockquote>")
1024 dctx
.add
("<pre>{doc.to_html}</pre>\n")
1026 dctx
.stage
("</blockquote>\n")
1030 dctx
.stage
("<hr/>\n")
1037 # Add rows for properties inheriterd to some heirs
1038 fun properties_inherited_from
(dctx
: DocContext, heir
: MMLocalClass, pass
: Int)
1040 var properties
= new Array[String]
1041 for g
in global_properties
do
1043 if p
.local_class
== self and p
.need_doc
(dctx
) and accept_prop
(p
, pass
) then
1044 properties
.add
(p
.html_link
(dctx
))
1047 if not properties
.is_empty
then
1049 if heir
.global
== global
then
1050 s
= module.html_link
(dctx
)
1052 s
= self.html_link
(dctx
)
1054 dctx
.add
("<tr><td width=\"20%\
"><small>in {s}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
1059 redef class MMSrcLocalClass
1065 else if global
.intro
== self then
1068 var bc
= global
.intro
1076 if not n
isa AClassdef then
1079 assert n
isa AClassdef
1085 if d
.n_comment
.is_empty
then
1092 redef fun need_doc
(dctx
)
1094 if global
.visibility_level
>= 3 then
1095 if not dctx
.intrude_mode
then return false
1096 if dctx
.module.visibility_for
(module) == 0 then return false
1098 if global
.intro
== self then
1101 for p
in src_local_properties
do
1102 if p
.need_doc
(dctx
) then
1110 redef class MMSignature
1111 # Htlm transcription of the signature (with nested links)
1112 fun to_html
(dctx
: DocContext): String
1114 var res
= new Buffer
1117 res
.append
(self[0].html_link
(dctx
))
1118 for i
in [1..arity
[ do
1120 res
.append
(self[i
].html_link
(dctx
))
1124 if return_type
!= null then
1126 res
.append
(return_type
.html_link
(dctx
))
1133 # Htlm transcription of the type (with nested links)
1134 fun html_link
(dctx
: DocContext): String do return to_s
1137 redef class MMTypeSimpleClass
1138 redef fun html_link
(dctx
) do return local_class
.html_link
(dctx
)
1141 redef class MMTypeGeneric
1142 redef fun html_link
(dctx
)
1144 var res
= new Buffer
1145 res
.append
(local_class
.html_link
(dctx
))
1147 res
.append
(params
[0].html_link
(dctx
))
1148 for i
in [1..params
.length
[ do
1150 res
.append
(params
[i
].html_link
(dctx
))
1157 var c
= new DocContext