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
252 option_context
.add_option
(opt_dir
)
255 redef fun process_options
258 var d
= opt_dir
.value
259 if d
!= null then dir
= d
263 # Conditionnal part of the text content of a DocContext
265 # Content of the current stage
266 readable var _content
: Array[String] = new Array[String]
268 # Is a normal string already added?
269 readable writable var _validate
: Bool = false
271 # Parent stage is any
272 readable var _parent
: nullable StageContext = null
274 init(parent
: nullable StageContext) do _parent
= parent
278 # Efficiently sort object with their to_s method
279 class AlphaSorter[E
: Object]
280 special AbstractSorter[E
]
281 redef fun compare
(a
, b
)
301 # Keep track of to_s values
302 var _dico
: HashMap[Object, String] = new HashMap[Object, String]
307 # Generalization of metamodel entities
310 fun html_link
(dctx
: DocContext): String is abstract
312 # Is the entity should appear in the generaed doc
313 fun need_doc
(dctx
: DocContext): Bool is abstract
315 # Return a one liner description
316 fun short_doc
: String do return " "
318 # The doc node from the AST
319 # Return null is none
320 fun doc
: nullable ADoc do return null
322 # Human redable location of the entity (module/class/property)
323 fun locate
(dctx
: DocContext): String do return ""
325 # Part of the prototype before the name (kind, modifiers, qualifier)
326 fun prototype_head
(dctx
: DocContext): String is abstract
328 # Part of the property after the name (signature, modifiers)
329 fun prototype_body
(dctx
: DocContext): String do return ""
334 redef fun html_link
(dctx
) do
335 if dctx
.module == self then
338 return "<a href=\"{self}.html\
">{self}</a>"
341 redef fun need_doc
(dctx
) do return true
342 redef fun prototype_head
(dctx
) do return "module "
344 var _known_owner_of_cache
: Map[MMModule, MMModule] = new HashMap[MMModule, MMModule]
345 fun known_owner_of
(module: MMModule): MMModule
347 if _known_owner_of_cache
.has_key
(module) then return _known_owner_of_cache
[module]
349 if mhe
< module and visibility_for
(module) != 0 then
350 res
= known_owner_of_intern
(module, self, false)
352 res
= module.owner
(self)
354 _known_owner_of_cache
[module] = res
358 # Return the most general module that own self
359 fun owner
(from
: MMModule): MMModule
362 var d
: nullable MMDirectory = directory
363 while d
!= null and d
!= from
.directory
do
365 if o
!= null and o
.mhe
<= res
then res
= o
371 private fun known_owner_of_intern
(module: MMModule, from
: MMModule, as_owner
: Bool): MMModule
373 if module == self then return self
374 var candidates
= new Array[MMModule]
375 for m
in explicit_imported_modules
do
376 if from
.visibility_for
(m
) == 0 then continue
377 if not m
.mhe
<= module then continue
378 candidates
.add
(m
.known_owner_of_intern
(module, from
, true))
380 assert not candidates
.is_empty
381 var max
= candidates
.first
382 for m
in candidates
do
383 if max
.mhe
< m
then max
= m
385 if as_owner
and max
.directory
.owner
== self then
394 redef class MMLocalProperty
396 # Anchor of the property description in the module html file
397 fun html_anchor
: String
399 return "PROP_{local_class}_{cmangle(name)}"
402 redef fun html_link
(dctx
)
405 if not need_doc
(dctx
) then m
= global
.intro
.module
406 var m
= dctx
.known_owner_of
(m
)
407 if m
== dctx
.module then
408 return "<a href=\"#{html_anchor}\">{self}</a>"
410 return "<a href=\"{m}.html
#{html_anchor}\">{self}</a>"
414 # Kind of property (fun, attr, etc.)
415 fun kind
: String is abstract
417 redef fun locate
(dctx
)
419 return "in {module.html_link(dctx)}::{local_class.html_link(dctx)}"
422 fun known_intro_class
(dctx
: DocContext): MMLocalClass
424 var mod
= dctx
.known_owner_of
(global
.intro
.local_class
.module)
425 var cla
= mod
[global
.intro
.local_class
.global
]
429 redef fun prototype_head
(dctx
)
432 var intro_class
= known_intro_class
(dctx
)
433 var is_redef
= local_class
!= intro_class
435 if is_redef
then res
.append
("redef ")
436 if global
.visibility_level
== 2 then
437 res
.append
("protected ")
438 else if global
.visibility_level
== 3 then
439 res
.append
("private ")
443 var gp
= global
.intro
444 if intro_class
.global
!= local_class
.global
then
445 res
.append
(" {module[intro_class.global].html_link(dctx)}::")
446 else if intro_class
.module != module then
447 res
.append
(" {intro_class.module.html_link(dctx)}::")
453 redef fun prototype_body
(dctx
)
456 res
.append
(signature
.to_html
(dctx
))
458 if s
isa MMMethod then
459 if s
.is_abstract
then
460 res
.append
(" is abstract")
461 else if s
.is_intern
then
462 res
.append
(" is intern")
468 redef fun need_doc
(dctx
)
470 if global
.visibility_level
>= 3 or self isa MMAttribute then
471 if not dctx
.intrude_mode
then return false
472 if dctx
.module.visibility_for
(module) == 0 then return false
474 if global
.intro
== self then
485 else if global
.intro
== self then
488 return global
.intro
.short_doc
495 if n
== null or not n
isa APropdef then
502 if d
.n_comment
.is_empty
then
510 redef fun kind
do return if global
.is_init
then "init" else "meth"
512 redef class MMAttribute
513 redef fun kind
do return "attr"
515 redef class MMTypeProperty
516 redef fun kind
do return "type"
519 redef class MMSrcModule
520 # Extract and generate html file for the module
521 fun extract_module_doc
(dctx
: DocContext)
523 dctx
.info
("Generating HTML for module {name}",1)
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
665 if d
.n_comment
.is_empty
then
674 # Html transcription of the doc
678 for c
in n_comment
do
679 res
.append
(c
.text
.substring_from
(1))
684 # Oneliner transcription of the doc
687 return n_comment
.first
.text
.substring_from
(1)
691 redef class MMLocalClass
693 # Anchor of the class description in the module html file
694 fun html_anchor
: String do return "CLASS_{self}"
696 redef fun html_link
(dctx
)
699 if not need_doc
(dctx
) then m
= global
.module
700 var m
= dctx
.known_owner_of
(m
)
701 if m
== dctx
.module then
702 return "<a href=\"#{html_anchor}\">{self}</a>"
704 return "<a href=\"{m}.html
#{html_anchor}\">{self}</a>"
708 redef fun short_doc
do return global
.intro
.short_doc
710 redef fun doc
do return global
.intro
.doc
712 redef fun need_doc
(dctx
) do
713 if module == dctx
.module then
714 for m
in dctx
.owned_modules
do
715 if m
.global_classes
.has
(global
) then
717 if c
.need_doc
(dctx
) then return true
724 redef fun locate
(dctx
) do return "in {module.html_link(dctx)}"
726 fun known_intro
(dctx
: DocContext): MMLocalClass do return dctx
.known_owner_of
(global
.intro
.module)[global
]
728 redef fun prototype_head
(dctx
)
731 var ki
= known_intro
(dctx
)
732 var is_redef
= ki
!= self
733 if is_redef
then res
.append
("redef ")
734 if global
.visibility_level
== 3 then res
.append
("private ")
736 if is_redef
then res
.append
("{ki.module.html_link(dctx)}::")
740 redef fun prototype_body
(dctx
)
745 for i
in [0..arity
[ do
746 var t
= get_formal
(i
)
747 res
.append
(t
.name
.to_s
)
749 res
.append
(t
.bound
.html_link
(dctx
))
756 # Extract the doc of a class
757 fun extract_class_doc
(dctx
: DocContext)
759 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")
760 dctx
.add
("<blockquote>\n")
763 var sup2
= new Array[String]
764 var intro_module
= dctx
.known_owner_of
(global
.module)
765 if intro_module
!= module then
766 dctx
.add
("<dt>Refine {self} from: <dd>{intro_module.html_link(dctx)}\n")
768 var mods
= new Array[MMModule]
769 for c
in crhe
.greaters
do
770 if c
.need_doc
(dctx
) then
771 var km
= dctx
.known_owner_of
(c
.module)
772 if km
!= module and km
!= intro_module
and not mods
.has
(km
) then
777 for c
in crhe
.linear_extension
do
778 if mods
.has
(c
.module) then sup2
.add
(c
.module.html_link
(dctx
))
780 if not sup2
.is_empty
then dctx
.add
("<dt>Previous refinements in: <dd>{sup2.join(", ")}\n")
782 if not cshe
.greaters
.is_empty
then
784 var clas
= new Array[MMLocalClass]
785 for c
in cshe
.direct_greaters
do
786 sup2
.add
(c
.html_link
(dctx
))
788 dctx
.add
("<dt>Direct superclasses: <dd>{sup2.join(", ")}\n")
790 for c
in cshe
.linear_extension
do
791 if c
!= self then sup2
.add
(c
.html_link
(dctx
))
793 dctx
.add
("<dt>All superclasses: <dd>{sup2.join(", ")}\n")
795 if not cshe
.direct_smallers
.is_empty
then
797 for c
in cshe
.direct_smallers
do
798 sup2
.add
(c
.html_link
(dctx
))
800 dctx
.add
("<dt>Direct subclasses: <dd>{sup2.join(", ")}\n")
803 for c
in crhe
.smallers
do
804 c
.compute_super_classes
805 for c2
in c
.module.local_classes
do
806 if not c2
isa MMConcreteClass then continue
807 c2
.compute_super_classes
809 c2
.inherit_global_properties
811 for c2
in c
.cshe
.direct_smallers
do
812 if c2
.global
.intro
== c2
then
813 sup2
.add
("{c2.html_link(dctx)}")
817 if not sup2
.is_empty
then
818 dctx
.add
("<dt>Other direct subclasses in known modules: <dd>{sup2.join(", ")}\n")
821 for c
in crhe
.order
do
822 if not module.mhe
<= c
.module and c
.need_doc
(dctx
) then
823 sup2
.add
(c
.module.html_link
(dctx
))
826 if not sup2
.is_empty
then
827 dctx
.add
("<dt>Refinements in known modules: <dd>{sup2.join(", ")}\n")
833 dctx
.add
("<pre>{doc.to_html}</pre>\n")
836 var details
= new Array[Array[MMLocalProperty]]
837 for i
in [0..4[ do details
.add
(property_summary
(dctx
, i
))
838 for i
in [0..4[ do property_detail
(dctx
, i
, details
[i
])
840 dctx
.add
("</blockquote><hr/>\n")
843 fun pass_name
(pass
: Int): String
845 var names
= once
["Virtual Types", "Consructors", "Methods", "Attributes"]
849 fun accept_prop
(p
: MMLocalProperty, pass
: Int): Bool
852 return p
isa MMTypeProperty
853 else if pass
== 1 then
854 return p
.global
.is_init
855 else if pass
== 2 then
856 return p
isa MMMethod and not p
.global
.is_init
857 else if pass
== 3 then
858 return p
isa MMAttribute
863 fun property_summary
(dctx
: DocContext, pass
: Int): Array[MMLocalProperty]
865 var passname
= pass_name
(pass
)
867 dctx
.stage
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
868 dctx
.stage
("<tr bgcolor=\"#CCCCFF\"><th colspan=\"2\">{passname} Summary of {self}</th></tr>\n")
870 var new_props
= new Array[MMLocalProperty]
871 for g
in global_properties
do
872 if not accept_prop
(g
.intro
, pass
) then continue
873 if module.visibility_for
(g
.intro
.module) < g
.visibility_level
then continue
875 if p
.local_class
!= self or not p
.need_doc
(dctx
) then
876 var cla
= new Array[MMLocalClass]
877 for m
in dctx
.owned_modules
do
878 if not m
.global_classes
.has
(global
) then continue
880 if not c
isa MMConcreteClass then continue
881 if not c
.has_global_property
(g
) then continue
883 if p2
.local_class
!= c
or not p2
.need_doc
(dctx
) then continue
886 if cla
.is_empty
then continue
887 cla
= crhe
.order
.select_smallests
(cla
)
891 if p
.global
.intro
== p
then
896 for p
in new_props
do
897 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")
899 dctx
.stage
("</table><br/>\n")
902 dctx
.stage
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
904 # skip pass 1 because constructors are not inherited
905 var cmap
= new HashMap[MMLocalClass, Array[MMLocalProperty]]
906 var mmap
= new HashMap[MMModule, Array[MMLocalProperty]]
907 var props
= new Array[MMLocalClass]
908 for c
in che
.greaters
do
909 if c
isa MMSrcLocalClass then
910 var km
= dctx
.known_owner_of
(c
.module)
911 var kc
= km
[c
.global
]
912 if kc
== self then continue
913 var props
: Array[MMLocalProperty]
915 if cmap
.has_key
(kc
) then
918 props
= new Array[MMLocalProperty]
922 if mmap
.has_key
(km
) then
925 props
= new Array[MMLocalProperty]
929 for g
in c
.global_properties
do
931 if p
.local_class
== c
and p
.need_doc
(dctx
) and accept_prop
(p
, pass
) then
938 dctx
.stage
("<tr bgcolor=\"#EEEEFF\"><th colspan=\"2\"><small>Inherited {passname}</small></th><tr>\n")
939 for c
in cshe
.linear_extension
do
940 if not cmap
.has_key
(c
) then continue
942 if props
.is_empty
then continue
944 var properties
= new Array[String]
945 for p
in props
do properties
.add
(p
.html_link
(dctx
))
946 dctx
.add
("<tr><td width=\"20%\
"><small>from {c.html_link(dctx)}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
951 dctx
.stage
("<tr bgcolor=\"#EEEEFF\"><th colspan=\"2\"><small>Imported {passname}</small></th><tr>\n")
952 for m
in module.mhe
.linear_extension
do
953 if not mmap
.has_key
(m
) then continue
955 if props
.is_empty
then continue
957 var properties
= new Array[String]
958 for p
in props
do properties
.add
(p
.html_link
(dctx
))
959 dctx
.add
("<tr><td width=\"20%\
"><small>from {m.html_link(dctx)}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
964 var mmap
= new HashMap[MMModule, Array[MMLocalProperty]]
965 var props
= new Array[MMLocalClass]
966 for c
in crhe
.order
do
967 if module.mhe
<= c
.module or dctx
.owned_modules
.has
(c
.module) or not c
isa MMSrcLocalClass then continue
968 var km
= dctx
.known_owner_of
(c
.module)
969 if module.mhe
<= km
then continue
970 var kc
= km
[c
.global
]
971 var props
: Array[MMLocalProperty]
972 if mmap
.has_key
(km
) then
975 props
= new Array[MMLocalProperty]
978 for g
in c
.global_properties
do
980 if p
.local_class
== c
and p
.need_doc
(dctx
) and accept_prop
(p
, pass
) then
982 if not props
.has
(kp
) then props
.add
(kp
)
985 # c.properties_inherited_from(dctx, self, pass)
988 dctx
.stage
("<tr bgcolor=\"#EEEEFF\"><th colspan=\"2\"><small>Added {passname} in known modules</small></th><tr>\n")
989 for c
in crhe
.order
do
991 if not mmap
.has_key
(m
) then continue
993 if props
.is_empty
then continue
995 var properties
= new Array[String]
996 for p
in props
do properties
.add
(p
.html_link
(dctx
))
997 dctx
.add
("<tr><td width=\"20%\
"><small>in {m.html_link(dctx)}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
1000 dctx
.stage
("</table><br/><br/>\n")
1007 fun property_detail
(dctx
: DocContext, pass
: Int, new_props
: Array[MMLocalProperty])
1009 var passname
= pass_name
(pass
)
1011 dctx
.stage
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
1012 dctx
.stage
("<tr bgcolor=\"#CCCCFF\"><th>{passname} Detail of {self}</th><tr>\n")
1013 dctx
.stage
("</table>\n")
1016 for p
in new_props
do
1017 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")
1018 dctx
.add
("<blockquote>")
1021 dctx
.add
("<pre>{doc.to_html}</pre>\n")
1023 dctx
.stage
("</blockquote>\n")
1027 dctx
.stage
("<hr/>\n")
1034 # Add rows for properties inheriterd to some heirs
1035 fun properties_inherited_from
(dctx
: DocContext, heir
: MMLocalClass, pass
: Int)
1037 var properties
= new Array[String]
1038 for g
in global_properties
do
1040 if p
.local_class
== self and p
.need_doc
(dctx
) and accept_prop
(p
, pass
) then
1041 properties
.add
(p
.html_link
(dctx
))
1044 if not properties
.is_empty
then
1046 if heir
.global
== global
then
1047 s
= module.html_link
(dctx
)
1049 s
= self.html_link
(dctx
)
1051 dctx
.add
("<tr><td width=\"20%\
"><small>in {s}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
1056 redef class MMSrcLocalClass
1062 else if global
.intro
== self then
1065 var bc
= global
.intro
1073 if not n
isa AStdClassdef then
1080 if d
.n_comment
.is_empty
then
1087 redef fun need_doc
(dctx
)
1089 if global
.visibility_level
>= 3 then
1090 if not dctx
.intrude_mode
then return false
1091 if dctx
.module.visibility_for
(module) == 0 then return false
1093 if global
.intro
== self then
1096 for p
in src_local_properties
do
1097 if p
.need_doc
(dctx
) then
1105 redef class MMSignature
1106 # Htlm transcription of the signature (with nested links)
1107 fun to_html
(dctx
: DocContext): String
1109 var res
= new Buffer
1112 res
.append
(self[0].html_link
(dctx
))
1113 for i
in [1..arity
[ do
1115 res
.append
(self[i
].html_link
(dctx
))
1119 if return_type
!= null then
1121 res
.append
(return_type
.html_link
(dctx
))
1128 # Htlm transcription of the type (with nested links)
1129 fun html_link
(dctx
: DocContext): String do return to_s
1132 redef class MMTypeSimpleClass
1133 redef fun html_link
(dctx
) do return local_class
.html_link
(dctx
)
1136 redef class MMTypeGeneric
1137 redef fun html_link
(dctx
)
1139 var res
= new Buffer
1140 res
.append
(local_class
.html_link
(dctx
))
1142 res
.append
(params
[0].html_link
(dctx
))
1143 for i
in [1..params
.length
[ do
1145 res
.append
(params
[i
].html_link
(dctx
))
1152 var c
= new DocContext