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")
172 add
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
173 add
("<tr bgcolor=\"#CCCCFF\"><th colspan=\"2\"><big>Overview of all Modules</big></th><tr>\n")
175 add
("<tr><td width=\"20%\
" align=\"right\
">{m.html_link(self)}</td><td>{m.short_doc}</td><tr>\n")
177 add
("</table></body></html>\n")
178 write_to
("{dir}/overview.html")
181 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")
182 write_to
("{dir}/index.html")
185 fun add_header
(title
: String)
187 add
("<html><head><title>{title}</title></head>\n<body>\n")
188 add
("<table border=\"0\
" width=\"100%\
" cellpadding=\"1\
" cellspacing=\"0\
"><tr><td bgcolor=\"#eeeeff\">\n")
189 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")
190 add
("</td></tr></table>")
193 if (not inside_mode
and not intrude_mode
) or mod
== null then
194 add
("<b>Public</b> ")
196 add
("<a href=\"{mod}.html\
"><b>Public</b></a> ")
198 if inside_mode
or mod
== null then
199 add
("<b>Inside</b> ")
200 else if mod
.directory
.owner
!= mod
then
201 add
("<strike><b>Inside</b></strike> ")
203 add
("<a href=\"{mod}_
.html\
"><b>Inside</b></a> ")
205 if intrude_mode
or mod
== null then
206 add
("<b>Intrude</b> ")
208 add
("<a href=\"{mod}__
.html\
"><b>Intrude</b></a> ")
213 # Sorter of entities in alphabetical order
214 var _sorter
: AlphaSorter[MMEntity] = new AlphaSorter[MMEntity]
216 # Sort entities in the alphabetical order
217 fun sort
(array
: Array[MMEntity])
222 readable writable var _owned_modules
: Array[MMModule] = new Array[MMModule]
224 # Return the known_owner for current module
225 # if inside_mode is set, it could be a different result
226 fun known_owner_of
(m
: MMModule): MMModule
229 if mod
== null then return m
230 var res
= mod
.known_owner_of
(m
)
231 if not inside_mode
and not intrude_mode
and res
.directory
.owner
== mod
then
238 readable var _opt_dir
: OptionString = new OptionString("Directory where doc is generated", "-d", "--dir")
240 redef fun perform_work
(mods
)
244 for mod
in modules
do
245 assert mod
isa MMSrcModule
246 mod
.extract_module_doc
(self)
248 self.extract_other_doc
255 option_context
.add_option
(opt_dir
)
258 redef fun process_options
261 var d
= opt_dir
.value
262 if d
!= null then dir
= d
266 # Conditionnal part of the text content of a DocContext
268 # Content of the current stage
269 readable var _content
: Array[String] = new Array[String]
271 # Is a normal string already added?
272 readable writable var _validate
: Bool = false
274 # Parent stage is any
275 readable var _parent
: nullable StageContext = null
277 init(parent
: nullable StageContext) do _parent
= parent
281 # Efficiently sort object with their to_s method
282 class AlphaSorter[E
: Object]
283 super AbstractSorter[E
]
284 redef fun compare
(a
, b
)
304 # Keep track of to_s values
305 var _dico
: HashMap[Object, String] = new HashMap[Object, String]
310 # Generalization of metamodel entities
313 fun html_link
(dctx
: DocContext): String is abstract
315 # Is the entity should appear in the generaed doc
316 fun need_doc
(dctx
: DocContext): Bool is abstract
318 # Return a one liner description
319 fun short_doc
: String do return " "
321 # The doc node from the AST
322 # Return null is none
323 fun doc
: nullable ADoc do return null
325 # Human redable location of the entity (module/class/property)
326 fun locate
(dctx
: DocContext): String do return ""
328 # Part of the prototype before the name (kind, modifiers, qualifier)
329 fun prototype_head
(dctx
: DocContext): String is abstract
331 # Part of the property after the name (signature, modifiers)
332 fun prototype_body
(dctx
: DocContext): String do return ""
337 redef fun html_link
(dctx
) do
338 if dctx
.mmmodule
== self then
341 return "<a href=\"{self}.html\
">{self}</a>"
344 redef fun need_doc
(dctx
) do return true
345 redef fun prototype_head
(dctx
) do return "module "
347 var _known_owner_of_cache
: Map[MMModule, MMModule] = new HashMap[MMModule, MMModule]
349 # Return the owner of `module` from the point of view of `self`
350 fun known_owner_of
(mod
: MMModule): MMModule
352 if _known_owner_of_cache
.has_key
(mod
) then return _known_owner_of_cache
[mod
]
354 # is module is publicly imported by self?
355 if mhe
< mod
and visibility_for
(mod
) != 0 then
356 res
= known_owner_of_intern
(mod
, self, false)
358 # Return the canonnical owner of module from the point of view of self
359 res
= mod
.owner
(self)
361 _known_owner_of_cache
[mod
] = res
365 # Return the most general module that own self
366 fun owner
(from
: MMModule): MMModule
369 var d
: nullable MMDirectory = directory
370 while d
!= null and d
!= from
.directory
do
372 if o
!= null and o
.mhe
<= res
then res
= o
379 private fun known_owner_of_intern
(mod
: MMModule, from
: MMModule, as_owner
: Bool): MMModule
381 if mod
== self then return self
382 var candidates
= new Array[MMModule]
383 for m
in explicit_imported_modules
do
384 if from
.visibility_for
(m
) == 0 then continue
385 if not m
.mhe
<= mod
then continue
386 candidates
.add
(m
.known_owner_of_intern
(mod
, from
, true))
388 # FIXME: I do not know what this does
389 if candidates
.is_empty
then return mod
.owner
(from
)
390 var max
= candidates
.first
391 for m
in candidates
do
392 if max
.mhe
< m
then max
= m
394 if as_owner
and max
.directory
.owner
== self then
403 redef class MMLocalProperty
405 # Anchor of the property description in the module html file
406 fun html_anchor
: String
408 return "PROP_{local_class}_{cmangle(name)}"
411 redef fun html_link
(dctx
)
414 if not need_doc
(dctx
) then m
= global
.intro
.mmmodule
415 m
= dctx
.known_owner_of
(m
)
416 if m
== dctx
.mmmodule
then
417 return "<a href=\"#{html_anchor}\">{self}</a>"
419 return "<a href=\"{m}.html
#{html_anchor}\">{self}</a>"
423 # Kind of property (fun, attr, etc.)
424 fun kind
: String is abstract
426 redef fun locate
(dctx
)
428 return "in {mmmodule.html_link(dctx)}::{local_class.html_link(dctx)}"
431 fun known_intro_class
(dctx
: DocContext): MMLocalClass
433 var mod
= dctx
.known_owner_of
(global
.intro
.local_class
.mmmodule
)
434 var cla
= mod
[global
.intro
.local_class
.global
]
438 redef fun prototype_head
(dctx
)
441 var intro_class
= known_intro_class
(dctx
)
442 var is_redef
= local_class
!= intro_class
444 if is_redef
then res
.append
("redef ")
445 if global
.visibility_level
== 2 then
446 res
.append
("protected ")
447 else if global
.visibility_level
== 3 then
448 res
.append
("private ")
452 var gp
= global
.intro
453 if intro_class
.global
!= local_class
.global
then
454 res
.append
(" {mmmodule[intro_class.global].html_link(dctx)}::")
455 else if intro_class
.mmmodule
!= mmmodule
then
456 res
.append
(" {intro_class.mmmodule.html_link(dctx)}::")
462 redef fun prototype_body
(dctx
)
465 res
.append
(signature
.to_html
(dctx
, true))
467 if s
isa MMMethod then
468 if s
.is_abstract
then
469 res
.append
(" is abstract")
470 else if s
.is_intern
then
471 res
.append
(" is intern")
477 redef fun need_doc
(dctx
)
479 if global
.visibility_level
>= 3 or self isa MMAttribute then
480 if not dctx
.intrude_mode
then return false
481 if dctx
.mmmodule
.visibility_for
(mmmodule
) == 0 then return false
483 if global
.intro
== self then
494 else if global
.intro
== self then
497 return global
.intro
.short_doc
504 if n
== null or not n
isa APropdef then
511 if d
.n_comment
.is_empty
then
519 redef fun kind
do return if global
.is_init
then "init" else "fun"
521 redef class MMAttribute
522 redef fun kind
do return "var"
524 redef class MMTypeProperty
525 redef fun kind
do return "type"
528 redef class MMSrcModule
529 # Extract and generate html file for the module
530 fun extract_module_doc
(dctx
: DocContext)
532 dctx
.info
("Generating HTML for module {name}",1)
536 extract_module_doc_inside
(dctx
)
537 dctx
.write_to
("{dctx.dir}/{name}.html")
539 dctx
.intrude_mode
= true
541 extract_module_doc_inside
(dctx
)
542 dctx
.write_to
("{dctx.dir}/{name}__.html")
543 dctx
.intrude_mode
= false
545 if directory
.owner
== self then
546 dctx
.inside_mode
= true
548 extract_module_doc_inside
(dctx
)
549 dctx
.write_to
("{dctx.dir}/{name}_.html")
550 dctx
.inside_mode
= false
554 fun extract_module_doc_inside
(dctx
: DocContext)
556 dctx
.add_header
("Module {self}")
557 dctx
.add
("<h1>Module {self}</h1>\n<dl>")
559 var d
: nullable MMDirectory = directory
561 if d
.owner
!= null and (d
.owner
!= self or dctx
.inside_mode
or dctx
.intrude_mode
) then
562 s
= "{d.owner.html_link(dctx)}::{s}"
566 dctx
.add
("{s}<br/>{prototype_head(dctx)}<b>{self}</b>{prototype_body(dctx)}<br/>\n")
568 var strs
= new Array[String]
569 var intrude_modules
= new Array[MMModule]
570 var public_modules
= new Array[MMModule]
571 var private_modules
= new Array[MMModule]
572 var owned_modules
= dctx
.owned_modules
574 for m
in mhe
.greaters
do
575 var v
= visibility_for
(m
)
576 if not dctx
.inside_mode
and not dctx
.intrude_mode
and m
.directory
.owner
== self then
577 if v
>= 2 then owned_modules
.add
(m
)
581 intrude_modules
.add
(m
)
583 public_modules
.add
(m
)
585 private_modules
.add
(m
)
588 if not intrude_modules
.is_empty
then
589 var mods
= mhe
.order
.select_smallests
(intrude_modules
)
590 for i
in mods
do strs
.add
(i
.html_link
(dctx
))
591 dctx
.add
("<dt>Intruded modules: <dd>{strs.join(", ")}\n")
593 if not public_modules
.is_empty
then
595 var mods
= mhe
.order
.select_smallests
(public_modules
)
596 for i
in mods
do strs
.add
(i
.html_link
(dctx
))
597 dctx
.add
("<dt>Imported modules: <dd>{strs.join(", ")}\n")
599 if not private_modules
.is_empty
then
601 var mods
= mhe
.order
.select_smallests
(private_modules
)
602 for i
in mods
do strs
.add
(i
.html_link
(dctx
))
603 dctx
.add
("<dt>Privatly imported modules: <dd>{strs.join(", ")}\n")
608 if doc
!= null then dctx
.add
("<pre>{doc.to_html}</pre>\n")
610 var new_classes
= new Array[MMLocalClass]
611 for c
in local_classes
do
612 if c
.need_doc
(dctx
) then
614 if c
.global
.intro
== c
then
618 for m
in owned_modules
do
619 if m
.global_classes
.has
(c
.global
) then
621 if mc
.need_doc
(dctx
) then
630 if not new_classes
.is_empty
then
631 dctx
.sort
(new_classes
)
632 dctx
.add
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
633 dctx
.add
("<tr bgcolor=\"#CCCCFF\"><th colspan=\"2\"><big>Class Summary of {self}</big></th><tr>\n")
634 for c
in new_classes
do
635 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")
637 dctx
.add
("</table><br/>\n")
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=\"#CCCCFF\"><th><big>Class Detail of {self}</big></th><tr>\n")
643 dctx
.add
("</table>\n")
645 for c
in new_classes
do
646 c
.extract_class_doc
(dctx
)
650 dctx
.add
("</body></html>\n")
666 if n
.n_moduledecl
== null then
669 var np
= n
.n_moduledecl
674 if d
.n_comment
.is_empty
then
683 # Html transcription of the doc
687 for c
in n_comment
do
688 res
.append
(c
.text
.substring_from
(1))
693 # Oneliner transcription of the doc
696 return n_comment
.first
.text
.substring_from
(1)
700 redef class MMLocalClass
702 # Anchor of the class description in the module html file
703 fun html_anchor
: String do return "CLASS_{self}"
705 redef fun html_link
(dctx
)
708 if not need_doc
(dctx
) then m
= global
.mmmodule
709 m
= dctx
.known_owner_of
(m
)
710 if m
== dctx
.mmmodule
then
711 return "<a href=\"#{html_anchor}\">{self}</a>"
713 return "<a href=\"{m}.html
#{html_anchor}\">{self}</a>"
717 redef fun short_doc
do return global
.intro
.short_doc
719 redef fun doc
do return global
.intro
.doc
721 redef fun need_doc
(dctx
) do
722 if mmmodule
== dctx
.mmmodule
then
723 for m
in dctx
.owned_modules
do
724 if m
.global_classes
.has
(global
) then
726 if c
.need_doc
(dctx
) then return true
733 redef fun locate
(dctx
) do return "in {mmmodule.html_link(dctx)}"
735 fun known_intro
(dctx
: DocContext): MMLocalClass do return dctx
.known_owner_of
(global
.intro
.mmmodule
)[global
]
737 redef fun prototype_head
(dctx
)
740 var ki
= known_intro
(dctx
)
741 var is_redef
= ki
!= self
742 if is_redef
then res
.append
("redef ")
743 if global
.visibility_level
== 3 then res
.append
("private ")
745 if is_redef
then res
.append
("{ki.mmmodule.html_link(dctx)}::")
749 redef fun prototype_body
(dctx
)
754 for i
in [0..arity
[ do
755 var t
= get_formal
(i
)
756 res
.append
(t
.name
.to_s
)
758 res
.append
(t
.bound
.html_link
(dctx
))
765 # Extract the doc of a class
766 fun extract_class_doc
(dctx
: DocContext)
768 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")
769 dctx
.add
("<blockquote>\n")
772 var sup2
= new Array[String]
773 var intro_module
= dctx
.known_owner_of
(global
.mmmodule
)
774 if intro_module
!= mmmodule
then
775 dctx
.add
("<dt>Refine {self} from: <dd>{intro_module.html_link(dctx)}\n")
777 var mods
= new Array[MMModule]
778 for c
in crhe
.greaters
do
779 if c
.need_doc
(dctx
) then
780 var km
= dctx
.known_owner_of
(c
.mmmodule
)
781 if km
!= mmmodule
and km
!= intro_module
and not mods
.has
(km
) then
786 for c
in crhe
.linear_extension
do
787 if mods
.has
(c
.mmmodule
) then sup2
.add
(c
.mmmodule
.html_link
(dctx
))
789 if not sup2
.is_empty
then dctx
.add
("<dt>Previous refinements in: <dd>{sup2.join(", ")}\n")
791 if not cshe
.greaters
.is_empty
then
793 var clas
= new Array[MMLocalClass]
794 for c
in cshe
.direct_greaters
do
795 sup2
.add
(c
.html_link
(dctx
))
797 dctx
.add
("<dt>Direct superclasses: <dd>{sup2.join(", ")}\n")
799 for c
in cshe
.linear_extension
do
800 if c
!= self then sup2
.add
(c
.html_link
(dctx
))
802 dctx
.add
("<dt>All superclasses: <dd>{sup2.join(", ")}\n")
804 if not cshe
.direct_smallers
.is_empty
then
806 for c
in cshe
.direct_smallers
do
807 sup2
.add
(c
.html_link
(dctx
))
809 dctx
.add
("<dt>Direct subclasses: <dd>{sup2.join(", ")}\n")
812 for c
in crhe
.smallers
do
813 c
.compute_super_classes
814 for c2
in c
.mmmodule
.local_classes
do
815 if not c2
isa MMConcreteClass then continue
816 c2
.compute_super_classes
819 for c2
in c
.cshe
.direct_smallers
do
820 if c2
.global
.intro
== c2
then
821 sup2
.add
("{c2.html_link(dctx)}")
825 if not sup2
.is_empty
then
826 dctx
.add
("<dt>Other direct subclasses in known modules: <dd>{sup2.join(", ")}\n")
829 for c
in crhe
.order
do
830 if not mmmodule
.mhe
<= c
.mmmodule
and c
.need_doc
(dctx
) then
831 sup2
.add
(c
.mmmodule
.html_link
(dctx
))
834 if not sup2
.is_empty
then
835 dctx
.add
("<dt>Refinements in known modules: <dd>{sup2.join(", ")}\n")
841 dctx
.add
("<pre>{doc.to_html}</pre>\n")
844 var details
= new Array[Array[MMLocalProperty]]
845 for i
in [0..4[ do details
.add
(property_summary
(dctx
, i
))
846 for i
in [0..4[ do property_detail
(dctx
, i
, details
[i
])
848 dctx
.add
("</blockquote><hr/>\n")
851 fun pass_name
(pass
: Int): String
853 var names
= once
["Virtual Types", "Consructors", "Methods", "Attributes"]
857 fun accept_prop
(p
: MMLocalProperty, pass
: Int): Bool
860 return p
isa MMTypeProperty
861 else if pass
== 1 then
862 return p
.global
.is_init
863 else if pass
== 2 then
864 return p
isa MMMethod and not p
.global
.is_init
865 else if pass
== 3 then
866 return p
isa MMAttribute
871 fun property_summary
(dctx
: DocContext, pass
: Int): Array[MMLocalProperty]
873 var passname
= pass_name
(pass
)
875 dctx
.stage
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
876 dctx
.stage
("<tr bgcolor=\"#CCCCFF\"><th colspan=\"2\">{passname} Summary of {self}</th></tr>\n")
878 var new_props
= new Array[MMLocalProperty]
879 for g
in global_properties
do
880 if not accept_prop
(g
.intro
, pass
) then continue
881 if mmmodule
.visibility_for
(g
.intro
.mmmodule
) < g
.visibility_level
then continue
883 if p
.local_class
!= self or not p
.need_doc
(dctx
) then
884 var cla
= new Array[MMLocalClass]
885 for m
in dctx
.owned_modules
do
886 if not m
.global_classes
.has
(global
) then continue
888 if not c
isa MMConcreteClass then continue
889 if not c
.has_global_property
(g
) then continue
891 if p2
.local_class
!= c
or not p2
.need_doc
(dctx
) then continue
894 if cla
.is_empty
then continue
895 cla
= crhe
.order
.select_smallests
(cla
)
899 if p
.global
.intro
== p
then
904 for p
in new_props
do
905 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")
907 dctx
.stage
("</table><br/>\n")
910 dctx
.stage
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
912 # skip pass 1 because constructors are not inherited
913 var cmap
= new HashMap[MMLocalClass, Array[MMLocalProperty]]
914 var mmap
= new HashMap[MMModule, Array[MMLocalProperty]]
915 for c
in che
.greaters
do
916 if c
isa MMSrcLocalClass then
917 var km
= dctx
.known_owner_of
(c
.mmmodule
)
918 var kc
= km
[c
.global
]
919 if kc
== self then continue
920 var props
: Array[MMLocalProperty]
921 if km
== mmmodule
then
922 if cmap
.has_key
(kc
) then
925 props
= new Array[MMLocalProperty]
929 if mmap
.has_key
(km
) then
932 props
= new Array[MMLocalProperty]
936 for g
in c
.global_properties
do
938 if p
.local_class
== c
and p
.need_doc
(dctx
) and accept_prop
(p
, pass
) then
945 dctx
.stage
("<tr bgcolor=\"#EEEEFF\"><th colspan=\"2\"><small>Inherited {passname}</small></th><tr>\n")
946 for c
in cshe
.linear_extension
do
947 if not cmap
.has_key
(c
) then continue
949 if props
.is_empty
then continue
951 var properties
= new Array[String]
952 for p
in props
do properties
.add
(p
.html_link
(dctx
))
953 dctx
.add
("<tr><td width=\"20%\
"><small>from {c.html_link(dctx)}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
958 dctx
.stage
("<tr bgcolor=\"#EEEEFF\"><th colspan=\"2\"><small>Imported {passname}</small></th><tr>\n")
959 for m
in mmmodule
.mhe
.linear_extension
do
960 if not mmap
.has_key
(m
) then continue
962 if props
.is_empty
then continue
964 var properties
= new Array[String]
965 for p
in props
do properties
.add
(p
.html_link
(dctx
))
966 dctx
.add
("<tr><td width=\"20%\
"><small>from {m.html_link(dctx)}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
971 var mmap
= new HashMap[MMModule, Array[MMLocalProperty]]
972 for c
in crhe
.order
do
973 if mmmodule
.mhe
<= c
.mmmodule
or dctx
.owned_modules
.has
(c
.mmmodule
) or not c
isa MMSrcLocalClass then continue
974 var km
= dctx
.known_owner_of
(c
.mmmodule
)
975 if mmmodule
.mhe
<= km
then continue
976 var kc
= km
[c
.global
]
977 var props
: Array[MMLocalProperty]
978 if mmap
.has_key
(km
) then
981 props
= new Array[MMLocalProperty]
984 for g
in c
.global_properties
do
986 if p
.local_class
== c
and p
.need_doc
(dctx
) and accept_prop
(p
, pass
) then
988 if not props
.has
(kp
) then props
.add
(kp
)
991 # c.properties_inherited_from(dctx, self, pass)
994 dctx
.stage
("<tr bgcolor=\"#EEEEFF\"><th colspan=\"2\"><small>Added {passname} in known modules</small></th><tr>\n")
995 for c
in crhe
.order
do
997 if not mmap
.has_key
(m
) then continue
999 if props
.is_empty
then continue
1001 var properties
= new Array[String]
1002 for p
in props
do properties
.add
(p
.html_link
(dctx
))
1003 dctx
.add
("<tr><td width=\"20%\
"><small>in {m.html_link(dctx)}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
1006 dctx
.stage
("</table><br/><br/>\n")
1013 fun property_detail
(dctx
: DocContext, pass
: Int, new_props
: Array[MMLocalProperty])
1015 var passname
= pass_name
(pass
)
1017 dctx
.stage
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
1018 dctx
.stage
("<tr bgcolor=\"#CCCCFF\"><th>{passname} Detail of {self}</th><tr>\n")
1019 dctx
.stage
("</table>\n")
1022 for p
in new_props
do
1023 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")
1024 dctx
.add
("<blockquote>")
1027 dctx
.add
("<pre>{doc.to_html}</pre>\n")
1029 dctx
.stage
("</blockquote>\n")
1033 dctx
.stage
("<hr/>\n")
1040 # Add rows for properties inheriterd to some heirs
1041 fun properties_inherited_from
(dctx
: DocContext, heir
: MMLocalClass, pass
: Int)
1043 var properties
= new Array[String]
1044 for g
in global_properties
do
1046 if p
.local_class
== self and p
.need_doc
(dctx
) and accept_prop
(p
, pass
) then
1047 properties
.add
(p
.html_link
(dctx
))
1050 if not properties
.is_empty
then
1052 if heir
.global
== global
then
1053 s
= mmmodule
.html_link
(dctx
)
1055 s
= self.html_link
(dctx
)
1057 dctx
.add
("<tr><td width=\"20%\
"><small>in {s}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
1062 redef class MMSrcLocalClass
1068 else if global
.intro
== self then
1071 var bc
= global
.intro
1079 if not n
isa AStdClassdef then
1086 if d
.n_comment
.is_empty
then
1093 redef fun need_doc
(dctx
)
1095 if global
.visibility_level
>= 3 then
1096 if not dctx
.intrude_mode
then return false
1097 if dctx
.mmmodule
.visibility_for
(mmmodule
) == 0 then return false
1099 if global
.intro
== self then
1102 for p
in src_local_properties
do
1103 if p
.need_doc
(dctx
) then
1111 redef class MMSignature
1112 # Htlm transcription of the signature (with nested links)
1113 fun to_html
(dctx
: DocContext, with_closure
: Bool): String
1115 var res
= new Buffer
1118 res
.append
(self[0].html_link
(dctx
))
1119 for i
in [1..arity
[ do
1121 res
.append
(self[i
].html_link
(dctx
))
1125 if return_type
!= null then
1127 res
.append
(return_type
.html_link
(dctx
))
1129 if with_closure
then
1130 for c
in closures
do
1132 if c
.is_optional
then res
.append
("[")
1133 if c
.is_break
then res
.append
("break ")
1134 res
.append
("!{c.name}")
1135 res
.append
(c
.signature
.to_html
(dctx
, false))
1136 if c
.is_optional
then res
.append
("]")
1144 # Htlm transcription of the type (with nested links)
1145 fun html_link
(dctx
: DocContext): String do return to_s
1148 redef class MMTypeSimpleClass
1149 redef fun html_link
(dctx
) do return local_class
.html_link
(dctx
)
1152 redef class MMTypeGeneric
1153 redef fun html_link
(dctx
)
1155 var res
= new Buffer
1156 res
.append
(local_class
.html_link
(dctx
))
1158 res
.append
(params
[0].html_link
(dctx
))
1159 for i
in [1..params
.length
[ do
1161 res
.append
(params
[i
].html_link
(dctx
))
1168 var c
= new DocContext