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 id=\"listBranches\
"><label id=\"lbBranches\
">Branch </label><select id=\"dropBranches\
" name=\"dropBranches\
" tabindex=\"1\
" class=\"dropdown\
"></select></div></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><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"
188 add
("<!DOCTYPE html>")
189 add
("<html><head>{head}<title>Overview | {custom_title}</title></head><body>\n")
191 add
("<div class=\"page\
">")
192 add
("<div class=\"content fullpage\
">")
193 add
("<h1>{custom_title}</h1>\n<article class='overview'>{overview_text}</article><article class='overview'><h2>Modules</h2><ul>")
194 var modss
= mainmod
.mhe
.greaters_and_self
.to_a
197 if not mod
.is_toplevel
then continue
198 if not mod
.require_doc
(self) then continue
199 assert mod
isa MMSrcModule
200 add
("<li>{mod.html_link(self)} {mod.short_doc}</li>")
206 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")
208 if not mod
.is_toplevel
then continue
209 if not mod
.require_doc
(self) then continue
210 op
.append
("\"{mod.name}\
"[URL=\"{mod.html_name}.html\
"];\n")
211 for mod2
in mod
.tmhe
.direct_greaters
do
212 if not modss
.has
(mod2
) then continue
213 op
.append
("\"{mod.name}\
"->\"{mod2.name}\
";\n")
217 self.gen_dot
(op
.to_s
, "dep", "Modules hierarchy")
218 add
("</article></div>")
220 add
("<footer>{footer_text}</footer>")
221 add
("</body></html>\n")
222 write_to
("{dir}/index.html")
224 # Generate page for modules
225 for mod
in modules
do
226 if mod
== mainmod
then continue
227 assert mod
isa MMSrcModule
228 if not mod
.require_doc
(self) then continue
229 self.filename
= mod
.html_name
230 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 id=\"listBranches\
"><label id=\"lbBranches\
">Branch </label><select id=\"dropBranches\
" name=\"dropBranches\
" tabindex=\"1\
" class=\"dropdown\
"></select></div>/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"
234 add
("<!DOCTYPE html>")
235 add
("<html><head>{head}<title>{mod.name} module | {custom_title}</title></head><body>\n")
237 add
("<div class=\"page\
">")
238 mod
.file_page_doc
(self)
240 add
("<footer>{footer_text}</footer>")
241 add
("</body></html>\n")
242 write_to
("{dir}/{mod.html_name}.html")
245 # Generate pages for global classes
246 for c
in mainmod
.local_classes
do
247 if not c
.require_doc
(self) then continue
248 self.filename
= c
.html_name
249 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 id=\"listBranches\
"><label id=\"lbBranches\
">Branch </label><select id=\"dropBranches\
" name=\"dropBranches\
" tabindex=\"1\
" class=\"dropdown\
"></select></div></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"
253 add
("<!DOCTYPE html>")
254 add
("<html><head>{head}<title>{c.name} class | {custom_title}</title></head><body>\n")
256 add
("<div class=\"page\
">")
257 c
.file_page_doc
(self)
259 add
("<footer>{footer_text}</footer>")
260 add
("</body></html>\n")
261 write_to
("{dir}/{c.html_name}.html")
264 self.filename
= "fullindex"
265 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 id=\"listBranches\
"><label id=\"lbBranches\
">Branch </label><select id=\"dropBranches\
" name=\"dropBranches\
" tabindex=\"1\
" class=\"dropdown\
"></select></div></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"
269 add
("<!DOCTYPE html>")
270 add
("<html><head>{head}<title>Full Index | {custom_title}</title></head><body>\n")
272 add
("<div class=\"page\
">")
273 add
("<div class=\"content fullpage\
">")
274 mainmod
.file_index_page_doc
(self)
277 add
("<footer>{footer_text}</footer>")
278 add
("</body></html>\n")
279 write_to
("{dir}/full-index.html")
281 self.filename
= "quicksearch-list"
283 mainmod
.file_quicksearch_list_doc
(self)
284 write_to
("{dir}/quicksearch-list.js")
287 # Add or not a tag for the github repository
288 fun addGithubInformation
do
289 if not github_repo
== null then add
("<div id=\"repoName\
" name=\"{github_repo.to_s}\
"></div>")
292 # Add all tags for the commit form
294 add
("<div id=\"modal\
"><form class=\"clearfix\
"><div><label for=\"commitMessage\
">Commit message</label><input id=\"commitMessage\
" type=\"text\
" name=\"commitMessage\
"></div><div class=\"social-signup login\
"><form ></form></div><form id=\"github-connect-form\
" class=\"connect-button\
" name=\"login\
"><a id=\"loginAction\
" title=\"Commit on
GitHub\
"><img src=\"resources
/icons
/github-icon
.png\
"><span id=\"btnGitHub\
"><strong>Commit</strong></span></a></form></form></div><div id=\"modalQuestion\
"><label id=\"txtQuestion\
"></label><br><a id=\"btnCreateBranch\
">Yes</a><a id=\"btnCancelBranch\
">No</a></div><div id=\"waitCommit\
"></div>\n\n")
297 # Add a (source) link fo a given location
298 fun show_source
(l
: Location)
300 var s
= opt_source
.value
302 add
("({l.file.filename.simplify_path})")
304 # THIS IS JUST UGLY ! (but there is no replace yet)
305 var x
= s
.split_with
("%f")
306 s
= x
.join
(l
.file
.filename
.simplify_path
)
307 x
= s
.split_with
("%l")
308 s
= x
.join
(l
.line_start
.to_s
)
309 x
= s
.split_with
("%L")
310 s
= x
.join
(l
.line_end
.to_s
)
311 add
(" (<a href=\"{s}\
">show code</a>)")
315 # Return source link for a given location
316 fun get_source
(l
: Location): String
318 var s
= opt_source
.value
320 return l
.file
.filename
.simplify_path
322 # THIS IS JUST UGLY ! (but there is no replace yet)
323 var x
= s
.split_with
("%f")
324 s
= x
.join
(l
.file
.filename
.simplify_path
)
325 x
= s
.split_with
("%l")
326 s
= x
.join
(l
.line_start
.to_s
)
327 x
= s
.split_with
("%L")
328 s
= x
.join
(l
.line_end
.to_s
)
333 # Generate a clicable graphiz image using a dot content.
334 # `name' refer to the filename (without extension) and the id name of the map.
335 # `name' must also match the name of the graph in the dot content (eg. digraph NAME {...)
336 fun gen_dot
(dot
: String, name
: String, alt
: String)
338 if opt_nodot
.value
then return
339 var f
= new OFStream.open
("{self.dir}/{name}.dot")
342 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 ; \}")
343 self.add
("<article class=\"graph\
"><img src=\"{name}.png\
" usemap=\"#{name}\" style=\"margin:auto\" alt=\"{alt}\"/></article>")
344 var fmap
= new IFStream.open
("{self.dir}/{name}.map")
345 self.add
(fmap
.read_all
)
354 option_context
.add_option
(opt_public
)
355 option_context
.add_option
(opt_private
)
356 option_context
.add_option
(opt_dir
)
357 option_context
.add_option
(opt_source
)
358 option_context
.add_option
(opt_nodot
)
359 option_context
.add_option
(opt_sharedir
)
360 option_context
.add_option
(opt_custom_title
)
361 option_context
.add_option
(opt_custom_menu_items
)
362 option_context
.add_option
(opt_custom_overview_text
)
363 option_context
.add_option
(opt_custom_footer_text
)
364 option_context
.add_option
(opt_github_repo_name
)
367 redef fun process_options
370 var d
= opt_dir
.value
371 if d
!= null then dir
= d
373 if not opt_nodot
.value
then
374 # Test if dot is runable
375 var res
= sys
.system
("sh -c dot </dev/null >/dev/null 2>&1")
377 stderr
.write
"--no-dot implied since `dot' is not available. Try to install graphviz.\n"
378 opt_nodot
.value
= true
382 sharedir
= opt_sharedir
.value
383 if sharedir
== null then
384 var dir
= "NIT_DIR".environ
386 dir
= "{sys.program_name.dirname}/../share/nitdoc"
387 if dir
.file_exists
then sharedir
= dir
389 dir
= "{dir}/share/nitdoc"
390 if dir
.file_exists
then sharedir
= dir
392 if sharedir
== null then
393 fatal_error
(null, "Error: Cannot locate nitdoc shared files. Uses --sharedir or envvar NIT_DIR.")
395 dir
= "{sharedir.to_s}/scripts/js-facilities.js"
396 if sharedir
== null then
397 fatal_error
(null, "Error: Invalid nitdoc shared files. Check --sharedir or envvar NIT_DIR.")
401 var git
= opt_github_repo_name
.value
402 if not git
== null then github_repo
= git
405 redef fun handle_property_conflict
(lc
, impls
)
407 # THIS IS SO UGLY! See MMVirtualModule
408 if lc
.mmmodule
== self.mainmod
then
409 return # We just accept, so one in impls is arbitrary inherited
415 # A virtual module is used to work as an implicit main module that combine unrelated modules
416 # Since conflict may arrise in a virtual module (the main method for instance) conflicts are disabled
417 class MMVirtualModule
419 init(ctx
: MMContext, mods
: Array[MMModule])
421 # We need to compute the whole metamodel since there is no mmbuilder to do it
422 super(" main".to_symbol
, mods
.first
.directory
, ctx
, new Location(null,0,0,0,0))
423 ctx
.add_module
(self, mods
)
425 self.add_super_module
(m
, 1)
427 self.import_global_classes
428 self.import_local_classes
429 for c
in self.local_classes
do
430 c
.compute_super_classes
432 for c
in self.local_classes
do
437 redef fun require_doc
(dctx
) do return false
440 # Conditionnal part of the text content of a DocContext
442 # Content of the current stage
443 readable var _content
: Array[String] = new Array[String]
445 # Is a normal string already added?
446 readable writable var _validate
: Bool = false
448 # Parent stage is any
449 readable var _parent
: nullable StageContext = null
451 init(parent
: nullable StageContext) do _parent
= parent
455 # Efficiently sort object with their to_s method
456 class AlphaSorter[E
: Object]
457 super AbstractSorter[E
]
458 redef fun compare
(a
, b
)
478 # Keep track of to_s values
479 var _dico
: HashMap[Object, String] = new HashMap[Object, String]
484 # Generalization of metamodel entities
487 fun html_link
(dctx
: DocContext): String is abstract
489 # Return a one liner description
490 fun short_doc
: String do return " "
492 # The doc node from the AST
493 # Return null is none
494 fun doc
: nullable ADoc do return null
496 # Return a JSON entry for quicksearch list
497 fun json_entry
(dctx
: DocContext): String is abstract
499 # Return the qualified name as string
500 fun qualified_name
: String is abstract
506 redef fun html_link
(dctx
) do
507 if short_doc
== " " then
508 return "<a href=\"{html_name}.html\
"\">{self}</a
>"
510 return "<a href
=\
"{html_name}.html\" title
=\
"{short_doc}\">{self}</a
>"
514 fun html_anchor: String do
515 return "<a id
=\
"MOD_{html_name}\"></a
>"
518 fun html_link_to_anchor: String do
519 return "<a href
=\
"#MOD_{html_name}\" title
=\
"Jump to definitions from module {html_name}\">{self}</a
>"
522 redef fun json_entry(dctx) do
523 return "\
{txt:\"{self.qualified_name}\
",url:\"{html_name}.html\
"\},"
526 redef fun qualified_name
do
527 var buffer
= new Buffer
528 for m
in mnhe
.smallers
do
529 buffer
.append
("{m.html_name}::")
531 buffer
.append
("{self.name}")
535 fun require_doc
(dctx
: DocContext): Bool
537 if dctx
.public_only
and not is_toplevel
then return false
541 # Return true if the module is a top-level owner or a top-level module
542 fun is_toplevel
: Bool
544 var pd
= directory
.parent
545 return pd
== null or (pd
.owner
== null and directory
.owner
== self)
548 # Element in the module nesting tree
549 fun mnhe
: PartialOrderElement[MMModule] do return mnhe_
.as(not null)
550 var mnhe_
: nullable PartialOrderElement[MMModule] = null
552 # Element in the top level module importation hierarchy
553 fun tmhe
: PartialOrderElement[MMModule] do return tmhe_
.as(not null)
554 var tmhe_
: nullable PartialOrderElement[MMModule] = null
556 fun toplevel_owner
: MMModule
560 var ds
= m
.mnhe
.direct_smallers
561 if ds
.length
== 0 then return m
562 if ds
.length
== 1 then m
= ds
.first
else abort
566 fun html_name
: String
571 fun direct_owner
: nullable MMModule
574 while d
.owner
== self do d
= d
.parent
.as(not null)
578 # Fill the body for the page associated to the module
579 fun file_page_doc
(dctx
: DocContext)
581 dctx
.add
("<div class=\"menu\
">\n")
583 var mods
= new Array[MMModule]
584 mods
= self.mhe
.greaters
.to_a
588 dctx
.stage
("<nav>\n")
589 dctx
.stage
("<h3>Module Hierarchy</h3>\n")
590 dctx
.stage
("<h4>All dependencies</h4>\n")
593 if not mod
.require_doc
(dctx
) then continue
594 if self.mnhe
<= mod
then continue # do not want nested stuff
595 if mod
.direct_owner
!= null and not mod
.direct_owner
.mnhe
<= self then continue # not in the right nesting
596 dctx
.add
("<li>{mod.html_link(dctx)}</li>")
598 dctx
.stage
("</ul>\n")
600 mods
= self.mhe
.smallers
.to_a
602 dctx
.stage
("<h4>All clients</h4>\n")
605 if not mod
.require_doc
(dctx
) then continue
606 if self.mnhe
<= mod
then continue # do not want nested stuff
607 if mod
.direct_owner
!= null and not mod
.direct_owner
.mnhe
<= self then continue # not in the right nesting
608 dctx
.add
("<li>{mod.html_link(dctx)}</li>")
610 dctx
.stage
("</ul>\n")
611 dctx
.stage
("</nav>\n")
614 if not dctx
.public_only
then
615 mods
= self.mnhe
.direct_greaters
.to_a
618 dctx
.stage
("<nav>\n")
619 dctx
.stage
("<h3>Nested Modules</h3><ul>\n")
621 if not mod
.require_doc
(dctx
) then continue
622 dctx
.add
("<li>{mod.html_link(dctx)}</li>")
624 dctx
.stage
("</ul></nav>\n")
628 dctx
.add
("</div>") # metadata
630 dctx
.add
("<div class=\"content\
">\n")
631 dctx
.add
("<h1>{name}</h1>\n")
632 dctx
.add
("<div class='subtitle'>module ")
633 for m
in mnhe
.smallers
do
634 dctx
.add
("{m.html_link(dctx)}::")
636 dctx
.add
("{self.name}</div>\n")
638 dctx
.add
("<section class='description'>\n")
642 dctx
.add
("<div id=\"description\
">\n")
643 dctx
.add
("<pre class=\"text_label\
">{doc.to_html}</pre>\n")
644 dctx
.add
("<textarea rows=\"1\
" cols=\"76\
" id=\"fileContent\
" class=\"edit\
"></textarea>\n")
645 dctx
.add
("<a id=\"cancelBtn\
">Cancel</a><a id=\"commitBtn\
">Commit</a>")
650 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")
651 var ms
= new Array[nullable MMModule]
653 var m0
: nullable MMModule = self
659 var cla
= new HashSet[MMModule]
661 for m0
in self.mhe
.greaters
do
662 if not m0
.require_doc
(dctx
) then continue
663 if self.visibility_for
(m0
) <= 1 then continue # private or hidden
664 if self.mnhe
<= m0
then continue # do not want nested stuff
665 if m0
.direct_owner
!= null and not m0
.direct_owner
.mnhe
<= self then continue # not in the right nesting
668 for m0
in self.mhe
.smallers
do
669 if not m0
.require_doc
(dctx
) then continue
670 if m0
.visibility_for
(self) <= 1 then continue # private or hidden
671 if m0
.direct_owner
!= null and not m0
.direct_owner
.mnhe
<= self then continue # not in the right nesting
674 for m0
in self.mnhe
.smallers
do
680 op
.append
("subgraph \"cluster_
{m0.name}\
"\{\n")
683 if c
.direct_owner
!= m0
then continue
685 op
.append
("\"{c.name}\
"[shape=box,margin=0.03];\n")
687 op
.append
("\"{c.name}\
"[URL=\"{c.html_name}.html\
"];\n")
691 op
.append
("\"{m0.name}\
"[URL=\"{m0.html_name}.html\
"];\n")
692 for c
in m0
.mhe
.direct_greaters
do
693 if not cla
.has
(c
) then continue
694 op
.append
("\"{m0.name}\
"->\"{c.name}\
";\n")
699 # Close the nesting subgraph
705 for c2
in c
.tmhe
.direct_greaters
do
706 if not cla
.has
(c2
) then continue
707 op
.append
("\"{c.name}\
"->\"{c2.name}\
";\n")
711 dctx
.gen_dot
(op
.to_s
, name
.to_s
, "Dependency graph for module {name}")
712 dctx
.add
("</section>")
714 var clas
= new Array[MMLocalClass]
715 var props
= new HashMap[MMGlobalProperty, Array[MMLocalProperty]]
716 var gprops
= new Array[MMLocalProperty]
719 for g
in m
.global_classes
do
721 if not lc
.require_doc
(dctx
) then continue
722 var im
= g
.intro
.mmmodule
723 if self.visibility_for
(im
) <= 1 then continue # private import or invisible import
725 for lc2
in lc
.crhe
.greaters_and_self
do
726 if not lc2
isa MMSrcLocalClass then continue
727 if not self.mnhe
<= lc2
.mmmodule
then continue # not introduced/redefined here/stolen
730 if not keep
then continue
732 lc
.compute_super_classes
733 for gp
in lc
.global_properties
do
734 if self.visibility_for
(gp
.intro
.local_class
.mmmodule
) <= 1 then continue # private import or invisible import
736 var mp
= lp
.local_class
.mmmodule
737 if not self.mnhe
<= mp
then continue # not introduced/redefined here/stolen
739 if not lp
.require_doc
(dctx
) then continue
740 if props
.has_key
(lp
.global
) then
741 if not props
[lp
.global
].has
(lp
) then
742 props
[lp
.global
].add
(lp
)
745 props
[lp
.global
] = [lp
]
746 gprops
.add
(lp
.global
.intro
)
751 dctx
.add
("<section class=\"module\
">\n")
753 dctx
.stage
("<article class=\"classes filterable\
">\n")
754 dctx
.stage
("<h2>Classes</h2>\n")
758 if self.mnhe
<= lc
.global
.intro
.mmmodule
then
759 dctx
.add
("<li class='intro'><span title='introduced in this module'>I</span> ")
761 dctx
.add
("<li class='redef'><span title='refined in this module'>R</span> ")
763 dctx
.add
("{lc.html_link(dctx)}</li>\n")
765 dctx
.stage
("</ul></article>\n")
769 dctx
.stage
("<article class=\"properties filterable\
">\n")
770 dctx
.stage
("<h2>Properties</h2>\n")
777 if gp
.intro
isa MMAttribute then continue
779 var lpi
= self[gp
.intro
.local_class
.global
][gp
]
782 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")
785 dctx
.add
("<li class='intro'><span title='introduction in this module'>I</span> {lpi.html_name}")
786 dctx
.add
(" ({lpi.local_class})</li>\n")
788 if lps
.length
>= 1 then
791 dctx
.add
("<li class='redef'><span title='redefinition'>R</span> {lp.html_open_link(dctx)}{lp.html_name} ({lp.local_class})</a></li>")
795 dctx
.stage
("</ul></article>\n")
797 dctx
.add
("</section>\n")
801 # Fill the body for the page associated to the full index
802 fun file_index_page_doc
(dctx
: DocContext)
805 dctx
.add
("<h1>Full Index</h1>\n")
807 var clas
= new Array[MMLocalClass]
808 var props
= new HashMap[MMGlobalProperty, Array[MMLocalProperty]]
809 var gprops
= new Array[MMLocalProperty]
810 var mods
= new Array[MMModule]
811 for m
in mhe
.greaters_and_self
do
812 if not m
.require_doc
(dctx
) then continue
815 for g
in global_classes
do
817 if not lc
.require_doc
(dctx
) then continue
819 for gp
in lc
.global_properties
do
821 if not lp
.require_doc
(dctx
) then continue
822 if props
.has_key
(lp
.global
) then
823 if not props
[lp
.global
].has
(lp
) then
824 props
[lp
.global
].add
(lp
)
827 props
[lp
.global
] = [lp
]
828 gprops
.add
(lp
.global
.intro
)
833 dctx
.stage
("<article class=\"modules filterable\
">\n")
834 dctx
.stage
("<h2>Modules</h2>\n")
838 dctx
.add
("<li>{m.html_link(dctx)}</li>")
840 dctx
.stage
("</ul></article>\n")
844 dctx
.stage
("<article class=\"classes filterable\
">\n")
845 dctx
.stage
("<h2>Classes</h2>\n")
849 dctx
.add
("<li>{lc.html_link(dctx)}</li>")
851 dctx
.stage
("</ul></article>\n")
855 dctx
.stage
("<article class=\"properties filterable\
">\n")
856 dctx
.stage
("<h2>Properties</h2>\n")
863 if gp
.intro
isa MMAttribute then continue
865 var lpi
= self[gp
.intro
.local_class
.global
][gp
]
868 dctx
.add
("<li class='intro'><span title='introduction'>I</span> {lpi.html_open_link(dctx)}{lpi.html_name} ({lpi.local_class})</a></li>\n")
869 if lps
.length
>= 1 then
872 dctx
.add
("<li class='redef'><span title='redefinition'>R</span> {lp.html_open_link(dctx)}{lp.html_name} ({lp.local_class})</a></li>\n")
876 dctx
.stage
("</ul></article>\n")
880 # Fill the quicksearch list JSON object
881 fun file_quicksearch_list_doc
(dctx
: DocContext)
883 var entities
= new HashMap[String, Array[MMEntity]]
884 var props
= new HashMap[MMGlobalProperty, Array[MMLocalProperty]]
885 for m
in mhe
.greaters_and_self
do
886 if not m
.require_doc
(dctx
) then continue
887 var a
= new Array[MMEntity]
889 entities
[m
.html_name
] = a
891 for g
in global_classes
do
893 if not lc
.require_doc
(dctx
) then continue
894 var a
= new Array[MMEntity]
896 entities
[lc
.html_name
] = a
897 for gp
in lc
.global_properties
do
899 if not lp
.require_doc
(dctx
) then continue
900 if lp
.kind
== "var" then continue
901 if props
.has_key
(lp
.global
) then
902 if not props
[lp
.global
].has
(lp
) then
903 props
[lp
.global
].add
(lp
)
906 props
[lp
.global
] = [lp
]
912 entities
[k
.short_name
] = v
915 var keys
= entities
.keys
.to_a
916 var sorter
= new AlphaSorter[String]
920 dctx
.stage
("var entries = \{")
922 dctx
.add
("\"{key}\
": [")
923 for entity
in entities
[key
] do
924 dctx
.add
(entity
.json_entry
(dctx
))
933 redef class MMGlobalProperty
934 # Return the short name of the property
935 fun short_name
: String do
936 return self.intro
.html_name
940 redef class MMLocalProperty
942 # Anchor of the property description in the module html file
943 fun html_anchor
: String
945 return "PROP_{self.mmmodule.toplevel_owner}_{local_class}_{cmangle(name)}"
948 redef fun json_entry
(dctx
) do
949 return "\{txt:\"{qualified_name}\",url
:\
"{local_class.html_name}.html#{html_anchor}\"\
},"
952 redef fun qualified_name do
953 return "{intro_module.qualified_name}::{local_class.html_name}::{html_name}"
956 fun html_open_link(dctx: DocContext): String
958 if not require_doc(dctx) then print "not required
{self}"
959 var title = "{html_name}{signature.to_s}"
960 if short_doc != " 
;" then
961 title += " #{short_doc}"
963 return "<a href=\"{local_class.html_name}.html
#{html_anchor}\" title=\"{title}\">"
966 fun html_name
: String
968 return self.name
.to_s
.html_escape
971 redef fun html_link
(dctx
)
973 if not require_doc
(dctx
) then print
"not required {self}"
974 var title
= "{html_name}{signature.to_s}"
975 if short_doc
!= " " then
976 title
+= " #{short_doc}"
978 return "<a href=\"{local_class.html_name}.html
#{html_anchor}\" title=\"{title}\">{html_name}</a>"
981 fun html_link_special
(dctx
: DocContext, lc
: MMLocalClass): String
983 if not require_doc
(dctx
) then print
"not required {self}"
984 var title
= "{html_name}{signature_for(lc.get_type)}"
985 if short_doc
!= " " then
986 title
+= " #{short_doc}"
988 return "<a href=\"{lc.html_name}.html
#{html_anchor}\" title=\"{title}\">{html_name}</a>"
991 # Kind of property (fun, attr, etc.)
992 fun kind
: String is abstract
999 else if global
.intro
== self then
1002 return global
.intro
.short_doc
1009 if n
== null or not n
isa APropdef then
1016 if d
.n_comment
.is_empty
then
1023 # The most specific module in the nesting hierarchy that exports the intro of self
1024 fun intro_module
: MMModule
1026 var m
= global
.intro
.mmmodule
1027 var mo
= m
.direct_owner
1028 while mo
!= null and mo
.visibility_for
(m
) >= 2 do
1035 # Is the intro of self exported by the top-level module ?
1036 fun is_toplevel
: Bool
1038 var m
= intro_module
1039 return m
== m
.toplevel_owner
1042 # Return true if the global property must be documented according to the visibility configured
1043 fun require_doc
(dctx
: DocContext): Bool
1045 if global
.visibility_level
== 3 and not dctx
.with_private
then return false # Private
1046 if dctx
.public_only
then
1047 var m
= intro_module
1048 if m
!= m
.toplevel_owner
then return false # Unexported
1053 # Document the global property in the global class lc
1054 fun full_documentation
(dctx
: DocContext, lc
: MMLocalClass)
1056 var visibility
: String
1057 if global
.visibility_level
== 1 then
1058 visibility
= "public"
1059 else if global
.visibility_level
== 2 then
1060 visibility
= "protected"
1061 else if global
.visibility_level
== 3 then
1062 visibility
= "private"
1067 var intro_class
= global
.intro
.local_class
1068 var is_redef
= local_class
.global
!= intro_class
.global
or local_class
.mmmodule
.toplevel_owner
!= intro_class
.mmmodule
.toplevel_owner
1070 dctx
.add
("<article id=\"{html_anchor}\
" class=\"{kind} {visibility} {if is_redef then "redef" else ""}\
">\n")
1071 dctx
.add
("<h3 class=\"signature\
">{html_name}{signature.to_html(dctx, true)}</h3>\n")
1072 dctx
.add
("<div class=\"info\
">\n")
1077 if not is_toplevel
then
1078 dctx
.add
("(unexported) ")
1080 if global
.visibility_level
== 2 then
1081 dctx
.add
("protected ")
1082 else if global
.visibility_level
== 3 then
1083 dctx
.add
("private ")
1086 dctx
.add
(" {intro_class.mmmodule.toplevel_owner.name}")
1087 if intro_class
.global
== lc
.global
then
1088 dctx
.add
("::{lc.name}")
1090 dctx
.add
("::{mmmodule[intro_class.global].html_link(dctx)}")
1093 dctx
.add
("::{mmmodule[intro_class.global][global].global.intro.html_link(dctx)}")
1095 dctx
.add
("::{html_name}")
1099 dctx
.add
("<div class=\"description\
">")
1101 # Collect all refinement of the global property in the same global property
1102 var lps
= new Array[MMLocalProperty]
1103 for l
in prhe
.greaters_and_self
do
1107 var introdoc
= false
1108 if global
.intro
.doc
!= null then
1110 if lp
.doc
== null then introdoc
= true
1114 dctx
.add
("<pre class=\"text_label\
" name=\"{html_name}\
" >{global.intro.doc.to_html}</pre>")
1115 dctx
.add
("<textarea rows=\"1\
" cols=\"76\
" id=\"fileContent\
" class=\"edit\
"></textarea>")
1116 dctx
.add
("<a id=\"cancelBtn\
">Cancel</a><a id=\"commitBtn\
">Commit</a>")
1119 var tlmods
= new Array[MMModule]
1121 var bm
= lp
.mmmodule
.toplevel_owner
1122 var lcm
= lc
.global
.intro
.mmmodule
1123 if lcm
.mhe
< lp
.mmmodule
then bm
= lcm
.toplevel_owner
1124 if not tlmods
.has
(bm
) then tlmods
.add
(bm
)
1128 # Document the top level property for the current top level module
1130 if tm
.global_classes
.has
(lc
.global
) then
1131 tlp
= tm
[lc
.global
][self.global
]
1133 else if tm
.global_classes
.has
(self.local_class
.global
) then
1134 # Self is the inherited property. Process it
1135 tlp
= tm
[self.local_class
.global
][self.global
]
1138 # We skip this module since the props defined by the module is
1142 var tlcm
= lc
.global
.intro
.mmmodule
.toplevel_owner
1143 if not tlcm
.mhe
<= tm
then
1144 dctx
.add
("<h4>In module {tm.html_link(dctx)} :</h4>")
1149 if doc
!= null and (not introdoc
or global
.intro
.doc
!= doc
) then
1152 dctx
.add
("<pre type=\"1\
" class=\"text_label\
" tag=\"{l.file.filename}\
" name=\"{dctx.get_source(l)}\
" title=\"{l.line_start.to_s}\
" >{doc.to_html}</pre>")
1154 else if not is_redef
then
1157 dctx
.add
("<a class=\"newComment\
" tag=\"{l.file.filename}\
" title=\"{l.line_start.to_s}\
">New comment</a>\n")
1160 dctx
.add
("<textarea rows=\"1\
" cols=\"76\
" id=\"fileContent\
" class=\"edit\
"></textarea>")
1161 dctx
.add
("<a id=\"cancelBtn\
">Cancel</a><a id=\"commitBtn\
">Commit</a>")
1163 if tlp
.local_class
.global
!= lc
.global
then
1164 dctx
.add
("inherited from {tlp.local_class.html_link(dctx)} ")
1166 if tm
!= tlp
.mmmodule
then
1167 dctx
.add
("defined by the module {tlp.mmmodule.html_link(dctx)} ")
1175 dctx
.stage
(". previously defined by:")
1177 var tl
= lp
.mmmodule
.toplevel_owner
1178 if tl
!= tm
then continue
1179 if lp
== tlp
then continue
1180 dctx
.add
(" {lp.mmmodule.html_link(dctx)}")
1181 if lp
.local_class
.global
!= lc
.global
then
1182 dctx
.add
(" for {lp.local_class.html_link(dctx)} ")
1195 dctx
.add
("</article>")
1198 redef class MMMethod
1199 redef fun kind
do return if global
.is_init
then "init" else "fun"
1201 redef class MMAttribute
1202 redef fun kind
do return "var"
1204 redef class MMTypeProperty
1205 redef fun kind
do return "type"
1208 redef class MMSrcModule
1222 if n
.n_moduledecl
== null then
1225 var np
= n
.n_moduledecl
1230 if d
.n_comment
.is_empty
then
1239 # Html transcription of the doc
1242 var res
= new Buffer
1243 for c
in n_comment
do
1244 res
.append
(c
.text
.substring_from
(1))
1246 return res
.to_s
.html_escape
1249 # Oneliner transcription of the doc
1252 return n_comment
.first
.text
.substring_from
(1).html_escape
1256 redef class MMLocalClass
1259 # Anchor of the class description in the module html file
1260 fun html_anchor
: String do return "CLASS_{self}"
1262 fun html_name
: String do return "{self}"
1264 redef fun html_link
(dctx
)
1266 if not require_doc
(dctx
) then print
"{dctx.filename}: not required {self}"
1267 if short_doc
== " " then
1268 return "<a href=\"{html_name}.html\
"\">{self}</a
>"
1270 return "<a href
=\
"{html_name}.html\" title
=\
"{short_doc}\">{self}</a
>"
1274 redef fun json_entry(dctx) do
1275 return "\
{txt:\"{qualified_name}\
",url:\"{html_name}.html\
"\},"
1278 redef fun qualified_name
do
1279 return "{intro_module.qualified_name}::{html_name}"
1282 redef fun short_doc
do return global
.intro
.short_doc
1284 redef fun doc
do return global
.intro
.doc
1288 if global
.is_interface
then
1290 else if global
.is_abstract
then
1291 return "abstract class"
1292 else if global
.is_enum
then
1299 # The most specific module in the nesting hierarchy that exports the intro of self
1300 fun intro_module
: MMModule
1302 var m
= global
.intro
.mmmodule
1303 var mo
= m
.direct_owner
1304 while mo
!= null and mo
.visibility_for
(m
) >= 2 do
1311 fun menu_link
(dctx
: DocContext, p
: MMLocalProperty)
1313 if p
.local_class
.global
!= self.global
then
1314 if p
.global
.intro
.local_class
.name
== "Object".to_symbol
then return
1315 if p
.global
.is_init
or p
isa MMTypeProperty then
1316 dctx
.add
("<li class='inherit'><span title='Inherited'>H</span> {p.html_link_special(dctx, self)}</li>\n")
1318 dctx
.add
("<li class='inherit'><span title='Inherited'>H</span> {p.html_link(dctx)}</li>\n")
1320 else if p
.global
.intro
.local_class
.global
== self.global
then
1321 dctx
.add
("<li class='intro'><span title='Introduced'>I</span> {p.html_link_special(dctx, self)}</li>\n")
1323 dctx
.add
("<li class='redef'><span title='Redefined'>R</span> {p.html_link_special(dctx, self)}</li>\n")
1327 # Return true if the global class must be documented according to the visibility configured
1328 fun require_doc
(dctx
: DocContext): Bool
1330 if global
.visibility_level
== 3 and not dctx
.with_private
then return false # Private
1331 if dctx
.public_only
then
1332 var m
= intro_module
1333 if m
!= m
.toplevel_owner
then return false # Unexported
1338 # Fill the body for the page associated to the global class
1339 fun file_page_doc
(dctx
: DocContext)
1341 dctx
.add
("<div class=\"menu\
">\n")
1343 var props
= new Array[MMLocalProperty]
1344 var inh
= new HashMap[MMLocalClass, Array[MMLocalProperty]]
1345 var inhs
= new Array[MMLocalClass]
1346 for g
in global_properties
do
1348 if not p
.require_doc
(dctx
) then continue
1349 if p
.local_class
.global
== global
or g
.is_init_for
(self) or p
isa MMTypeProperty then
1352 var lc
= mmmodule
[p
.local_class
.global
]
1353 if inh
.has_key
(lc
) then
1364 dctx
.add
("<nav class=\"properties filterable\
">\n")
1365 dctx
.add
("<h3>Properties</h3>\n")
1367 dctx
.stage
("<h4>Virtual Types</h4>\n<ul>\n")
1369 if p
isa MMTypeProperty then
1373 dctx
.stage
("</ul>\n")
1376 dctx
.stage
("<h4>Constructors</h4>\n<ul>\n")
1378 if p
.global
.is_init_for
(self) then
1382 dctx
.stage
("</ul>\n")
1385 dctx
.stage
("<h4>Methods</h4>\n<ul>\n")
1387 if not p
.global
.is_init
and p
isa MMMethod then
1391 dctx
.stage
("</ul>\n")
1393 dctx
.add
("</nav>\n")
1395 dctx
.add
("<nav class=\"inheritance filterable\
">\n")
1396 dctx
.add
("<h3>Inheritance</h3>\n")
1397 dctx
.add
("<h4>Superclasses</h4>\n<ul>\n")
1398 for lc
in cshe
.linear_extension
do
1399 if lc
== self then continue
1400 if not lc
.require_doc
(dctx
) then continue
1401 dctx
.add
("<li>{lc.html_link(dctx)}</li>\n")
1404 if cshe
.smallers
.length
== 0 then
1405 dctx
.add
("<h4>No Known Subclasses</h4>\n")
1406 else if cshe
.smallers
.length
<= 100 then
1407 dctx
.add
("<h4>Subclasses</h4>\n")
1409 for lc
in cshe
.smallers
do
1410 if not lc
.require_doc
(dctx
) then continue
1411 dctx
.add
("<li>{lc.html_link(dctx)}</li>\n")
1414 else if cshe
.direct_smallers
.length
<= 100 then
1415 dctx
.add
("<h4>Direct Subclasses Only</h4>\n<ul>\n")
1416 for lc
in cshe
.direct_smallers
do
1417 if not lc
.require_doc
(dctx
) then continue
1418 dctx
.add
("<li>{lc.html_link(dctx)}</li>\n")
1422 dctx
.add
("<h4>Too much Subclasses to list</h4>\n")
1424 dctx
.add
("</nav>\n")
1426 dctx
.add
("</div>\n")
1429 dctx
.add
("<div class=\"content\
">\n")
1430 dctx
.add
("<h1>{name}</h1>\n")
1431 dctx
.add
("<div class='subtitle'>")
1432 if global
.visibility_level
== 2 then
1434 else if global
.visibility_level
== 3 then
1435 dctx
.add
("private ")
1436 else if self.global
.intro
.mmmodule
.toplevel_owner
.visibility_for
(self.global
.intro
.mmmodule
) <= 1 then
1437 dctx
.add
("(unexported) ")
1439 dctx
.add
("{kind} {global.intro.mmmodule.toplevel_owner.html_link(dctx)}::{name}</div>")
1441 dctx
.add
("<section class=\"description\
">\n")
1444 var l
= doc
.location
1445 dctx
.add
("<pre type=\"2\
" class=\"text_label\
" tag=\"{l.file.filename}\
" name=\"{dctx.get_source(l)}\
" title=\"{l.line_start.to_s}\
">{doc.to_html}</pre>\n")
1446 dctx
.add
("<textarea rows=\"1\
" cols=\"76\
" id=\"fileContent\
" class=\"edit\
"></textarea>")
1447 dctx
.add
("<a id=\"cancelBtn\
">Cancel</a><a id=\"commitBtn\
">Commit</a>")
1450 var cla
= new HashSet[MMLocalClass]
1451 var sm
= new HashSet[MMLocalClass]
1452 var sm2
= new HashSet[MMLocalClass]
1454 while cla
.length
+ sm
.length
< 10 and sm
.length
> 0 do
1458 sm2
.add_all
(x
.cshe
.direct_smallers
)
1464 cla
.add_all
(cshe
.greaters_and_self
)
1467 var name
= "class_{name}"
1468 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")
1471 op
.append
("\"{c.name}\
"[shape=box,margin=0.03];\n")
1473 op
.append
("\"{c.name}\
"[URL=\"{c.html_name}.html\
"];\n")
1475 for c2
in c
.cshe
.direct_greaters
do
1476 if not cla
.has
(c2
) then continue
1477 op
.append
("\"{c.name}\
"->\"{c2.name}\
";\n")
1479 if not c
.cshe
.direct_smallers
.is_empty
then
1481 for c2
in c
.cshe
.direct_smallers
do
1482 if cla
.has
(c2
) then others
= false
1485 op
.append
("\"{c.name}...\
"[label=\"\
"];\n")
1486 op
.append
("\"{c.name}...\
"->\"{c.name}\
"[style=dotted];\n")
1491 dctx
.gen_dot
(op
.to_s
, name
.to_s
, "Inheritance graph for class {name}")
1492 dctx
.add
("</section>\n")
1496 dctx
.stage
("<section class=\"concerns\
">\n")
1497 dctx
.stage
("<h2 class=\"section-header\
">Concerns</h2>\n")
1499 var mods
= new Array[MMModule]
1500 mods
.add
(global
.intro
.mmmodule
.toplevel_owner
)
1501 for lc
in crhe
.greaters
do
1502 if not lc
isa MMSrcLocalClass then continue
1503 var m
= lc
.mmmodule
.toplevel_owner
1504 if not mods
.has
(m
) then mods
.add
(m
)
1507 var intro
= global
.intro
.mmmodule
1512 if m
.short_doc
!= " " then short_doc
= ": {m.short_doc}"
1513 dctx
.add
("<li>{m.html_link_to_anchor}{short_doc}")
1515 for lc
in crhe
.linear_extension
.reversed
do
1516 if lc
.mmmodule
.toplevel_owner
!= m
then continue
1517 if lc
.mmmodule
== m
then continue
1519 if lc
.mmmodule
.short_doc
!= " " then short_doc
= ": {lc.mmmodule.short_doc}"
1520 dctx
.add
("<li>{lc.mmmodule.html_link_to_anchor}{short_doc}</li>")
1526 dctx
.stage
("</section>\n")
1530 dctx
.stage
("<section class=\"types\
">\n")
1531 dctx
.stage
("<h2>Formal and Virtual Types</h2>\n")
1532 for i
in [0..arity
[ do
1533 var f
= get_formal
(i
)
1534 f
.full_documentation
(dctx
, self)
1537 if not p
isa MMTypeProperty then continue
1538 p
.full_documentation
(dctx
, self)
1540 dctx
.stage
("</section>\n")
1544 dctx
.stage
("<section class=\"constructors\
">\n")
1545 dctx
.stage
("<h2 class=\"section-header\
">Constructors</h2>\n")
1547 if not p
.global
.is_init_for
(self) then continue
1548 p
.full_documentation
(dctx
, self)
1550 dctx
.stage
("</section>\n")
1554 dctx
.stage
("<section class=\"methods\
">\n")
1555 dctx
.stage
("<h2 class=\"section-header\
">Methods</h2>\n")
1556 var redefs
= new HashMap[MMModule, HashMap[MMModule, Array[MMMethod]]]
1558 if p
.global
.is_init
then continue
1559 if p
.local_class
.global
!= self.global
then continue
1560 if not p
isa MMMethod then continue
1562 var toplevel_module
= p
.mmmodule
.toplevel_owner
1563 if not redefs
.has_key
(toplevel_module
) then
1564 redefs
[toplevel_module
] = new HashMap[MMModule, Array[MMMethod]]
1567 var nested_module
= p
.mmmodule
1568 if not redefs
[toplevel_module
].has_key
(nested_module
) then
1569 redefs
[toplevel_module
][nested_module
] = new Array[MMMethod]
1572 redefs
[toplevel_module
][nested_module
].add
(p
)
1575 if p
.mmmodule
.toplevel_owner
!= p
.intro_module
then
1576 toplevel_module
= p
.intro_module
1577 nested_module
= p
.global
.intro
.mmmodule
1579 if not redefs
.has_key
(toplevel_module
) then
1580 redefs
[toplevel_module
] = new HashMap[MMModule, Array[MMMethod]]
1582 if not redefs
[toplevel_module
].has_key
(nested_module
) then
1583 redefs
[toplevel_module
][nested_module
] = new Array[MMMethod]
1586 redefs
[toplevel_module
][nested_module
].add
(p
.global
.intro
.as(MMMethod))
1590 # Display toplevel blocks
1592 if not redefs
.has_key
(m
) then continue
1593 dctx
.add
(m
.html_anchor
)
1594 if m
!= global
.intro
.mmmodule
.toplevel_owner
then
1595 dctx
.add
("<h3 class=\"concern-toplevel\
">Methods refined in {m.html_link(dctx)}</h3>")
1598 # Display nested module blocks
1599 for lc
in crhe
.linear_extension
.reversed
do
1600 if lc
.mmmodule
.toplevel_owner
!= m
then continue
1601 var nm
= lc
.mmmodule
1602 if not redefs
[m
].has_key
(nm
) then continue
1603 dctx
.add
(nm
.html_anchor
)
1604 if nm
!= global
.intro
.mmmodule
then
1606 if nm
.short_doc
!= " " then short_doc
= ": {nm.short_doc}"
1607 dctx
.add
("<p class=\"concern-doc\
">{nm.html_name}{short_doc}</p>\n")
1610 var pps
= redefs
[m
][nm
]
1613 p
.full_documentation
(dctx
, self)
1618 if not inhs
.is_empty
then
1620 dctx
.stage
("<h3>Inherited Methods</h3>\n")
1623 dctx
.stage
("<p>Defined in {lc.html_link(dctx)}:")
1625 var ims
= new Array[MMMethod]
1627 if p
.global
.is_init
then continue
1628 if not p
isa MMMethod then continue
1634 dctx
.add
(" {p.html_link(dctx)}")
1635 if i
< ims
.length
- 1 then dctx
.add
(",")
1644 dctx
.add
("</section>\n")
1646 dctx
.add
("</div> <!-- end class {name} -->\n")
1650 redef class MMSrcLocalClass
1656 else if global
.intro
== self then
1659 var bc
= global
.intro
1667 if not n
isa AStdClassdef then
1674 if d
.n_comment
.is_empty
then
1682 redef class MMSignature
1683 # Htlm transcription of the signature (with nested links)
1684 fun to_html
(dctx
: DocContext, with_closure
: Bool): String
1686 var res
= new Buffer
1689 for i
in [0..arity
[ do
1690 if i
> 0 then res
.append
(", ")
1691 res
.append
(self.params
[i
].name
.to_s
)
1693 res
.append
(self[i
].html_link
(dctx
))
1694 if self.vararg_rank
== i
then
1700 if return_type
!= null then
1702 res
.append
(return_type
.html_link
(dctx
))
1704 if with_closure
then
1705 for c
in closures
do
1707 if c
.is_optional
then res
.append
("[")
1708 if c
.is_break
then res
.append
("break ")
1709 res
.append
("!{c.name}")
1710 res
.append
(c
.signature
.to_html
(dctx
, false))
1711 if c
.is_optional
then res
.append
("]")
1719 # Htlm transcription of the type (with nested links)
1720 fun html_link
(dctx
: DocContext): String do return to_s
1723 redef class MMTypeSimpleClass
1724 redef fun html_link
(dctx
) do return local_class
.html_link
(dctx
)
1727 redef class MMTypeGeneric
1728 redef fun html_link
(dctx
)
1730 var res
= new Buffer
1731 res
.append
(local_class
.html_link
(dctx
))
1733 res
.append
(params
[0].html_link
(dctx
))
1734 for i
in [1..params
.length
[ do
1736 res
.append
(params
[i
].html_link
(dctx
))
1743 redef class MMTypeFormalParameter
1744 fun html_anchor
: String
1746 return "FT_{local_class}_{cmangle(name)}"
1748 redef fun html_link
(dctx
)
1750 return "<a href=\"#{html_anchor}\">{name}</a>"
1752 fun full_documentation
(dctx
: DocContext, lc
: MMLocalClass)
1754 dctx
.add
("<article id=\"{html_anchor}\
">\n")
1755 dctx
.add
("<h3 class=\"signature\
">{name}: {bound.html_link(dctx)}</h3>\n")
1756 dctx
.add
("<div class=\"info\
">")
1757 dctx
.add
("formal generic type")
1759 dctx
.add
("</article>")
1763 redef class MMNullableType
1764 redef fun html_link
(dctx
) do return "nullable " + as_notnull
.html_link
(dctx
)
1767 redef class MMVirtualType
1768 redef fun html_link
(dctx
) do return property
.html_link
(dctx
)
1771 var c
= new DocContext