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 attr _dir
: String
31 # Content of a generated file
32 attr _stage_context
: StageContext = new StageContext(null)
34 # Add a string in the content
35 meth add
(s
: String) do
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 meth stage
(s
: String) do _stage_context
.content
.add
(s
)
43 # Create a new stage in the content
44 meth 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
)
57 # Write the content to a new file
58 meth write_to
(filename
: String)
60 print
"Generate {filename}"
61 var f
= new OFStream.open
(filename
)
62 for s
in _stage_context
.content
do
68 # Currently computed module
69 readable attr _module
: MMSrcModule
71 # Is the current directory module computed as a simple modude ?
72 readable writable attr _inside_mode
: Bool
74 # Is the current module computed as a intruded one ?
75 readable writable attr _intrude_mode
: Bool
77 # Compued introducing entities (for the index)
78 attr _entities
: Array[MMEntity] = new Array[MMEntity]
80 # Register an entity (for the index)
81 meth register
(e
: MMEntity)
84 if e
isa MMSrcModule then
92 _stage_context
= new StageContext(null)
95 # Generate common files (frames, index, overview)
96 meth extract_other_doc
102 add
("<html><body>\n")
103 add
("<a href=\"overview
.html\
" target=\"mainFrame\
">Overview</a><br/>\n")
104 add
("<a href=\"index-1
.html\
" target=\"mainFrame\
">Index</a><br/>\n")
105 var modules
= modules
.to_a
108 var rootdirs
= new Array[MMDirectory]
111 if md
.parent
== null and not rootdirs
.has
(md
) then
116 var done
= new Array[MMModule]
117 for root
in rootdirs
do
118 var dirstack
= [root
]
120 add
("{root.name}<br/>\n")
121 var indent
= " "
122 while not dirstack
.is_empty
do
125 if done
.has
(m
) then continue
127 if md
.owner
== m
and md
.parent
== curdir
then
128 # It's a directory module
129 add
("{indent}<a href=\"{m}.html\
" target=\"mainFrame\
">{m}</a><br/>\n")
131 dirstack
.push
(curdir
)
132 indent
= "  " * dirstack
.length
134 break # restart to preserve alphabetic order
135 else if md
== curdir
then
136 if md
.owner
== m
then
137 add
("{indent}<a href=\"{m}_
.html\
" target=\"mainFrame\
">{m}</a><br/>\n")
139 add
("{indent}<a href=\"{m}.html\
" target=\"mainFrame\
">{m}</a><br/>\n")
147 if not dirstack
.is_empty
then
148 curdir
= dirstack
[dirstack
.length-1
]
149 indent
= "  " * dirstack
.length
154 add
("</body></html>\n")
155 write_to
("{dir}/menu-frame.html")
161 for e
in _entities
do
162 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")
164 add
("</dl></body></html>\n")
165 write_to
("{dir}/index-1.html")
168 add_header
("Overview")
169 add
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
170 add
("<tr bgcolor=\"#CCCCFF\"><th colspan=\"2\"><big>Overview of all Modules</big></th><tr>\n")
172 add
("<tr><td width=\"20%\
" align=\"right\
">{m.html_link(self)}</td><td>{m.short_doc}</td><tr>\n")
174 add
("</table></body></html>\n")
175 write_to
("{dir}/overview.html")
178 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")
179 write_to
("{dir}/index.html")
182 meth add_header
(title
: String)
184 add
("<html><head><title>{title}</title></head>\n<body>\n")
185 add
("<table border=\"0\
" width=\"100%\
" cellpadding=\"1\
" cellspacing=\"0\
"><tr><td bgcolor=\"#eeeeff\">\n")
186 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")
187 add
("</td></tr></table>")
189 if (not inside_mode
and not intrude_mode
) or module == null then
190 add
("<b>Public</b> ")
192 add
("<a href=\"{module}.html\
"><b>Public</b></a> ")
194 if inside_mode
or module == null then
195 add
("<b>Inside</b> ")
196 else if module.directory
.owner
!= module then
197 add
("<strike><b>Inside</b></strike> ")
199 add
("<a href=\"{module}_
.html\
"><b>Inside</b></a> ")
201 if intrude_mode
or module == null then
202 add
("<b>Intrude</b> ")
204 add
("<a href=\"{module}__
.html\
"><b>Intrude</b></a> ")
209 # Sorter of entities in alphabetical order
210 attr _sorter
: AlphaSorter[MMEntity] = new AlphaSorter[MMEntity]
212 # Sort entities in the alphabetical order
213 meth sort
(array
: Array[MMEntity])
218 readable writable attr _owned_modules
: Array[MMModule]
220 # Return the known_owner for current module
221 # if inside_mode is set, it could be a different result
222 meth known_owner_of
(m
: MMModule): MMModule
224 if module == null then return m
225 var res
= module.known_owner_of
(m
)
226 if not inside_mode
and not intrude_mode
and res
.directory
.owner
== module then
233 readable attr _opt_dir
: OptionString = new OptionString("Directory where doc is generated", "-d", "--dir")
235 redef meth perform_work
(mods
)
239 for mod
in modules
do
240 assert mod
isa MMSrcModule
241 mod
.extract_module_doc
(self)
243 self.extract_other_doc
249 option_context
.add_option
(opt_dir
)
252 redef meth process_options
256 if dir
== null then dir
= "."
260 # Conditionnal part of the text content of a DocContext
262 # Content of the current stage
263 readable attr _content
: Array[String] = new Array[String]
265 # Is a normal string already added?
266 readable writable attr _validate
: Bool
268 # Parent stage is any
269 readable attr _parent
: StageContext
271 init(parent
: StageContext) do _parent
= parent
275 # Efficiently sort object with their to_s method
276 class AlphaSorter[E
: Object]
277 special AbstractSorter[E
]
278 redef meth compare
(a
, b
)
298 # Keep track of to_s values
299 attr _dico
: HashMap[Object, String] = new HashMap[Object, String]
304 # Generalization of metamodel entities
307 meth html_link
(dctx
: DocContext): String is abstract
309 # Is the entity should appear in the generaed doc
310 meth need_doc
(dctx
: DocContext): Bool is abstract
312 # Return a one liner description
313 meth short_doc
: String do return " "
315 # The doc node from the AST
316 # Return null is none
317 meth doc
: ADoc do return null
319 # Human redable location of the entity (module/class/property)
320 meth locate
(dctx
: DocContext): String do return ""
322 # Part of the prototype before the name (kind, modifiers, qualifier)
323 meth prototype_head
(dctx
: DocContext): String is abstract
325 # Part of the property after the name (signature, modifiers)
326 meth prototype_body
(dctx
: DocContext): String do return ""
331 redef meth html_link
(dctx
) do
332 if dctx
.module == self then
335 return "<a href=\"{self}.html\
">{self}</a>"
338 redef meth need_doc
(dctx
) do return true
339 redef meth prototype_head
(dctx
) do return "module "
341 attr _known_owner_of_cache
: Map[MMModule, MMModule] = new HashMap[MMModule, MMModule]
342 meth known_owner_of
(module: MMModule): MMModule
344 if _known_owner_of_cache
.has_key
(module) then return _known_owner_of_cache
[module]
346 if mhe
< module and visibility_for
(module) != 0 then
347 res
= known_owner_of_intern
(module, self, false)
349 res
= module.owner
(self)
351 _known_owner_of_cache
[module] = res
355 # Return the most general module that own self
356 meth owner
(from
: MMModule): MMModule
360 while d
!= null and d
!= from
.directory
do
362 if o
!= null and o
.mhe
<= res
then res
= o
368 private meth known_owner_of_intern
(module: MMModule, from
: MMModule, as_owner
: Bool): MMModule
370 if module == self then return self
371 var candidates
= new Array[MMModule]
372 for m
in explicit_imported_modules
do
373 if from
.visibility_for
(m
) == 0 then continue
374 if not m
.mhe
<= module then continue
375 candidates
.add
(m
.known_owner_of_intern
(module, from
, true))
377 assert not candidates
.is_empty
378 var max
= candidates
.first
379 for m
in candidates
do
380 if max
.mhe
< m
then max
= m
382 if as_owner
and max
.directory
.owner
== self then
391 redef class MMLocalProperty
393 # Anchor of the property description in the module html file
394 meth html_anchor
: String
396 return "PROP_{local_class}_{cmangle(name)}"
399 redef meth html_link
(dctx
)
402 if not need_doc
(dctx
) then m
= global
.intro
.module
403 var m
= dctx
.known_owner_of
(m
)
404 if m
== dctx
.module then
405 return "<a href=\"#{html_anchor}\">{self}</a>"
407 return "<a href=\"{m}.html
#{html_anchor}\">{self}</a>"
411 redef meth short_doc
do return concrete_property
.short_doc
413 redef meth doc
do return concrete_property
.doc
415 redef meth need_doc
(dctx
) do return false
417 # Kind of property (meth, attr, etc.)
418 meth kind
: String is abstract
420 redef meth locate
(dctx
)
422 return "in {module.html_link(dctx)}::{local_class.html_link(dctx)}"
425 meth known_intro_class
(dctx
: DocContext): MMLocalClass
427 var mod
= dctx
.known_owner_of
(global
.intro
.local_class
.module)
428 var cla
= mod
[global
.intro
.local_class
.global
]
432 redef meth prototype_head
(dctx
)
435 var intro_class
= known_intro_class
(dctx
)
436 var is_redef
= local_class
!= intro_class
438 if is_redef
then res
.append
("redef ")
439 if global
.visibility_level
== 2 then
440 res
.append
("protected ")
441 else if global
.visibility_level
== 3 then
442 res
.append
("private ")
446 var gp
= global
.intro
447 if intro_class
.global
!= local_class
.global
then
448 res
.append
(" {module[intro_class.global].html_link(dctx)}::")
449 else if intro_class
.module != module then
450 res
.append
(" {intro_class.module.html_link(dctx)}::")
456 redef meth prototype_body
(dctx
)
458 var res
= signature
.to_html
(dctx
)
460 if s
isa MMConcreteProperty then
461 if s
.node
isa ADeferredMethPropdef then
462 res
.append
(" is abstract")
463 else if s
.node
isa AInternMethPropdef then
464 res
.append
(" is intern")
471 redef meth kind
do return if global
.is_init
then "init" else "meth"
473 redef class MMAttribute
474 redef meth kind
do return "attr"
476 redef class MMTypeProperty
477 redef meth kind
do return "type"
480 redef class MMSrcModule
481 # Extract and generate html file for the module
482 meth extract_module_doc
(dctx
: DocContext)
487 extract_module_doc_inside
(dctx
)
488 dctx
.write_to
("{dctx.dir}/{name}.html")
490 dctx
.intrude_mode
= true
492 extract_module_doc_inside
(dctx
)
493 dctx
.write_to
("{dctx.dir}/{name}__.html")
494 dctx
.intrude_mode
= false
496 if directory
.owner
== self then
497 dctx
.inside_mode
= true
499 extract_module_doc_inside
(dctx
)
500 dctx
.write_to
("{dctx.dir}/{name}_.html")
501 dctx
.inside_mode
= false
505 meth extract_module_doc_inside
(dctx
: DocContext)
507 dctx
.add_header
("Module {self}")
508 dctx
.add
("<h1>Module {self}</h1>\n<dl>")
512 if d
.owner
!= null and (d
.owner
!= self or dctx
.inside_mode
or dctx
.intrude_mode
) then
513 s
= "{d.owner.html_link(dctx)}::{s}"
517 dctx
.add
("{s}<br/>{prototype_head(dctx)}<b>{self}</b>{prototype_body(dctx)}<br/>\n")
519 var strs
= new Array[String]
520 var intrude_modules
= new Array[MMModule]
521 var public_modules
= new Array[MMModule]
522 var private_modules
= new Array[MMModule]
523 var owned_modules
= new Array[MMModule]
524 dctx
.owned_modules
= owned_modules
525 for m
in mhe
.greaters
do
526 var v
= visibility_for
(m
)
527 if not dctx
.inside_mode
and not dctx
.intrude_mode
and m
.directory
.owner
== self then
528 if v
>= 2 then owned_modules
.add
(m
)
532 intrude_modules
.add
(m
)
534 public_modules
.add
(m
)
536 private_modules
.add
(m
)
539 if not intrude_modules
.is_empty
then
540 var mods
= mhe
.order
.select_smallests
(intrude_modules
)
541 for i
in mods
do strs
.add
(i
.html_link
(dctx
))
542 dctx
.add
("<dt>Intruded modules: <dd>{strs.join(", ")}\n")
544 if not public_modules
.is_empty
then
546 var mods
= mhe
.order
.select_smallests
(public_modules
)
547 for i
in mods
do strs
.add
(i
.html_link
(dctx
))
548 dctx
.add
("<dt>Imported modules: <dd>{strs.join(", ")}\n")
550 if not private_modules
.is_empty
then
552 var mods
= mhe
.order
.select_smallests
(private_modules
)
553 for i
in mods
do strs
.add
(i
.html_link
(dctx
))
554 dctx
.add
("<dt>Privatly imported modules: <dd>{strs.join(", ")}\n")
559 if doc
!= null then dctx
.add
("<pre>{doc.to_html}</pre>\n")
561 var new_classes
= new Array[MMLocalClass]
562 for c
in local_classes
do
563 if c
.need_doc
(dctx
) then
565 if c
.global
.intro
== c
then
569 for m
in owned_modules
do
571 if mc
!= null and mc
.need_doc
(dctx
) then
579 if not new_classes
.is_empty
then
580 dctx
.sort
(new_classes
)
581 dctx
.add
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
582 dctx
.add
("<tr bgcolor=\"#CCCCFF\"><th colspan=\"2\"><big>Class Summary of {self}</big></th><tr>\n")
583 for c
in new_classes
do
584 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")
586 dctx
.add
("</table><br/>\n")
589 if not new_classes
.is_empty
then
590 dctx
.add
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
591 dctx
.add
("<tr bgcolor=\"#CCCCFF\"><th><big>Class Detail of {self}</big></th><tr>\n")
592 dctx
.add
("</table>\n")
594 for c
in new_classes
do
595 c
.extract_class_doc
(dctx
)
599 dctx
.add
("</body></html>\n")
615 if not n
isa AModule then
619 if n
.n_packagedecl
== null then
622 var np
= n
.n_packagedecl
623 assert np
isa APackagedecl
629 if d
.n_comment
.is_empty
then
638 # Html transcription of the doc
642 for c
in n_comment
do
643 res
.append
(c
.text
.substring_from
(1))
648 # Oneliner transcription of the doc
651 return n_comment
.first
.text
.substring_from
(1)
655 redef class MMLocalClass
657 # Anchor of the class description in the module html file
658 meth html_anchor
: String do return "CLASS_{self}"
660 redef meth html_link
(dctx
)
663 if not need_doc
(dctx
) then m
= global
.module
664 var m
= dctx
.known_owner_of
(m
)
665 if m
== dctx
.module then
666 return "<a href=\"#{html_anchor}\">{self}</a>"
668 return "<a href=\"{m}.html
#{html_anchor}\">{self}</a>"
672 redef meth short_doc
do return global
.intro
.short_doc
674 redef meth doc
do return global
.intro
.doc
676 redef meth need_doc
(dctx
) do
677 if module == dctx
.module then
678 for m
in dctx
.owned_modules
do
680 if c
!= null and c
.need_doc
(dctx
) then return true
686 redef meth locate
(dctx
) do return "in {module.html_link(dctx)}"
688 meth known_intro
(dctx
: DocContext): MMLocalClass do return dctx
.known_owner_of
(global
.intro
.module)[global
]
690 redef meth prototype_head
(dctx
)
693 var ki
= known_intro
(dctx
)
694 var is_redef
= ki
!= self
695 if is_redef
then res
.append
("redef ")
696 if global
.visibility_level
== 3 then res
.append
("private ")
698 if is_redef
then res
.append
("{ki.module.html_link(dctx)}::")
702 redef meth prototype_body
(dctx
)
707 for i
in [0..arity
[ do
708 var t
= get_formal
(i
)
709 res
.append
(t
.name
.to_s
)
711 res
.append
(t
.bound
.html_link
(dctx
))
718 # Extract the doc of a class
719 meth extract_class_doc
(dctx
: DocContext)
721 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")
722 dctx
.add
("<blockquote>\n")
725 var sup2
= new Array[String]
726 var intro_module
= dctx
.known_owner_of
(global
.module)
727 if intro_module
!= module then
728 dctx
.add
("<dt>Refine {self} from: <dd>{intro_module.html_link(dctx)}\n")
730 var mods
= new Array[MMModule]
731 for c
in crhe
.greaters
do
732 if c
.need_doc
(dctx
) then
733 var km
= dctx
.known_owner_of
(c
.module)
734 if km
!= module and km
!= intro_module
and not mods
.has
(km
) then
739 for c
in crhe
.linear_extension
do
740 if mods
.has
(c
.module) then sup2
.add
(c
.module.html_link
(dctx
))
742 if not sup2
.is_empty
then dctx
.add
("<dt>Previous refinements in: <dd>{sup2.join(", ")}\n")
744 if not cshe
.greaters
.is_empty
then
746 var clas
= new Array[MMLocalClass]
747 for c
in cshe
.direct_greaters
do
748 sup2
.add
(c
.html_link
(dctx
))
750 dctx
.add
("<dt>Direct superclasses: <dd>{sup2.join(", ")}\n")
752 for c
in cshe
.linear_extension
do
753 if c
!= self then sup2
.add
(c
.html_link
(dctx
))
755 dctx
.add
("<dt>All superclasses: <dd>{sup2.join(", ")}\n")
757 if not cshe
.direct_smallers
.is_empty
then
759 for c
in cshe
.direct_smallers
do
760 sup2
.add
(c
.html_link
(dctx
))
762 dctx
.add
("<dt>Direct subclasses: <dd>{sup2.join(", ")}\n")
765 for c
in crhe
.smallers
do
766 c
.compute_super_classes
767 for c2
in c
.module.local_classes
do
768 if not c2
isa MMConcreteClass then continue
769 c2
.compute_super_classes
771 c2
.inherit_global_properties
773 for c2
in c
.cshe
.direct_smallers
do
774 if c2
.global
.intro
== c2
then
775 sup2
.add
("{c2.html_link(dctx)}")
779 if not sup2
.is_empty
then
780 dctx
.add
("<dt>Other direct subclasses in known modules: <dd>{sup2.join(", ")}\n")
783 for c
in crhe
.order
do
784 if not module.mhe
<= c
.module and c
.need_doc
(dctx
) then
785 sup2
.add
(c
.module.html_link
(dctx
))
788 if not sup2
.is_empty
then
789 dctx
.add
("<dt>Refinements in known modules: <dd>{sup2.join(", ")}\n")
795 dctx
.add
("<pre>{doc.to_html}</pre>\n")
798 var details
= new Array[Array[MMLocalProperty]]
799 for i
in [0..4[ do details
.add
(property_summary
(dctx
, i
))
800 for i
in [0..4[ do property_detail
(dctx
, i
, details
[i
])
802 dctx
.add
("</blockquote><hr/>\n")
805 meth pass_name
(pass
: Int): String
807 var names
= once
["Virtual Types", "Consructors", "Methods", "Attributes"]
811 meth accept_prop
(p
: MMLocalProperty, pass
: Int): Bool
814 return p
isa MMTypeProperty
815 else if pass
== 1 then
816 return p
.global
.is_init
817 else if pass
== 2 then
818 return p
isa MMMethod and not p
.global
.is_init
819 else if pass
== 3 then
820 return p
isa MMAttribute
825 meth property_summary
(dctx
: DocContext, pass
: Int): Array[MMLocalProperty]
827 var passname
= pass_name
(pass
)
829 dctx
.stage
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
830 dctx
.stage
("<tr bgcolor=\"#CCCCFF\"><th colspan=\"2\">{passname} Summary of {self}</th><tr>\n")
832 var new_props
= new Array[MMLocalProperty]
833 for g
in global_properties
do
834 if not accept_prop
(g
.intro
, pass
) then continue
835 if module.visibility_for
(g
.intro
.module) < g
.visibility_level
then continue
837 if not p
.need_doc
(dctx
) then
838 var cla
= new Array[MMLocalClass]
839 for m
in dctx
.owned_modules
do
841 if c
== null or not c
isa MMConcreteClass then continue
843 if p2
== null or not p2
.need_doc
(dctx
) then continue
846 if cla
.is_empty
then continue
847 cla
= crhe
.order
.select_smallests
(cla
)
851 if p
.global
.intro
== p
then
856 for p
in new_props
do
857 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")
859 dctx
.stage
("</table><br/>\n")
862 dctx
.stage
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
864 # skip pass 1 because constructors are not inherited
865 var cmap
= new HashMap[MMLocalClass, Array[MMLocalProperty]]
866 var mmap
= new HashMap[MMModule, Array[MMLocalProperty]]
867 var props
= new Array[MMLocalClass]
868 for c
in che
.greaters
do
869 if c
isa MMSrcLocalClass then
870 var km
= dctx
.known_owner_of
(c
.module)
871 var kc
= km
[c
.global
]
872 if kc
== self or not c
isa MMConcreteClass then continue
873 var props
: Array[MMLocalProperty]
875 if cmap
.has_key
(kc
) then
878 props
= new Array[MMLocalProperty]
882 if mmap
.has_key
(km
) then
885 props
= new Array[MMLocalProperty]
889 for g
in c
.global_properties
do
891 if p
.need_doc
(dctx
) and accept_prop
(p
, pass
) then
898 dctx
.stage
("<tr bgcolor=\"#EEEEFF\"><th colspan=\"2\"><small>Inherited {passname}</small></th><tr>\n")
899 for c
in cshe
.linear_extension
do
900 if not cmap
.has_key
(c
) then continue
902 if props
.is_empty
then continue
904 var properties
= new Array[String]
905 for p
in props
do properties
.add
(p
.html_link
(dctx
))
906 dctx
.add
("<tr><td width=\"20%\
"><small>from {c.html_link(dctx)}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
911 dctx
.stage
("<tr bgcolor=\"#EEEEFF\"><th colspan=\"2\"><small>Imported {passname}</small></th><tr>\n")
912 for m
in module.mhe
.linear_extension
do
913 if not mmap
.has_key
(m
) then continue
915 if props
.is_empty
then continue
917 var properties
= new Array[String]
918 for p
in props
do properties
.add
(p
.html_link
(dctx
))
919 dctx
.add
("<tr><td width=\"20%\
"><small>from {m.html_link(dctx)}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
924 var mmap
= new HashMap[MMModule, Array[MMLocalProperty]]
925 var props
= new Array[MMLocalClass]
926 for c
in crhe
.order
do
927 if module.mhe
<= c
.module or dctx
.owned_modules
.has
(c
.module) or not c
isa MMSrcLocalClass then continue
928 var km
= dctx
.known_owner_of
(c
.module)
929 if module.mhe
<= km
then continue
930 var kc
= km
[c
.global
]
931 var props
: Array[MMLocalProperty]
932 if mmap
.has_key
(km
) then
935 props
= new Array[MMLocalProperty]
938 for g
in c
.global_properties
do
940 if p
.need_doc
(dctx
) and accept_prop
(p
, pass
) then
942 if not props
.has
(kp
) then props
.add
(kp
)
945 # c.properties_inherited_from(dctx, self, pass)
948 dctx
.stage
("<tr bgcolor=\"#EEEEFF\"><th colspan=\"2\"><small>Added {passname} in known modules</small></th><tr>\n")
949 for c
in crhe
.order
do
951 if not mmap
.has_key
(m
) then continue
953 if props
.is_empty
then continue
955 var properties
= new Array[String]
956 for p
in props
do properties
.add
(p
.html_link
(dctx
))
957 dctx
.add
("<tr><td width=\"20%\
"><small>in {m.html_link(dctx)}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
960 dctx
.stage
("</table><br/><br/>\n")
967 meth property_detail
(dctx
: DocContext, pass
: Int, new_props
: Array[MMLocalProperty])
969 var passname
= pass_name
(pass
)
971 dctx
.stage
("<table border=\"1\
" width=\"100%\
" cellpadding=\"3\
" cellspacing=\"0\
">\n")
972 dctx
.stage
("<tr bgcolor=\"#CCCCFF\"><th>{passname} Detail of {self}</th><tr>\n")
973 dctx
.stage
("</table>\n")
976 for p
in new_props
do
977 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")
978 dctx
.add
("<blockquote>")
981 dctx
.add
("<pre>{doc.to_html}</pre>\n")
983 dctx
.stage
("</blockquote>\n")
987 dctx
.stage
("<hr/>\n")
994 # Add rows for properties inheriterd to some heirs
995 meth properties_inherited_from
(dctx
: DocContext, heir
: MMLocalClass, pass
: Int)
997 var properties
= new Array[String]
998 for g
in global_properties
do
1000 if p
.need_doc
(dctx
) and accept_prop
(p
, pass
) then
1001 properties
.add
(p
.html_link
(dctx
))
1004 if not properties
.is_empty
then
1006 if heir
.global
== global
then
1007 s
= module.html_link
(dctx
)
1009 s
= self.html_link
(dctx
)
1011 dctx
.add
("<tr><td width=\"20%\
"><small>in {s}</small></td><td><small>{properties.join(", ")}</small></td><tr>\n")
1016 redef class MMSrcLocalClass
1017 redef meth short_doc
1022 else if global
.intro
== self then
1025 var bc
= global
.intro
1033 if not n
isa AClassdef then
1036 assert n
isa AClassdef
1042 if d
.n_comment
.is_empty
then
1049 redef meth need_doc
(dctx
)
1051 if global
.visibility_level
>= 3 then
1052 if not dctx
.intrude_mode
then return false
1053 if dctx
.module.visibility_for
(module) == 0 then return false
1055 if global
.intro
== self then
1058 for p
in src_local_properties
do
1059 if p
.need_doc
(dctx
) then
1067 redef class MMConcreteProperty
1068 redef meth need_doc
(dctx
)
1070 if global
.visibility_level
>= 3 or self isa MMAttribute then
1071 if not dctx
.intrude_mode
then return false
1072 if dctx
.module.visibility_for
(module) == 0 then return false
1074 if global
.intro
== self then
1080 redef meth short_doc
1085 else if global
.intro
== self then
1088 return global
.intro
.short_doc
1095 if not node
isa PPropdef then
1098 assert n
isa PPropdef
1104 if d
.n_comment
.is_empty
then
1112 redef class MMSignature
1113 # Htlm transcription of the signature (with nested links)
1114 meth to_html
(dctx
: DocContext): String
1116 var res
= new String
1119 res
.append
(self[0].html_link
(dctx
))
1120 for i
in [1..arity
[ do
1122 res
.append
(self[i
].html_link
(dctx
))
1126 if return_type
!= null then
1128 res
.append
(return_type
.html_link
(dctx
))
1135 # Htlm transcription of the type (with nested links)
1136 meth html_link
(dctx
: DocContext): String do return to_s
1139 redef class MMTypeSimpleClass
1140 redef meth html_link
(dctx
) do return local_class
.html_link
(dctx
)
1143 redef class MMTypeGeneric
1144 redef meth html_link
(dctx
)
1146 var res
= local_class
.html_link
(dctx
)
1148 res
.append
(params
[0].html_link
(dctx
))
1149 for i
in [1..params
.length
[ do
1151 res
.append
(params
[i
].html_link
(dctx
))
1158 var c
= new DocContext