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 = "doc"
31 var github_repo
: nullable String = null
32 # Content of a generated file
33 var _stage_context
: StageContext = new StageContext(null)
35 # Add a string in the content
37 _stage_context
.content
.add
(s
)
38 _stage_context
.validate
= true
41 # Add a string in the content iff some other string are added
42 fun stage
(s
: String) do _stage_context
.content
.add
(s
)
44 # Create a new stage in the content
45 fun open_stage
do _stage_context
= new StageContext(_stage_context
)
47 # Close the current stage in the content
50 var s
= _stage_context
.parent
51 if _stage_context
.validate
then
52 s
.content
.add_all
(_stage_context
.content
)
59 # Write the content to a new file
60 fun write_to
(filename
: String)
62 var f
= new OFStream.open
(filename
)
63 for s
in _stage_context
.content
do
72 _stage_context
= new StageContext(null)
75 # Sorter of entities in alphabetical order
76 var _sorter
: AlphaSorter[MMEntity] = new AlphaSorter[MMEntity]
78 # Sort entities in the alphabetical order
79 fun sort
(array
: Array[MMEntity])
84 readable var _opt_dir
: OptionString = new OptionString("Directory where doc is generated", "-d", "--dir")
85 readable var _opt_source
: OptionString = new OptionString("What link for source (%f for filename, %l for first line, %L for last line)", "--source")
86 readable var _opt_public
: OptionBool = new OptionBool("Generate only the public API", "--public")
87 readable var _opt_private
: OptionBool = new OptionBool("Generate the private API", "--private")
88 readable var _opt_nodot
: OptionBool = new OptionBool("Do not generate graphes with graphviz", "--no-dot")
89 readable var _opt_sharedir
: OptionString = new OptionString("Directory containing the nitdoc files", "--sharedir")
91 readable var _opt_custom_menu_items
: OptionString = new OptionString("Items displayed in menu before the 'Overview' item (Each item must be enclosed in 'li' tags)", "--custom-menu-items")
92 readable var _opt_custom_title
: OptionString = new OptionString("Title displayed in the top of the Overview page and as suffix of all page names", "--custom-title")
93 readable var _opt_custom_overview_text
: OptionString = new OptionString("Text displayed as introduction of Overview page before the modules list", "--custom-overview-text")
94 readable var _opt_custom_footer_text
: OptionString = new OptionString("Text displayed as footer of all pages", "--custom-footer-text")
95 readable var _opt_github_repo_name
: OptionString = new OptionString("GitHub repo name, example: --github MyRepoName", "--github")
96 var sharedir
: nullable String
100 if self._opt_public
.value
== true then return true
104 fun with_private
: Bool
106 if self._opt_private
.value
== true then return true
110 # The current processed filename
113 # The main virtual module
114 var mainmod
: nullable MMVirtualModule
116 redef fun perform_work
(mods
)
118 mainmod
= new MMVirtualModule(self, mods
)
122 sys
.system
("cp -r '{sharedir.to_s}'/* {dir}/")
124 # Compute the set of direct owned nested modules
125 var owns
= new HashMap[MMModule, Array[MMModule]]
126 for mod
in modules
do
127 owns
[mod
] = new Array[MMModule]# [mod]
129 for mod
in modules
do
130 if mod
== mainmod
then continue
131 var d
= mod
.directory
134 if o
!= null and o
!= mod
then
138 if dp
== null or dp
== d
then break
143 # Builds the various module hierarchies
144 var mnh
= new PartialOrder[MMModule] # nested module hierarchy
145 var tmh
= new PartialOrder[MMModule] # top module import hierrchy
146 var ms
= mainmod
.mhe
.linear_extension
.reversed
148 if ms
== mainmod
then continue
149 m
.mnhe_
= mnh
.add
(m
, owns
[m
])
150 var pub
= new Array[MMModule]
151 for m2
in m
.mhe
.greaters
do
152 if m2
.toplevel_owner
!= m2
and m2
.toplevel_owner
!= m
.toplevel_owner
then continue
153 if m
.mnhe
<= m2
then continue
154 if m
.visibility_for
(m2
) <= 0 then
156 else if m
.visibility_for
(m2
) == 1 then
161 m
.tmhe_
= tmh
.add
(m
, pub
)
164 var head
= "<meta charset=\"utf-8\
">" +
165 "<script type=\"text
/javascript\
" src=\"scripts
/jquery-1
.7
.1.min
.js\
"></script>\n" +
166 "<script type=\"text
/javascript\
" src=\"quicksearch-list
.js\
"></script>\n" +
167 "<script type=\"text
/javascript\
" src=\"scripts
/js-facilities
.js\
"></script>\n" +
168 "<link rel=\"stylesheet\
" href=\"styles
/main
.css\
" type=\"text
/css\
" media=\"screen\
" />"
170 var custom_items
= ""
171 if self._opt_custom_menu_items
.value
!= null then custom_items
= self._opt_custom_menu_items
.value
.as(not null)
173 var action_bar
= "<header><nav class='main'><ul>{custom_items}<li class=\"current\
">Overview</li><li><a href='full-index.html'>Full Index</a></li><li><a href=\"help
.html\
">Help</a></li><li id=\"liGitHub\
" class=\"\
"><a id=\"logGitHub\
" class=\"btn\
" ><img id=\"imgGitHub\
" src=\"resources
/icons
/github-icon
.png\
" /></a><div class=\"popover bottom\
"><div class=\"arrow\
"></div><div><label id=\"lbloginGit\
" for=\"login\
">Username</label><input id=\"loginGit\
" type=\"text\
" name=\"login\
"><label id=\"logginMessage\
" >Hello <a id=\"githubAccount\
" ><strong id=\"nickName\
"></strong></a></label></div><div><label id=\"lbpasswordGit\
" for=\"password\
">Password</label><input id=\"passwordGit\
" type=\"password\
" name=\"password\
"><div><label id=\"lbrepositoryGit\
" for=\"repository\
">Repository</label><input id=\"repositoryGit\
" type=\"text\
" name=\"repository\
"></div><div><label id=\"lbbranchGit\
" for=\"branch\
">Branch</label><input id=\"branchGit\
" type=\"text\
" name=\"branch\
"></div></div><div id=\"divlogIn\
"><a id=\"signIn\
" >Sign In</a></div></div></li></ul></nav></header>\n"
174 var custom_title
= "Nitdoc"
175 if self._opt_custom_title
.value
!= null then custom_title
= self._opt_custom_title
.value
.as(not null)
177 var overview_text
= ""
178 if self._opt_custom_overview_text
.value
!= null then overview_text
= self._opt_custom_overview_text
.value
.as(not null)
181 if self._opt_custom_footer_text
.value
!= null then footer_text
= self._opt_custom_footer_text
.value
.as(not null)
184 self.filename
= "index.html"
187 add
("<!DOCTYPE html>")
188 add
("<html><head>{head}<title>Overview | {custom_title}</title></head><body>\n")
190 add
("<div class=\"page\
">")
191 add
("<div class=\"content fullpage\
">")
192 add
("<h1>{custom_title}</h1>\n<article class='overview'>{overview_text}</article><article class='overview'><h2>Modules</h2><ul>")
193 var modss
= mainmod
.mhe
.greaters_and_self
.to_a
196 if not mod
.is_toplevel
then continue
197 if not mod
.require_doc
(self) then continue
198 assert mod
isa MMSrcModule
199 add
("<li>{mod.html_link(self)} {mod.short_doc}</li>")
205 op
.append
("digraph dep \{ rankdir=BT; node[shape=none,margin=0,width=0,height=0,fontsize=10]; edge[dir=none,color=gray]; ranksep=0.2; nodesep=0.1;\n")
207 if not mod
.is_toplevel
then continue
208 if not mod
.require_doc
(self) then continue
209 op
.append
("\"{mod.name}\
"[URL=\"{mod.html_name}.html\
"];\n")
210 for mod2
in mod
.tmhe
.direct_greaters
do
211 if not modss
.has
(mod2
) then continue
212 op
.append
("\"{mod.name}\
"->\"{mod2.name}\
";\n")
216 self.gen_dot
(op
.to_s
, "dep", "Modules hierarchy")
217 add
("</article></div>")
219 add
("<footer>{footer_text}</footer>")
220 add
("</body></html>\n")
221 write_to
("{dir}/index.html")
223 # Generate page for modules
224 for mod
in modules
do
225 if mod
== mainmod
then continue
226 assert mod
isa MMSrcModule
227 if not mod
.require_doc
(self) then continue
228 self.filename
= mod
.html_name
229 action_bar
= "<header><nav class='main'><ul>{custom_items}<li><a href='./index.html'>Overview</a></li><li class=\"current\
">{mod.name}</li><li><a href='full-index.html'>Full Index</a></li><li><a href=\"help
.html\
">Help</a></li><li id=\"liGitHub\
" class=\"\
"><a id=\"logGitHub\
" class=\"btn\
" ><img id=\"imgGitHub\
" src=\"resources
/icons
/github-icon
.png\
" /></a><div class=\"popover bottom\
"><div class=\"arrow\
"></div><div><label id=\"lbloginGit\
" for=\"login\
">Username</label><input id=\"loginGit\
" type=\"text\
" name=\"login\
"><label id=\"logginMessage\
" >Hello <a id=\"githubAccount\
" ><strong id=\"nickName\
"></strong></a></label></div><div><label id=\"lbpasswordGit\
" for=\"password\
">Password</label><input id=\"passwordGit\
" type=\"password\
" name=\"password\
"></div><div><label id=\"lbrepositoryGit\
" for=\"repository\
">Repository</label><input id=\"repositoryGit\
" type=\"text\
" name=\"repository\
"></div><div><label id=\"lbbranchGit\
" for=\"branch\
">Branch</label><input id=\"branchGit\
" type=\"text\
" name=\"branch\
"></div><div id=\"divlogIn\
"><a id=\"signIn\
" >Sign In</a></div></div></li></ul></nav></header>\n"
232 add
("<!DOCTYPE html>")
233 add
("<html><head>{head}<title>{mod.name} module | {custom_title}</title></head><body>\n")
235 add
("<div class=\"page\
">")
236 mod
.file_page_doc
(self)
238 add
("<footer>{footer_text}</footer>")
239 add
("</body></html>\n")
240 write_to
("{dir}/{mod.html_name}.html")
243 # Generate pages for global classes
244 for c
in mainmod
.local_classes
do
245 if not c
.require_doc
(self) then continue
246 self.filename
= c
.html_name
247 action_bar
= "<header><nav class='main'><ul>{custom_items}<li><a href='./index.html'>Overview</a></li><li>{c.global.intro.mmmodule.toplevel_owner.html_link(self)}</li><li class=\"current\
">{c.name}</li><li><a href='full-index.html'>Full Index</a></li><li><a href=\"help
.html\
">Help</a></li><li id=\"liGitHub\
" class=\"\
"><a id=\"logGitHub\
" class=\"btn\
" ><img id=\"imgGitHub\
" src=\"resources
/icons
/github-icon
.png\
" /></a><div class=\"popover bottom\
"><div class=\"arrow\
"></div><div><label id=\"lbloginGit\
" for=\"login\
">Username</label><input id=\"loginGit\
" type=\"text\
" name=\"login\
"><label id=\"logginMessage\
" >Hello <a id=\"githubAccount\
" ><strong id=\"nickName\
"></strong></a></label></div><div><label id=\"lbpasswordGit\
" for=\"password\
">Password</label><input id=\"passwordGit\
" type=\"password\
" name=\"password\
"></div><div><label id=\"lbrepositoryGit\
" for=\"repository\
">Repository</label><input id=\"repositoryGit\
" type=\"text\
" name=\"repository\
"></div><div><label id=\"lbbranchGit\
" for=\"branch\
">Branch</label><input id=\"branchGit\
" type=\"text\
" name=\"branch\
"></div><div id=\"divlogIn\
"><a id=\"signIn\
" >Sign In</a></div></div></li></ul></nav></header>\n"
250 add
("<!DOCTYPE html>")
251 add
("<html><head>{head}<title>{c.name} class | {custom_title}</title></head><body>\n")
253 add
("<div class=\"page\
">")
254 c
.file_page_doc
(self)
256 add
("<footer>{footer_text}</footer>")
257 add
("</body></html>\n")
258 write_to
("{dir}/{c.html_name}.html")
261 self.filename
= "fullindex"
262 action_bar
= "<header><nav class='main'><ul>{custom_items}<li><a href='./index.html'>Overview</a></li><li class=\"current\
">Full Index</li><li><a href=\"help
.html\
">Help</a></li><li id=\"liGitHub\
" class=\"\
"><a id=\"logGitHub\
" class=\"btn\
" ><img id=\"imgGitHub\
" src=\"resources
/icons
/github-icon
.png\
" /></a><div class=\"popover bottom\
"><div class=\"arrow\
"></div><div><label id=\"lbloginGit\
" for=\"login\
">Username</label><input id=\"loginGit\
" type=\"text\
" name=\"login\
"><label id=\"logginMessage\
" >Hello <a id=\"githubAccount\
" ><strong id=\"nickName\
"></strong></a></label></div><div><label id=\"lbpasswordGit\
" for=\"password\
">Password</label><input id=\"passwordGit\
" type=\"password\
" name=\"password\
"></div><div><label id=\"lbrepositoryGit\
" for=\"repository\
">Repository</label><input id=\"repositoryGit\
" type=\"text\
" name=\"repository\
"></div><div><label id=\"lbbranchGit\
" for=\"branch\
">Branch</label><input id=\"branchGit\
" type=\"text\
" name=\"branch\
"></div><div id=\"divlogIn\
"><a id=\"signIn\
" >Sign In</a></div></div></li></ul></nav></header>\n"
265 add
("<!DOCTYPE html>")
266 add
("<html><head>{head}<title>Full Index | {custom_title}</title></head><body>\n")
268 add
("<div class=\"page\
">")
269 add
("<div class=\"content fullpage\
">")
270 mainmod
.file_index_page_doc
(self)
273 add
("<footer>{footer_text}</footer>")
274 add
("</body></html>\n")
275 write_to
("{dir}/full-index.html")
277 self.filename
= "quicksearch-list"
279 mainmod
.file_quicksearch_list_doc
(self)
280 write_to
("{dir}/quicksearch-list.js")
283 # Add or not a tag for the github repository
284 fun addGithubInformation
do
285 if not github_repo
== null then add
("<div id=\"repoName\
" name=\"{github_repo.to_s}\
"></div>")
288 # Add a (source) link fo a given location
289 fun show_source
(l
: Location)
291 var s
= opt_source
.value
293 add
("({l.file.filename.simplify_path})")
295 # THIS IS JUST UGLY ! (but there is no replace yet)
296 var x
= s
.split_with
("%f")
297 s
= x
.join
(l
.file
.filename
.simplify_path
)
298 x
= s
.split_with
("%l")
299 s
= x
.join
(l
.line_start
.to_s
)
300 x
= s
.split_with
("%L")
301 s
= x
.join
(l
.line_end
.to_s
)
302 add
(" (<a href=\"{s}\
">show code</a>)")
306 # Generate a clicable graphiz image using a dot content.
307 # `name' refer to the filename (without extension) and the id name of the map.
308 # `name' must also match the name of the graph in the dot content (eg. digraph NAME {...)
309 fun gen_dot
(dot
: String, name
: String, alt
: String)
311 if opt_nodot
.value
then return
312 var f
= new OFStream.open
("{self.dir}/{name}.dot")
315 sys
.system
("\{ test -f {self.dir}/{name}.png && test -f {self.dir}/{name}.s.dot && diff {self.dir}/{name}.dot {self.dir}/{name}.s.dot >/dev/null 2>&1 ; \} || \{ cp {self.dir}/{name}.dot {self.dir}/{name}.s.dot && dot -Tpng -o{self.dir}/{name}.png -Tcmapx -o{self.dir}/{name}.map {self.dir}/{name}.s.dot ; \}")
316 self.add
("<article class=\"graph\
"><img src=\"{name}.png\
" usemap=\"#{name}\" style=\"margin:auto\" alt=\"{alt}\"/></article>")
317 var fmap
= new IFStream.open
("{self.dir}/{name}.map")
318 self.add
(fmap
.read_all
)
327 option_context
.add_option
(opt_public
)
328 option_context
.add_option
(opt_private
)
329 option_context
.add_option
(opt_dir
)
330 option_context
.add_option
(opt_source
)
331 option_context
.add_option
(opt_nodot
)
332 option_context
.add_option
(opt_sharedir
)
333 option_context
.add_option
(opt_custom_title
)
334 option_context
.add_option
(opt_custom_menu_items
)
335 option_context
.add_option
(opt_custom_overview_text
)
336 option_context
.add_option
(opt_custom_footer_text
)
337 option_context
.add_option
(opt_github_repo_name
)
340 redef fun process_options
343 var d
= opt_dir
.value
344 if d
!= null then dir
= d
346 if not opt_nodot
.value
then
347 # Test if dot is runable
348 var res
= sys
.system
("sh -c dot </dev/null >/dev/null 2>&1")
350 stderr
.write
"--no-dot implied since `dot' is not available. Try to install graphviz.\n"
351 opt_nodot
.value
= true
355 sharedir
= opt_sharedir
.value
356 if sharedir
== null then
357 var dir
= "NIT_DIR".environ
359 dir
= "{sys.program_name.dirname}/../share/nitdoc"
360 if dir
.file_exists
then sharedir
= dir
362 dir
= "{dir}/share/nitdoc"
363 if dir
.file_exists
then sharedir
= dir
365 if sharedir
== null then
366 fatal_error
(null, "Error: Cannot locate nitdoc shared files. Uses --sharedir or envvar NIT_DIR.")
368 dir
= "{sharedir.to_s}/scripts/js-facilities.js"
369 if sharedir
== null then
370 fatal_error
(null, "Error: Invalid nitdoc shared files. Check --sharedir or envvar NIT_DIR.")
374 var git
= opt_github_repo_name
.value
375 if not git
== null then github_repo
= git
378 redef fun handle_property_conflict
(lc
, impls
)
380 # THIS IS SO UGLY! See MMVirtualModule
381 if lc
.mmmodule
== self.mainmod
then
382 return # We just accept, so one in impls is arbitrary inherited
388 # A virtual module is used to work as an implicit main module that combine unrelated modules
389 # Since conflict may arrise in a virtual module (the main method for instance) conflicts are disabled
390 class MMVirtualModule
392 init(ctx
: MMContext, mods
: Array[MMModule])
394 # We need to compute the whole metamodel since there is no mmbuilder to do it
395 super(" main".to_symbol
, mods
.first
.directory
, ctx
, new Location(null,0,0,0,0))
396 ctx
.add_module
(self, mods
)
398 self.add_super_module
(m
, 1)
400 self.import_global_classes
401 self.import_local_classes
402 for c
in self.local_classes
do
403 c
.compute_super_classes
405 for c
in self.local_classes
do
410 redef fun require_doc
(dctx
) do return false
413 # Conditionnal part of the text content of a DocContext
415 # Content of the current stage
416 readable var _content
: Array[String] = new Array[String]
418 # Is a normal string already added?
419 readable writable var _validate
: Bool = false
421 # Parent stage is any
422 readable var _parent
: nullable StageContext = null
424 init(parent
: nullable StageContext) do _parent
= parent
428 # Efficiently sort object with their to_s method
429 class AlphaSorter[E
: Object]
430 super AbstractSorter[E
]
431 redef fun compare
(a
, b
)
451 # Keep track of to_s values
452 var _dico
: HashMap[Object, String] = new HashMap[Object, String]
457 # Generalization of metamodel entities
460 fun html_link
(dctx
: DocContext): String is abstract
462 # Return a one liner description
463 fun short_doc
: String do return " "
465 # The doc node from the AST
466 # Return null is none
467 fun doc
: nullable ADoc do return null
469 # Return a JSON entry for quicksearch list
470 fun json_entry
(dctx
: DocContext): String is abstract
472 # Return the qualified name as string
473 fun qualified_name
: String is abstract
479 redef fun html_link
(dctx
) do
480 if short_doc
== " " then
481 return "<a href=\"{html_name}.html\
"\">{self}</a
>"
483 return "<a href
=\
"{html_name}.html\" title
=\
"{short_doc}\">{self}</a
>"
487 fun html_anchor: String do
488 return "<a id
=\
"MOD_{html_name}\"></a
>"
491 fun html_link_to_anchor: String do
492 return "<a href
=\
"#MOD_{html_name}\" title
=\
"Jump to definitions from module {html_name}\">{self}</a
>"
495 redef fun json_entry(dctx) do
496 return "\
{txt:\"{self.qualified_name}\
",url:\"{html_name}.html\
"\},"
499 redef fun qualified_name
do
500 var buffer
= new Buffer
501 for m
in mnhe
.smallers
do
502 buffer
.append
("{m.html_name}::")
504 buffer
.append
("{self.name}")
508 fun require_doc
(dctx
: DocContext): Bool
510 if dctx
.public_only
and not is_toplevel
then return false
514 # Return true if the module is a top-level owner or a top-level module
515 fun is_toplevel
: Bool
517 var pd
= directory
.parent
518 return pd
== null or (pd
.owner
== null and directory
.owner
== self)
521 # Element in the module nesting tree
522 fun mnhe
: PartialOrderElement[MMModule] do return mnhe_
.as(not null)
523 var mnhe_
: nullable PartialOrderElement[MMModule] = null
525 # Element in the top level module importation hierarchy
526 fun tmhe
: PartialOrderElement[MMModule] do return tmhe_
.as(not null)
527 var tmhe_
: nullable PartialOrderElement[MMModule] = null
529 fun toplevel_owner
: MMModule
533 var ds
= m
.mnhe
.direct_smallers
534 if ds
.length
== 0 then return m
535 if ds
.length
== 1 then m
= ds
.first
else abort
539 fun html_name
: String
544 fun direct_owner
: nullable MMModule
547 while d
.owner
== self do d
= d
.parent
.as(not null)
551 # Fill the body for the page associated to the module
552 fun file_page_doc
(dctx
: DocContext)
554 dctx
.add
("<div class=\"menu\
">\n")
556 var mods
= new Array[MMModule]
557 mods
= self.mhe
.greaters
.to_a
561 dctx
.stage
("<nav>\n")
562 dctx
.stage
("<h3>Module Hierarchy</h3>\n")
563 dctx
.stage
("<h4>All dependencies</h4>\n")
566 if not mod
.require_doc
(dctx
) then continue
567 if self.mnhe
<= mod
then continue # do not want nested stuff
568 if mod
.direct_owner
!= null and not mod
.direct_owner
.mnhe
<= self then continue # not in the right nesting
569 dctx
.add
("<li>{mod.html_link(dctx)}</li>")
571 dctx
.stage
("</ul>\n")
573 mods
= self.mhe
.smallers
.to_a
575 dctx
.stage
("<h4>All clients</h4>\n")
578 if not mod
.require_doc
(dctx
) then continue
579 if self.mnhe
<= mod
then continue # do not want nested stuff
580 if mod
.direct_owner
!= null and not mod
.direct_owner
.mnhe
<= self then continue # not in the right nesting
581 dctx
.add
("<li>{mod.html_link(dctx)}</li>")
583 dctx
.stage
("</ul>\n")
584 dctx
.stage
("</nav>\n")
587 if not dctx
.public_only
then
588 mods
= self.mnhe
.direct_greaters
.to_a
591 dctx
.stage
("<nav>\n")
592 dctx
.stage
("<h3>Nested Modules</h3><ul>\n")
594 if not mod
.require_doc
(dctx
) then continue
595 dctx
.add
("<li>{mod.html_link(dctx)}</li>")
597 dctx
.stage
("</ul></nav>\n")
601 dctx
.add
("</div>") # metadata
603 dctx
.add
("<div class=\"content\
">\n")
604 dctx
.add
("<h1>{name}</h1>\n")
605 dctx
.add
("<div class='subtitle'>module ")
606 for m
in mnhe
.smallers
do
607 dctx
.add
("{m.html_link(dctx)}::")
609 dctx
.add
("{self.name}</div>\n")
611 dctx
.add
("<section class='description'>\n")
615 dctx
.add
("<div id=\"description\
">\n")
616 dctx
.add
("<pre>{doc.to_html}</pre>\n")
621 op
.append
("digraph {name} \{ rankdir=BT; node[shape=none,margin=0,width=0,height=0,fontsize=10]; edge[dir=none,color=gray]; ranksep=0.2; nodesep=0.1;\n")
622 var ms
= new Array[nullable MMModule]
624 var m0
: nullable MMModule = self
630 var cla
= new HashSet[MMModule]
632 for m0
in self.mhe
.greaters
do
633 if not m0
.require_doc
(dctx
) then continue
634 if self.visibility_for
(m0
) <= 1 then continue # private or hidden
635 if self.mnhe
<= m0
then continue # do not want nested stuff
636 if m0
.direct_owner
!= null and not m0
.direct_owner
.mnhe
<= self then continue # not in the right nesting
639 for m0
in self.mhe
.smallers
do
640 if not m0
.require_doc
(dctx
) then continue
641 if m0
.visibility_for
(self) <= 1 then continue # private or hidden
642 if m0
.direct_owner
!= null and not m0
.direct_owner
.mnhe
<= self then continue # not in the right nesting
645 for m0
in self.mnhe
.smallers
do
651 op
.append
("subgraph \"cluster_
{m0.name}\
"\{\n")
654 if c
.direct_owner
!= m0
then continue
656 op
.append
("\"{c.name}\
"[shape=box,margin=0.03];\n")
658 op
.append
("\"{c.name}\
"[URL=\"{c.html_name}.html\
"];\n")
662 op
.append
("\"{m0.name}\
"[URL=\"{m0.html_name}.html\
"];\n")
663 for c
in m0
.mhe
.direct_greaters
do
664 if not cla
.has
(c
) then continue
665 op
.append
("\"{m0.name}\
"->\"{c.name}\
";\n")
670 # Close the nesting subgraph
676 for c2
in c
.tmhe
.direct_greaters
do
677 if not cla
.has
(c2
) then continue
678 op
.append
("\"{c.name}\
"->\"{c2.name}\
";\n")
682 dctx
.gen_dot
(op
.to_s
, name
.to_s
, "Dependency graph for module {name}")
683 dctx
.add
("</section>")
685 var clas
= new Array[MMLocalClass]
686 var props
= new HashMap[MMGlobalProperty, Array[MMLocalProperty]]
687 var gprops
= new Array[MMLocalProperty]
690 for g
in m
.global_classes
do
692 if not lc
.require_doc
(dctx
) then continue
693 var im
= g
.intro
.mmmodule
694 if self.visibility_for
(im
) <= 1 then continue # private import or invisible import
696 for lc2
in lc
.crhe
.greaters_and_self
do
697 if not lc2
isa MMSrcLocalClass then continue
698 if not self.mnhe
<= lc2
.mmmodule
then continue # not introduced/redefined here/stolen
701 if not keep
then continue
703 lc
.compute_super_classes
704 for gp
in lc
.global_properties
do
705 if self.visibility_for
(gp
.intro
.local_class
.mmmodule
) <= 1 then continue # private import or invisible import
707 var mp
= lp
.local_class
.mmmodule
708 if not self.mnhe
<= mp
then continue # not introduced/redefined here/stolen
710 if not lp
.require_doc
(dctx
) then continue
711 if props
.has_key
(lp
.global
) then
712 if not props
[lp
.global
].has
(lp
) then
713 props
[lp
.global
].add
(lp
)
716 props
[lp
.global
] = [lp
]
717 gprops
.add
(lp
.global
.intro
)
722 dctx
.add
("<section class=\"module\
">\n")
724 dctx
.stage
("<article class=\"classes filterable\
">\n")
725 dctx
.stage
("<h2>Classes</h2>\n")
729 if self.mnhe
<= lc
.global
.intro
.mmmodule
then
730 dctx
.add
("<li class='intro'><span title='introduced in this module'>I</span> ")
732 dctx
.add
("<li class='redef'><span title='refined in this module'>R</span> ")
734 dctx
.add
("{lc.html_link(dctx)}</li>\n")
736 dctx
.stage
("</ul></article>\n")
740 dctx
.stage
("<article class=\"properties filterable\
">\n")
741 dctx
.stage
("<h2>Properties</h2>\n")
748 if gp
.intro
isa MMAttribute then continue
750 var lpi
= self[gp
.intro
.local_class
.global
][gp
]
753 dctx
.add
("<li class='intro'><span title='introduction in an other module'>I</span> {lpi.html_open_link(dctx)}{lpi.html_name} ({lpi.local_class})</a></li>\n")
756 dctx
.add
("<li class='intro'><span title='introduction in this module'>I</span> {lpi.html_name}")
757 dctx
.add
(" ({lpi.local_class})</li>\n")
759 if lps
.length
>= 1 then
762 dctx
.add
("<li class='redef'><span title='redefinition'>R</span> {lp.html_open_link(dctx)}{lp.html_name} ({lp.local_class})</a></li>")
766 dctx
.stage
("</ul></article>\n")
768 dctx
.add
("</section>\n")
772 # Fill the body for the page associated to the full index
773 fun file_index_page_doc
(dctx
: DocContext)
776 dctx
.add
("<h1>Full Index</h1>\n")
778 var clas
= new Array[MMLocalClass]
779 var props
= new HashMap[MMGlobalProperty, Array[MMLocalProperty]]
780 var gprops
= new Array[MMLocalProperty]
781 var mods
= new Array[MMModule]
782 for m
in mhe
.greaters_and_self
do
783 if not m
.require_doc
(dctx
) then continue
786 for g
in global_classes
do
788 if not lc
.require_doc
(dctx
) then continue
790 for gp
in lc
.global_properties
do
792 if not lp
.require_doc
(dctx
) then continue
793 if props
.has_key
(lp
.global
) then
794 if not props
[lp
.global
].has
(lp
) then
795 props
[lp
.global
].add
(lp
)
798 props
[lp
.global
] = [lp
]
799 gprops
.add
(lp
.global
.intro
)
804 dctx
.stage
("<article class=\"modules filterable\
">\n")
805 dctx
.stage
("<h2>Modules</h2>\n")
809 dctx
.add
("<li>{m.html_link(dctx)}</li>")
811 dctx
.stage
("</ul></article>\n")
815 dctx
.stage
("<article class=\"classes filterable\
">\n")
816 dctx
.stage
("<h2>Classes</h2>\n")
820 dctx
.add
("<li>{lc.html_link(dctx)}</li>")
822 dctx
.stage
("</ul></article>\n")
826 dctx
.stage
("<article class=\"properties filterable\
">\n")
827 dctx
.stage
("<h2>Properties</h2>\n")
834 if gp
.intro
isa MMAttribute then continue
836 var lpi
= self[gp
.intro
.local_class
.global
][gp
]
839 dctx
.add
("<li class='intro'><span title='introduction'>I</span> {lpi.html_open_link(dctx)}{lpi.html_name} ({lpi.local_class})</a></li>\n")
840 if lps
.length
>= 1 then
843 dctx
.add
("<li class='redef'><span title='redefinition'>R</span> {lp.html_open_link(dctx)}{lp.html_name} ({lp.local_class})</a></li>\n")
847 dctx
.stage
("</ul></article>\n")
851 # Fill the quicksearch list JSON object
852 fun file_quicksearch_list_doc
(dctx
: DocContext)
854 var entities
= new HashMap[String, Array[MMEntity]]
855 var props
= new HashMap[MMGlobalProperty, Array[MMLocalProperty]]
856 for m
in mhe
.greaters_and_self
do
857 if not m
.require_doc
(dctx
) then continue
858 var a
= new Array[MMEntity]
860 entities
[m
.html_name
] = a
862 for g
in global_classes
do
864 if not lc
.require_doc
(dctx
) then continue
865 var a
= new Array[MMEntity]
867 entities
[lc
.html_name
] = a
868 for gp
in lc
.global_properties
do
870 if not lp
.require_doc
(dctx
) then continue
871 if lp
.kind
== "var" then continue
872 if props
.has_key
(lp
.global
) then
873 if not props
[lp
.global
].has
(lp
) then
874 props
[lp
.global
].add
(lp
)
877 props
[lp
.global
] = [lp
]
883 entities
[k
.short_name
] = v
886 var keys
= entities
.keys
.to_a
887 var sorter
= new AlphaSorter[String]
891 dctx
.stage
("var entries = \{")
893 dctx
.add
("\"{key}\
": [")
894 for entity
in entities
[key
] do
895 dctx
.add
(entity
.json_entry
(dctx
))
904 redef class MMGlobalProperty
905 # Return the short name of the property
906 fun short_name
: String do
907 return self.intro
.html_name
911 redef class MMLocalProperty
913 # Anchor of the property description in the module html file
914 fun html_anchor
: String
916 return "PROP_{self.mmmodule.toplevel_owner}_{local_class}_{cmangle(name)}"
919 redef fun json_entry
(dctx
) do
920 return "\{txt:\"{qualified_name}\",url
:\
"{local_class.html_name}.html#{html_anchor}\"\
},"
923 redef fun qualified_name do
924 return "{intro_module.qualified_name}::{local_class.html_name}::{html_name}"
927 fun html_open_link(dctx: DocContext): String
929 if not require_doc(dctx) then print "not required
{self}"
930 var title = "{html_name}{signature.to_s}"
931 if short_doc != " 
;" then
932 title += " #{short_doc}"
934 return "<a href=\"{local_class.html_name}.html
#{html_anchor}\" title=\"{title}\">"
937 fun html_name
: String
939 return self.name
.to_s
.html_escape
942 redef fun html_link
(dctx
)
944 if not require_doc
(dctx
) then print
"not required {self}"
945 var title
= "{html_name}{signature.to_s}"
946 if short_doc
!= " " then
947 title
+= " #{short_doc}"
949 return "<a href=\"{local_class.html_name}.html
#{html_anchor}\" title=\"{title}\">{html_name}</a>"
952 fun html_link_special
(dctx
: DocContext, lc
: MMLocalClass): String
954 if not require_doc
(dctx
) then print
"not required {self}"
955 var title
= "{html_name}{signature_for(lc.get_type)}"
956 if short_doc
!= " " then
957 title
+= " #{short_doc}"
959 return "<a href=\"{lc.html_name}.html
#{html_anchor}\" title=\"{title}\">{html_name}</a>"
962 # Kind of property (fun, attr, etc.)
963 fun kind
: String is abstract
970 else if global
.intro
== self then
973 return global
.intro
.short_doc
980 if n
== null or not n
isa APropdef then
987 if d
.n_comment
.is_empty
then
994 # The most specific module in the nesting hierarchy that exports the intro of self
995 fun intro_module
: MMModule
997 var m
= global
.intro
.mmmodule
998 var mo
= m
.direct_owner
999 while mo
!= null and mo
.visibility_for
(m
) >= 2 do
1006 # Is the intro of self exported by the top-level module ?
1007 fun is_toplevel
: Bool
1009 var m
= intro_module
1010 return m
== m
.toplevel_owner
1013 # Return true if the global property must be documented according to the visibility configured
1014 fun require_doc
(dctx
: DocContext): Bool
1016 if global
.visibility_level
== 3 and not dctx
.with_private
then return false # Private
1017 if dctx
.public_only
then
1018 var m
= intro_module
1019 if m
!= m
.toplevel_owner
then return false # Unexported
1024 # Document the global property in the global class lc
1025 fun full_documentation
(dctx
: DocContext, lc
: MMLocalClass)
1027 var visibility
: String
1028 if global
.visibility_level
== 1 then
1029 visibility
= "public"
1030 else if global
.visibility_level
== 2 then
1031 visibility
= "protected"
1032 else if global
.visibility_level
== 3 then
1033 visibility
= "private"
1038 var intro_class
= global
.intro
.local_class
1039 var is_redef
= local_class
.global
!= intro_class
.global
or local_class
.mmmodule
.toplevel_owner
!= intro_class
.mmmodule
.toplevel_owner
1041 dctx
.add
("<article id=\"{html_anchor}\
" class=\"{kind} {visibility} {if is_redef then "redef" else ""}\
">\n")
1042 dctx
.add
("<h3 class=\"signature\
">{html_name}{signature.to_html(dctx, true)}</h3>\n")
1043 dctx
.add
("<div class=\"info\
">\n")
1044 #dctx.add("<p>LP: {self.mmmodule.html_link(dctx)}::{self.local_class.html_link(dctx)}::{self.html_link(dctx)}</p>")
1049 if not is_toplevel
then
1050 dctx
.add
("(unexported) ")
1052 if global
.visibility_level
== 2 then
1053 dctx
.add
("protected ")
1054 else if global
.visibility_level
== 3 then
1055 dctx
.add
("private ")
1058 dctx
.add
(" {intro_class.mmmodule.toplevel_owner.name}")
1059 if intro_class
.global
== lc
.global
then
1060 dctx
.add
("::{lc.name}")
1062 dctx
.add
("::{mmmodule[intro_class.global].html_link(dctx)}")
1065 dctx
.add
("::{mmmodule[intro_class.global][global].global.intro.html_link(dctx)}")
1067 dctx
.add
("::{html_name}")
1071 dctx
.add
("<div class=\"description\
">")
1073 # Collect all refinement of the global property in the same global property
1074 var lps
= new Array[MMLocalProperty]
1075 for l
in prhe
.greaters_and_self
do
1079 var introdoc
= false
1080 if global
.intro
.doc
!= null then
1082 if lp
.doc
== null then introdoc
= true
1086 dctx
.add
("<pre>{global.intro.doc.to_html}</pre>")
1089 var tlmods
= new Array[MMModule]
1091 var bm
= lp
.mmmodule
.toplevel_owner
1092 var lcm
= lc
.global
.intro
.mmmodule
1093 if lcm
.mhe
< lp
.mmmodule
then bm
= lcm
.toplevel_owner
1094 if not tlmods
.has
(bm
) then tlmods
.add
(bm
)
1098 # Document the top level property for the current top level module
1100 if tm
.global_classes
.has
(lc
.global
) then
1101 tlp
= tm
[lc
.global
][self.global
]
1103 else if tm
.global_classes
.has
(self.local_class
.global
) then
1104 # Self is the inherited property. Process it
1105 tlp
= tm
[self.local_class
.global
][self.global
]
1108 # We skip this module since the props defined by the module is
1112 var tlcm
= lc
.global
.intro
.mmmodule
.toplevel_owner
1113 if not tlcm
.mhe
<= tm
then
1114 dctx
.add
("<h4>In module {tm.html_link(dctx)} :</h4>")
1117 #dctx.add("<p>TLP: {tm} x {lc} : {tlp.full_name}</p>")
1120 if doc
!= null and (not introdoc
or global
.intro
.doc
!= doc
) then
1121 dctx
.add
("<pre>{doc.to_html}</pre>")
1124 if tlp
.local_class
.global
!= lc
.global
then
1125 dctx
.add
("inherited from {tlp.local_class.html_link(dctx)} ")
1127 if tm
!= tlp
.mmmodule
then
1128 dctx
.add
("defined by the module {tlp.mmmodule.html_link(dctx)} ")
1137 dctx
.stage
(". previously defined by:")
1139 var tl
= lp
.mmmodule
.toplevel_owner
1140 if tl
!= tm
then continue
1141 if lp
== tlp
then continue
1142 dctx
.add
(" {lp.mmmodule.html_link(dctx)}")
1143 if lp
.local_class
.global
!= lc
.global
then
1144 dctx
.add
(" for {lp.local_class.html_link(dctx)} ")
1154 #if doc != null and (not introdoc or global.intro.doc != doc) then
1155 # dctx.add("<pre>{doc.to_html}</pre>")
1162 dctx
.add
("</article>")
1165 redef class MMMethod
1166 redef fun kind
do return if global
.is_init
then "init" else "fun"
1168 redef class MMAttribute
1169 redef fun kind
do return "var"
1171 redef class MMTypeProperty
1172 redef fun kind
do return "type"
1175 redef class MMSrcModule
1189 if n
.n_moduledecl
== null then
1192 var np
= n
.n_moduledecl
1197 if d
.n_comment
.is_empty
then
1206 # Html transcription of the doc
1209 var res
= new Buffer
1210 for c
in n_comment
do
1211 res
.append
(c
.text
.substring_from
(1))
1213 return res
.to_s
.html_escape
1216 # Oneliner transcription of the doc
1219 return n_comment
.first
.text
.substring_from
(1).html_escape
1223 redef class MMLocalClass
1226 # Anchor of the class description in the module html file
1227 fun html_anchor
: String do return "CLASS_{self}"
1229 fun html_name
: String do return "{self}"
1231 redef fun html_link
(dctx
)
1233 if not require_doc
(dctx
) then print
"{dctx.filename}: not required {self}"
1234 if short_doc
== " " then
1235 return "<a href=\"{html_name}.html\
"\">{self}</a
>"
1237 return "<a href
=\
"{html_name}.html\" title
=\
"{short_doc}\">{self}</a
>"
1241 redef fun json_entry(dctx) do
1242 return "\
{txt:\"{qualified_name}\
",url:\"{html_name}.html\
"\},"
1245 redef fun qualified_name
do
1246 return "{intro_module.qualified_name}::{html_name}"
1249 redef fun short_doc
do return global
.intro
.short_doc
1251 redef fun doc
do return global
.intro
.doc
1255 if global
.is_interface
then
1257 else if global
.is_abstract
then
1258 return "abstract class"
1259 else if global
.is_enum
then
1266 # The most specific module in the nesting hierarchy that exports the intro of self
1267 fun intro_module
: MMModule
1269 var m
= global
.intro
.mmmodule
1270 var mo
= m
.direct_owner
1271 while mo
!= null and mo
.visibility_for
(m
) >= 2 do
1278 fun menu_link
(dctx
: DocContext, p
: MMLocalProperty)
1280 if p
.local_class
.global
!= self.global
then
1281 if p
.global
.intro
.local_class
.name
== "Object".to_symbol
then return
1282 if p
.global
.is_init
or p
isa MMTypeProperty then
1283 dctx
.add
("<li class='inherit'><span title='Inherited'>H</span> {p.html_link_special(dctx, self)}</li>\n")
1285 dctx
.add
("<li class='inherit'><span title='Inherited'>H</span> {p.html_link(dctx)}</li>\n")
1287 else if p
.global
.intro
.local_class
.global
== self.global
then
1288 dctx
.add
("<li class='intro'><span title='Introduced'>I</span> {p.html_link_special(dctx, self)}</li>\n")
1290 dctx
.add
("<li class='redef'><span title='Redefined'>R</span> {p.html_link_special(dctx, self)}</li>\n")
1294 # Return true if the global class must be documented according to the visibility configured
1295 fun require_doc
(dctx
: DocContext): Bool
1297 if global
.visibility_level
== 3 and not dctx
.with_private
then return false # Private
1298 if dctx
.public_only
then
1299 var m
= intro_module
1300 if m
!= m
.toplevel_owner
then return false # Unexported
1305 # Fill the body for the page associated to the global class
1306 fun file_page_doc
(dctx
: DocContext)
1308 dctx
.add
("<div class=\"menu\
">\n")
1310 var props
= new Array[MMLocalProperty]
1311 var inh
= new HashMap[MMLocalClass, Array[MMLocalProperty]]
1312 var inhs
= new Array[MMLocalClass]
1313 for g
in global_properties
do
1315 if not p
.require_doc
(dctx
) then continue
1316 if p
.local_class
.global
== global
or g
.is_init_for
(self) or p
isa MMTypeProperty then
1319 var lc
= mmmodule
[p
.local_class
.global
]
1320 if inh
.has_key
(lc
) then
1331 dctx
.add
("<nav class=\"properties filterable\
">\n")
1332 dctx
.add
("<h3>Properties</h3>\n")
1334 dctx
.stage
("<h4>Virtual Types</h4>\n<ul>\n")
1336 if p
isa MMTypeProperty then
1340 dctx
.stage
("</ul>\n")
1343 dctx
.stage
("<h4>Constructors</h4>\n<ul>\n")
1345 if p
.global
.is_init_for
(self) then
1349 dctx
.stage
("</ul>\n")
1352 dctx
.stage
("<h4>Methods</h4>\n<ul>\n")
1354 if not p
.global
.is_init
and p
isa MMMethod then
1358 dctx
.stage
("</ul>\n")
1360 dctx
.add
("</nav>\n")
1362 dctx
.add
("<nav class=\"inheritance filterable\
">\n")
1363 dctx
.add
("<h3>Inheritance</h3>\n")
1364 dctx
.add
("<h4>Superclasses</h4>\n<ul>\n")
1365 for lc
in cshe
.linear_extension
do
1366 if lc
== self then continue
1367 if not lc
.require_doc
(dctx
) then continue
1368 dctx
.add
("<li>{lc.html_link(dctx)}</li>\n")
1371 if cshe
.smallers
.length
== 0 then
1372 dctx
.add
("<h4>No Known Subclasses</h4>\n")
1373 else if cshe
.smallers
.length
<= 100 then
1374 dctx
.add
("<h4>Subclasses</h4>\n")
1376 for lc
in cshe
.smallers
do
1377 if not lc
.require_doc
(dctx
) then continue
1378 dctx
.add
("<li>{lc.html_link(dctx)}</li>\n")
1381 else if cshe
.direct_smallers
.length
<= 100 then
1382 dctx
.add
("<h4>Direct Subclasses Only</h4>\n<ul>\n")
1383 for lc
in cshe
.direct_smallers
do
1384 if not lc
.require_doc
(dctx
) then continue
1385 dctx
.add
("<li>{lc.html_link(dctx)}</li>\n")
1389 dctx
.add
("<h4>Too much Subclasses to list</h4>\n")
1391 dctx
.add
("</nav>\n")
1393 dctx
.add
("</div>\n")
1396 dctx
.add
("<div class=\"content\
">\n")
1397 dctx
.add
("<h1>{name}</h1>\n")
1398 dctx
.add
("<div class='subtitle'>")
1399 if global
.visibility_level
== 2 then
1401 else if global
.visibility_level
== 3 then
1402 dctx
.add
("private ")
1403 else if self.global
.intro
.mmmodule
.toplevel_owner
.visibility_for
(self.global
.intro
.mmmodule
) <= 1 then
1404 dctx
.add
("(unexported) ")
1406 dctx
.add
("{kind} {global.intro.mmmodule.toplevel_owner.html_link(dctx)}::{name}</div>")
1408 dctx
.add
("<section class=\"description\
">\n")
1411 dctx
.add
("<pre>{doc.to_html}</pre>\n")
1414 var cla
= new HashSet[MMLocalClass]
1415 var sm
= new HashSet[MMLocalClass]
1416 var sm2
= new HashSet[MMLocalClass]
1418 while cla
.length
+ sm
.length
< 10 and sm
.length
> 0 do
1422 sm2
.add_all
(x
.cshe
.direct_smallers
)
1428 cla
.add_all
(cshe
.greaters_and_self
)
1431 var name
= "class_{name}"
1432 op
.append
("digraph {name} \{ rankdir=BT; node[shape=none,margin=0,width=0,height=0,fontsize=10]; edge[dir=none,color=gray]; ranksep=0.2; nodesep=0.1;\n")
1435 op
.append
("\"{c.name}\
"[shape=box,margin=0.03];\n")
1437 op
.append
("\"{c.name}\
"[URL=\"{c.html_name}.html\
"];\n")
1439 for c2
in c
.cshe
.direct_greaters
do
1440 if not cla
.has
(c2
) then continue
1441 op
.append
("\"{c.name}\
"->\"{c2.name}\
";\n")
1443 if not c
.cshe
.direct_smallers
.is_empty
then
1445 for c2
in c
.cshe
.direct_smallers
do
1446 if cla
.has
(c2
) then others
= false
1449 op
.append
("\"{c.name}...\
"[label=\"\
"];\n")
1450 op
.append
("\"{c.name}...\
"->\"{c.name}\
"[style=dotted];\n")
1455 dctx
.gen_dot
(op
.to_s
, name
.to_s
, "Inheritance graph for class {name}")
1456 dctx
.add
("</section>\n")
1460 dctx
.stage
("<section class=\"concerns\
">\n")
1461 dctx
.stage
("<h2 class=\"section-header\
">Concerns</h2>\n")
1463 var mods
= new Array[MMModule]
1464 mods
.add
(global
.intro
.mmmodule
.toplevel_owner
)
1465 for lc
in crhe
.greaters
do
1466 if not lc
isa MMSrcLocalClass then continue
1467 var m
= lc
.mmmodule
.toplevel_owner
1468 if not mods
.has
(m
) then mods
.add
(m
)
1471 var intro
= global
.intro
.mmmodule
1476 if m
.short_doc
!= " " then short_doc
= ": {m.short_doc}"
1477 dctx
.add
("<li>{m.html_link_to_anchor}{short_doc}")
1479 for lc
in crhe
.linear_extension
.reversed
do
1480 if lc
.mmmodule
.toplevel_owner
!= m
then continue
1481 if lc
.mmmodule
== m
then continue
1483 if lc
.mmmodule
.short_doc
!= " " then short_doc
= ": {lc.mmmodule.short_doc}"
1484 dctx
.add
("<li>{lc.mmmodule.html_link_to_anchor}{short_doc}</li>")
1490 dctx
.stage
("</section>\n")
1494 dctx
.stage
("<section class=\"types\
">\n")
1495 dctx
.stage
("<h2>Formal and Virtual Types</h2>\n")
1496 for i
in [0..arity
[ do
1497 var f
= get_formal
(i
)
1498 f
.full_documentation
(dctx
, self)
1501 if not p
isa MMTypeProperty then continue
1502 p
.full_documentation
(dctx
, self)
1504 dctx
.stage
("</section>\n")
1508 dctx
.stage
("<section class=\"constructors\
">\n")
1509 dctx
.stage
("<h2 class=\"section-header\
">Constructors</h2>\n")
1511 if not p
.global
.is_init_for
(self) then continue
1512 p
.full_documentation
(dctx
, self)
1514 dctx
.stage
("</section>\n")
1518 dctx
.stage
("<section class=\"methods\
">\n")
1519 dctx
.stage
("<h2 class=\"section-header\
">Methods</h2>\n")
1520 var redefs
= new HashMap[MMModule, HashMap[MMModule, Array[MMMethod]]]
1522 if p
.global
.is_init
then continue
1523 if p
.local_class
.global
!= self.global
then continue
1524 if not p
isa MMMethod then continue
1526 var toplevel_module
= p
.mmmodule
.toplevel_owner
1527 if not redefs
.has_key
(toplevel_module
) then
1528 redefs
[toplevel_module
] = new HashMap[MMModule, Array[MMMethod]]
1531 var nested_module
= p
.mmmodule
1532 if not redefs
[toplevel_module
].has_key
(nested_module
) then
1533 redefs
[toplevel_module
][nested_module
] = new Array[MMMethod]
1536 redefs
[toplevel_module
][nested_module
].add
(p
)
1539 if p
.mmmodule
.toplevel_owner
!= p
.intro_module
then
1540 toplevel_module
= p
.intro_module
1541 nested_module
= p
.global
.intro
.mmmodule
1543 if not redefs
.has_key
(toplevel_module
) then
1544 redefs
[toplevel_module
] = new HashMap[MMModule, Array[MMMethod]]
1546 if not redefs
[toplevel_module
].has_key
(nested_module
) then
1547 redefs
[toplevel_module
][nested_module
] = new Array[MMMethod]
1550 redefs
[toplevel_module
][nested_module
].add
(p
.global
.intro
.as(MMMethod))
1554 # Display toplevel blocks
1556 if not redefs
.has_key
(m
) then continue
1557 dctx
.add
(m
.html_anchor
)
1558 if m
!= global
.intro
.mmmodule
.toplevel_owner
then
1559 dctx
.add
("<h3 class=\"concern-toplevel\
">Methods refined in {m.html_link(dctx)}</h3>")
1562 # Display nested module blocks
1563 for lc
in crhe
.linear_extension
.reversed
do
1564 if lc
.mmmodule
.toplevel_owner
!= m
then continue
1565 var nm
= lc
.mmmodule
1566 if not redefs
[m
].has_key
(nm
) then continue
1567 dctx
.add
(nm
.html_anchor
)
1568 if nm
!= global
.intro
.mmmodule
then
1570 if nm
.short_doc
!= " " then short_doc
= ": {nm.short_doc}"
1571 dctx
.add
("<p class=\"concern-doc\
">{nm.html_name}{short_doc}</p>\n")
1574 var pps
= redefs
[m
][nm
]
1577 p
.full_documentation
(dctx
, self)
1582 if not inhs
.is_empty
then
1584 dctx
.stage
("<h3>Inherited Methods</h3>\n")
1587 dctx
.stage
("<p>Defined in {lc.html_link(dctx)}:")
1589 var ims
= new Array[MMMethod]
1591 if p
.global
.is_init
then continue
1592 if not p
isa MMMethod then continue
1598 dctx
.add
(" {p.html_link(dctx)}")
1599 if i
< ims
.length
- 1 then dctx
.add
(",")
1608 dctx
.add
("</section>\n")
1610 dctx
.add
("</div> <!-- end class {name} -->\n")
1614 redef class MMSrcLocalClass
1620 else if global
.intro
== self then
1623 var bc
= global
.intro
1631 if not n
isa AStdClassdef then
1638 if d
.n_comment
.is_empty
then
1646 redef class MMSignature
1647 # Htlm transcription of the signature (with nested links)
1648 fun to_html
(dctx
: DocContext, with_closure
: Bool): String
1650 var res
= new Buffer
1653 for i
in [0..arity
[ do
1654 if i
> 0 then res
.append
(", ")
1655 res
.append
(self.params
[i
].name
.to_s
)
1657 res
.append
(self[i
].html_link
(dctx
))
1658 if self.vararg_rank
== i
then
1664 if return_type
!= null then
1666 res
.append
(return_type
.html_link
(dctx
))
1668 if with_closure
then
1669 for c
in closures
do
1671 if c
.is_optional
then res
.append
("[")
1672 if c
.is_break
then res
.append
("break ")
1673 res
.append
("!{c.name}")
1674 res
.append
(c
.signature
.to_html
(dctx
, false))
1675 if c
.is_optional
then res
.append
("]")
1683 # Htlm transcription of the type (with nested links)
1684 fun html_link
(dctx
: DocContext): String do return to_s
1687 redef class MMTypeSimpleClass
1688 redef fun html_link
(dctx
) do return local_class
.html_link
(dctx
)
1691 redef class MMTypeGeneric
1692 redef fun html_link
(dctx
)
1694 var res
= new Buffer
1695 res
.append
(local_class
.html_link
(dctx
))
1697 res
.append
(params
[0].html_link
(dctx
))
1698 for i
in [1..params
.length
[ do
1700 res
.append
(params
[i
].html_link
(dctx
))
1707 redef class MMTypeFormalParameter
1708 fun html_anchor
: String
1710 return "FT_{local_class}_{cmangle(name)}"
1712 redef fun html_link
(dctx
)
1714 return "<a href=\"#{html_anchor}\">{name}</a>"
1716 fun full_documentation
(dctx
: DocContext, lc
: MMLocalClass)
1718 dctx
.add
("<article id=\"{html_anchor}\
">\n")
1719 dctx
.add
("<h3 class=\"signature\
">{name}: {bound.html_link(dctx)}</h3>\n")
1720 dctx
.add
("<div class=\"info\
">")
1721 dctx
.add
("formal generic type")
1723 dctx
.add
("</article>")
1727 redef class MMNullableType
1728 redef fun html_link
(dctx
) do return "nullable " + as_notnull
.html_link
(dctx
)
1731 redef class MMVirtualType
1732 redef fun html_link
(dctx
) do return property
.html_link
(dctx
)
1735 var c
= new DocContext