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 class=\"githubTitle\
"><h3>Github Sign In</h3></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=\"divGitHubRepoDisplay\
"><label id=\"lbRepoDisplay\
">Repository: </label><strong><label id=\"githubRepoDisplay\
"></label></strong></div></div><div><label id=\"lbrepositoryGit\
" for=\"repository\
">Repository</label><input id=\"repositoryGit\
" type=\"text\
" name=\"repository\
"><div id=\"listBranches\
"><label id=\"lbBranches\
">Branch </label><select id=\"dropBranches\
" name=\"dropBranches\
" tabindex=\"1\
" class=\"dropdown\
"></select></div></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"
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"
186 add
("<!DOCTYPE html>")
187 add
("<html><head>{head}<title>Overview | {custom_title}</title></head><body>\n")
189 add
("<div class=\"page\
">")
190 add
("<div class=\"content fullpage\
">")
191 add
("<h1>{custom_title}</h1>\n<article class='overview'>{overview_text}</article><article class='overview'><h2>Modules</h2><ul>")
192 var modss
= mainmod
.mhe
.greaters_and_self
.to_a
195 if not mod
.is_toplevel
then continue
196 if not mod
.require_doc
(self) then continue
197 assert mod
isa MMSrcModule
198 add
("<li>{mod.html_link(self)} {mod.short_doc}</li>")
204 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")
206 if not mod
.is_toplevel
then continue
207 if not mod
.require_doc
(self) then continue
208 op
.append
("\"{mod.name}\
"[URL=\"{mod.html_name}.html\
"];\n")
209 for mod2
in mod
.tmhe
.direct_greaters
do
210 if not modss
.has
(mod2
) then continue
211 op
.append
("\"{mod.name}\
"->\"{mod2.name}\
";\n")
215 self.gen_dot
(op
.to_s
, "dep", "Modules hierarchy")
216 add
("</article></div>")
218 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 class=\"githubTitle\
"><h3>Github Sign In</h3></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=\"divGitHubRepoDisplay\
"><label id=\"lbRepoDisplay\
">Repository: </label><strong><label id=\"githubRepoDisplay\
"></label></strong></div></div><div><label id=\"lbrepositoryGit\
" for=\"repository\
">Repository</label><input id=\"repositoryGit\
" type=\"text\
" name=\"repository\
"><div id=\"listBranches\
"><label id=\"lbBranches\
">Branch </label><select id=\"dropBranches\
" name=\"dropBranches\
" tabindex=\"1\
" class=\"dropdown\
"></select></div></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>")
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 class=\"githubTitle\
"><h3>Github Sign In</h3></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=\"divGitHubRepoDisplay\
"><label id=\"lbRepoDisplay\
">Repository: </label><strong><label id=\"githubRepoDisplay\
"></label></strong></div></div><div><label id=\"lbrepositoryGit\
" for=\"repository\
">Repository</label><input id=\"repositoryGit\
" type=\"text\
" name=\"repository\
"><div id=\"listBranches\
"><label id=\"lbBranches\
">Branch </label><select id=\"dropBranches\
" name=\"dropBranches\
" tabindex=\"1\
" class=\"dropdown\
"></select></div></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"
251 add
("<!DOCTYPE html>")
252 add
("<html><head>{head}<title>{c.name} class | {custom_title}</title></head><body>\n")
254 add
("<div class=\"page\
">")
255 c
.file_page_doc
(self)
257 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 class=\"githubTitle\
"><h3>Github Sign In</h3></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=\"divGitHubRepoDisplay\
"><label id=\"lbRepoDisplay\
">Repository: </label><strong><label id=\"githubRepoDisplay\
"></label></strong></div></div><div><label id=\"lbrepositoryGit\
" for=\"repository\
">Repository</label><input id=\"repositoryGit\
" type=\"text\
" name=\"repository\
"><div id=\"listBranches\
"><label id=\"lbBranches\
">Branch </label><select id=\"dropBranches\
" name=\"dropBranches\
" tabindex=\"1\
" class=\"dropdown\
"></select></div></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"
267 add
("<!DOCTYPE html>")
268 add
("<html><head>{head}<title>Full Index | {custom_title}</title></head><body>\n")
270 add
("<div class=\"page\
">")
271 add
("<div class=\"content fullpage\
">")
272 mainmod
.file_index_page_doc
(self)
275 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><textarea id=\"commitMessage\
" rows=\"1\
" cols=\"76\
" name=\"commitMessage\
" ></textarea><input id=\"chkSignedOff\
" type=\"checkbox\
" name=\"chkSignedOff\
">Signed-Off </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")
637 dctx
.add
("<div style=\"float
: right
;\
"><a id=\"lblDiffCommit\
"></a></div>")
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>")
646 dctx
.add
("<pre id=\"preSave\
" type=\"2\
" class=\"text_label\
" ></pre>")
651 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")
652 var ms
= new Array[nullable MMModule]
654 var m0
: nullable MMModule = self
660 var cla
= new HashSet[MMModule]
662 for m0
in self.mhe
.greaters
do
663 if not m0
.require_doc
(dctx
) then continue
664 if self.visibility_for
(m0
) <= 1 then continue # private or hidden
665 if self.mnhe
<= m0
then continue # do not want nested stuff
666 if m0
.direct_owner
!= null and not m0
.direct_owner
.mnhe
<= self then continue # not in the right nesting
669 for m0
in self.mhe
.smallers
do
670 if not m0
.require_doc
(dctx
) then continue
671 if m0
.visibility_for
(self) <= 1 then continue # private or hidden
672 if m0
.direct_owner
!= null and not m0
.direct_owner
.mnhe
<= self then continue # not in the right nesting
675 for m0
in self.mnhe
.smallers
do
681 op
.append
("subgraph \"cluster_
{m0.name}\
"\{\n")
684 if c
.direct_owner
!= m0
then continue
686 op
.append
("\"{c.name}\
"[shape=box,margin=0.03];\n")
688 op
.append
("\"{c.name}\
"[URL=\"{c.html_name}.html\
"];\n")
692 op
.append
("\"{m0.name}\
"[URL=\"{m0.html_name}.html\
"];\n")
693 for c
in m0
.mhe
.direct_greaters
do
694 if not cla
.has
(c
) then continue
695 op
.append
("\"{m0.name}\
"->\"{c.name}\
";\n")
700 # Close the nesting subgraph
706 for c2
in c
.tmhe
.direct_greaters
do
707 if not cla
.has
(c2
) then continue
708 op
.append
("\"{c.name}\
"->\"{c2.name}\
";\n")
712 dctx
.gen_dot
(op
.to_s
, name
.to_s
, "Dependency graph for module {name}")
713 dctx
.add
("</section>")
715 var clas
= new Array[MMLocalClass]
716 var props
= new HashMap[MMGlobalProperty, Array[MMLocalProperty]]
717 var gprops
= new Array[MMLocalProperty]
720 for g
in m
.global_classes
do
722 if not lc
.require_doc
(dctx
) then continue
723 var im
= g
.intro
.mmmodule
724 if self.visibility_for
(im
) <= 1 then continue # private import or invisible import
726 for lc2
in lc
.crhe
.greaters_and_self
do
727 if not lc2
isa MMSrcLocalClass then continue
728 if not self.mnhe
<= lc2
.mmmodule
then continue # not introduced/redefined here/stolen
731 if not keep
then continue
733 lc
.compute_super_classes
734 for gp
in lc
.global_properties
do
735 if self.visibility_for
(gp
.intro
.local_class
.mmmodule
) <= 1 then continue # private import or invisible import
737 var mp
= lp
.local_class
.mmmodule
738 if not self.mnhe
<= mp
then continue # not introduced/redefined here/stolen
740 if not lp
.require_doc
(dctx
) then continue
741 if props
.has_key
(lp
.global
) then
742 if not props
[lp
.global
].has
(lp
) then
743 props
[lp
.global
].add
(lp
)
746 props
[lp
.global
] = [lp
]
747 gprops
.add
(lp
.global
.intro
)
752 dctx
.add
("<section class=\"module\
">\n")
754 dctx
.stage
("<article class=\"classes filterable\
">\n")
755 dctx
.stage
("<h2>Classes</h2>\n")
759 if self.mnhe
<= lc
.global
.intro
.mmmodule
then
760 dctx
.add
("<li class='intro'><span title='introduced in this module'>I</span> ")
762 dctx
.add
("<li class='redef'><span title='refined in this module'>R</span> ")
764 dctx
.add
("{lc.html_link(dctx)}</li>\n")
766 dctx
.stage
("</ul></article>\n")
770 dctx
.stage
("<article class=\"properties filterable\
">\n")
771 dctx
.stage
("<h2>Properties</h2>\n")
778 if gp
.intro
isa MMAttribute then continue
780 var lpi
= self[gp
.intro
.local_class
.global
][gp
]
783 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")
786 dctx
.add
("<li class='intro'><span title='introduction in this module'>I</span> {lpi.html_name}")
787 dctx
.add
(" ({lpi.local_class})</li>\n")
789 if lps
.length
>= 1 then
792 dctx
.add
("<li class='redef'><span title='redefinition'>R</span> {lp.html_open_link(dctx)}{lp.html_name} ({lp.local_class})</a></li>")
796 dctx
.stage
("</ul></article>\n")
798 dctx
.add
("</section>\n")
802 # Fill the body for the page associated to the full index
803 fun file_index_page_doc
(dctx
: DocContext)
806 dctx
.add
("<h1>Full Index</h1>\n")
808 var clas
= new Array[MMLocalClass]
809 var props
= new HashMap[MMGlobalProperty, Array[MMLocalProperty]]
810 var gprops
= new Array[MMLocalProperty]
811 var mods
= new Array[MMModule]
812 for m
in mhe
.greaters_and_self
do
813 if not m
.require_doc
(dctx
) then continue
816 for g
in global_classes
do
818 if not lc
.require_doc
(dctx
) then continue
820 for gp
in lc
.global_properties
do
822 if not lp
.require_doc
(dctx
) then continue
823 if props
.has_key
(lp
.global
) then
824 if not props
[lp
.global
].has
(lp
) then
825 props
[lp
.global
].add
(lp
)
828 props
[lp
.global
] = [lp
]
829 gprops
.add
(lp
.global
.intro
)
834 dctx
.stage
("<article class=\"modules filterable\
">\n")
835 dctx
.stage
("<h2>Modules</h2>\n")
839 dctx
.add
("<li>{m.html_link(dctx)}</li>")
841 dctx
.stage
("</ul></article>\n")
845 dctx
.stage
("<article class=\"classes filterable\
">\n")
846 dctx
.stage
("<h2>Classes</h2>\n")
850 dctx
.add
("<li>{lc.html_link(dctx)}</li>")
852 dctx
.stage
("</ul></article>\n")
856 dctx
.stage
("<article class=\"properties filterable\
">\n")
857 dctx
.stage
("<h2>Properties</h2>\n")
864 if gp
.intro
isa MMAttribute then continue
866 var lpi
= self[gp
.intro
.local_class
.global
][gp
]
869 dctx
.add
("<li class='intro'><span title='introduction'>I</span> {lpi.html_open_link(dctx)}{lpi.html_name} ({lpi.local_class})</a></li>\n")
870 if lps
.length
>= 1 then
873 dctx
.add
("<li class='redef'><span title='redefinition'>R</span> {lp.html_open_link(dctx)}{lp.html_name} ({lp.local_class})</a></li>\n")
877 dctx
.stage
("</ul></article>\n")
881 # Fill the quicksearch list JSON object
882 fun file_quicksearch_list_doc
(dctx
: DocContext)
884 var entities
= new HashMap[String, Array[MMEntity]]
885 var props
= new HashMap[MMGlobalProperty, Array[MMLocalProperty]]
886 for m
in mhe
.greaters_and_self
do
887 if not m
.require_doc
(dctx
) then continue
888 var a
= new Array[MMEntity]
890 entities
[m
.html_name
] = a
892 for g
in global_classes
do
894 if not lc
.require_doc
(dctx
) then continue
895 var a
= new Array[MMEntity]
897 entities
[lc
.html_name
] = a
898 for gp
in lc
.global_properties
do
900 if not lp
.require_doc
(dctx
) then continue
901 if lp
.kind
== "var" then continue
902 if props
.has_key
(lp
.global
) then
903 if not props
[lp
.global
].has
(lp
) then
904 props
[lp
.global
].add
(lp
)
907 props
[lp
.global
] = [lp
]
913 entities
[k
.short_name
] = v
916 var keys
= entities
.keys
.to_a
917 var sorter
= new AlphaSorter[String]
921 dctx
.stage
("var entries = \{")
923 dctx
.add
("\"{key}\
": [")
924 for entity
in entities
[key
] do
925 dctx
.add
(entity
.json_entry
(dctx
))
934 redef class MMGlobalProperty
935 # Return the short name of the property
936 fun short_name
: String do
937 return self.intro
.html_name
941 redef class MMLocalProperty
943 # Anchor of the property description in the module html file
944 fun html_anchor
: String
946 return "PROP_{self.mmmodule.toplevel_owner}_{local_class}_{cmangle(name)}"
949 redef fun json_entry
(dctx
) do
950 return "\{txt:\"{qualified_name}\",url
:\
"{local_class.html_name}.html#{html_anchor}\"\
},"
953 redef fun qualified_name do
954 return "{intro_module.qualified_name}::{local_class.html_name}::{html_name}"
957 fun html_open_link(dctx: DocContext): String
959 if not require_doc(dctx) then print "not required
{self}"
960 var title = "{html_name}{signature.to_s}"
961 if short_doc != " 
;" then
962 title += " #{short_doc}"
964 return "<a href=\"{local_class.html_name}.html
#{html_anchor}\" title=\"{title}\">"
967 fun html_name
: String
969 return self.name
.to_s
.html_escape
972 redef fun html_link
(dctx
)
974 if not require_doc
(dctx
) then print
"not required {self}"
975 var title
= "{html_name}{signature.to_s}"
976 if short_doc
!= " " then
977 title
+= " #{short_doc}"
979 return "<a href=\"{local_class.html_name}.html
#{html_anchor}\" title=\"{title}\">{html_name}</a>"
982 fun html_link_special
(dctx
: DocContext, lc
: MMLocalClass): String
984 if not require_doc
(dctx
) then print
"not required {self}"
985 var title
= "{html_name}{signature_for(lc.get_type)}"
986 if short_doc
!= " " then
987 title
+= " #{short_doc}"
989 return "<a href=\"{lc.html_name}.html
#{html_anchor}\" title=\"{title}\">{html_name}</a>"
992 # Kind of property (fun, attr, etc.)
993 fun kind
: String is abstract
1000 else if global
.intro
== self then
1003 return global
.intro
.short_doc
1010 if n
== null or not n
isa APropdef then
1017 if d
.n_comment
.is_empty
then
1024 # The most specific module in the nesting hierarchy that exports the intro of self
1025 fun intro_module
: MMModule
1027 var m
= global
.intro
.mmmodule
1028 var mo
= m
.direct_owner
1029 while mo
!= null and mo
.visibility_for
(m
) >= 2 do
1036 # Is the intro of self exported by the top-level module ?
1037 fun is_toplevel
: Bool
1039 var m
= intro_module
1040 return m
== m
.toplevel_owner
1043 # Return true if the global property must be documented according to the visibility configured
1044 fun require_doc
(dctx
: DocContext): Bool
1046 if global
.visibility_level
== 3 and not dctx
.with_private
then return false # Private
1047 if dctx
.public_only
then
1048 var m
= intro_module
1049 if m
!= m
.toplevel_owner
then return false # Unexported
1054 # Document the global property in the global class lc
1055 fun full_documentation
(dctx
: DocContext, lc
: MMLocalClass)
1057 var visibility
: String
1058 if global
.visibility_level
== 1 then
1059 visibility
= "public"
1060 else if global
.visibility_level
== 2 then
1061 visibility
= "protected"
1062 else if global
.visibility_level
== 3 then
1063 visibility
= "private"
1068 var intro_class
= global
.intro
.local_class
1069 var is_redef
= local_class
.global
!= intro_class
.global
or local_class
.mmmodule
.toplevel_owner
!= intro_class
.mmmodule
.toplevel_owner
1071 dctx
.add
("<article id=\"{html_anchor}\
" class=\"{kind} {visibility} {if is_redef then "redef" else ""}\
">\n")
1072 dctx
.add
("<h3 class=\"signature\
">{html_name}{signature.to_html(dctx, true)}</h3>\n")
1073 dctx
.add
("<div class=\"info\
">\n")
1078 if not is_toplevel
then
1079 dctx
.add
("(unexported) ")
1081 if global
.visibility_level
== 2 then
1082 dctx
.add
("protected ")
1083 else if global
.visibility_level
== 3 then
1084 dctx
.add
("private ")
1087 dctx
.add
(" {intro_class.mmmodule.toplevel_owner.name}")
1088 if intro_class
.global
== lc
.global
then
1089 dctx
.add
("::{lc.name}")
1091 dctx
.add
("::{mmmodule[intro_class.global].html_link(dctx)}")
1094 dctx
.add
("::{mmmodule[intro_class.global][global].global.intro.html_link(dctx)}")
1096 dctx
.add
("::{html_name}")
1099 dctx
.add
("<div style=\"float
: right
;\
"><a id=\"lblDiffCommit\
"></a></div>")
1100 dctx
.add
("<div class=\"description\
">")
1102 # Collect all refinement of the global property in the same global property
1103 var lps
= new Array[MMLocalProperty]
1104 for l
in prhe
.greaters_and_self
do
1108 var introdoc
= false
1109 if global
.intro
.doc
!= null then
1111 if lp
.doc
== null then introdoc
= true
1115 dctx
.add
("<pre class=\"text_label\
" name=\"{html_name}\
" >{global.intro.doc.to_html}</pre>")
1116 dctx
.add
("<textarea rows=\"1\
" cols=\"76\
" id=\"fileContent\
" class=\"edit\
"></textarea>")
1117 dctx
.add
("<a id=\"cancelBtn\
">Cancel</a><a id=\"commitBtn\
">Commit</a>")
1118 dctx
.add
("<pre id=\"preSave\
" type=\"2\
" class=\"text_label\
" ></pre>")
1121 var tlmods
= new Array[MMModule]
1123 var bm
= lp
.mmmodule
.toplevel_owner
1124 var lcm
= lc
.global
.intro
.mmmodule
1125 if lcm
.mhe
< lp
.mmmodule
then bm
= lcm
.toplevel_owner
1126 if not tlmods
.has
(bm
) then tlmods
.add
(bm
)
1130 # Document the top level property for the current top level module
1132 if tm
.global_classes
.has
(lc
.global
) then
1133 tlp
= tm
[lc
.global
][self.global
]
1135 else if tm
.global_classes
.has
(self.local_class
.global
) then
1136 # Self is the inherited property. Process it
1137 tlp
= tm
[self.local_class
.global
][self.global
]
1140 # We skip this module since the props defined by the module is
1144 var tlcm
= lc
.global
.intro
.mmmodule
.toplevel_owner
1145 if not tlcm
.mhe
<= tm
then
1146 dctx
.add
("<h4>In module {tm.html_link(dctx)} :</h4>")
1151 if doc
!= null and (not introdoc
or global
.intro
.doc
!= doc
) then
1154 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>")
1156 else if not is_redef
then
1159 dctx
.add
("<a class=\"newComment\
" tag=\"{l.file.filename}\
" title=\"{l.line_start.to_s}\
">New comment</a>\n")
1162 dctx
.add
("<textarea rows=\"1\
" cols=\"76\
" id=\"fileContent\
" class=\"edit\
"></textarea>")
1163 dctx
.add
("<a id=\"cancelBtn\
">Cancel</a><a id=\"commitBtn\
">Commit</a>")
1164 dctx
.add
("<pre id=\"preSave\
" type=\"2\
" class=\"text_label\
" ></pre>")
1166 if tlp
.local_class
.global
!= lc
.global
then
1167 dctx
.add
("inherited from {tlp.local_class.html_link(dctx)} ")
1169 if tm
!= tlp
.mmmodule
then
1170 dctx
.add
("defined by the module {tlp.mmmodule.html_link(dctx)} ")
1178 dctx
.stage
(". previously defined by:")
1180 var tl
= lp
.mmmodule
.toplevel_owner
1181 if tl
!= tm
then continue
1182 if lp
== tlp
then continue
1183 dctx
.add
(" {lp.mmmodule.html_link(dctx)}")
1184 if lp
.local_class
.global
!= lc
.global
then
1185 dctx
.add
(" for {lp.local_class.html_link(dctx)} ")
1198 dctx
.add
("</article>")
1201 redef class MMMethod
1202 redef fun kind
do return if global
.is_init
then "init" else "fun"
1204 redef class MMAttribute
1205 redef fun kind
do return "var"
1207 redef class MMTypeProperty
1208 redef fun kind
do return "type"
1211 redef class MMSrcModule
1225 if n
.n_moduledecl
== null then
1228 var np
= n
.n_moduledecl
1233 if d
.n_comment
.is_empty
then
1242 # Html transcription of the doc
1245 var res
= new Buffer
1246 for c
in n_comment
do
1247 res
.append
(c
.text
.substring_from
(1))
1249 return res
.to_s
.html_escape
1252 # Oneliner transcription of the doc
1255 return n_comment
.first
.text
.substring_from
(1).html_escape
1259 redef class MMLocalClass
1262 # Anchor of the class description in the module html file
1263 fun html_anchor
: String do return "CLASS_{self}"
1265 fun html_name
: String do return "{self}"
1267 redef fun html_link
(dctx
)
1269 if not require_doc
(dctx
) then print
"{dctx.filename}: not required {self}"
1270 if short_doc
== " " then
1271 return "<a href=\"{html_name}.html\
"\">{self}</a
>"
1273 return "<a href
=\
"{html_name}.html\" title
=\
"{short_doc}\">{self}</a
>"
1277 redef fun json_entry(dctx) do
1278 return "\
{txt:\"{qualified_name}\
",url:\"{html_name}.html\
"\},"
1281 redef fun qualified_name
do
1282 return "{intro_module.qualified_name}::{html_name}"
1285 redef fun short_doc
do return global
.intro
.short_doc
1287 redef fun doc
do return global
.intro
.doc
1291 if global
.is_interface
then
1293 else if global
.is_abstract
then
1294 return "abstract class"
1295 else if global
.is_enum
then
1302 # The most specific module in the nesting hierarchy that exports the intro of self
1303 fun intro_module
: MMModule
1305 var m
= global
.intro
.mmmodule
1306 var mo
= m
.direct_owner
1307 while mo
!= null and mo
.visibility_for
(m
) >= 2 do
1314 fun menu_link
(dctx
: DocContext, p
: MMLocalProperty)
1316 if p
.local_class
.global
!= self.global
then
1317 if p
.global
.intro
.local_class
.name
== "Object".to_symbol
then return
1318 if p
.global
.is_init
or p
isa MMTypeProperty then
1319 dctx
.add
("<li class='inherit'><span title='Inherited'>H</span> {p.html_link_special(dctx, self)}</li>\n")
1321 dctx
.add
("<li class='inherit'><span title='Inherited'>H</span> {p.html_link(dctx)}</li>\n")
1323 else if p
.global
.intro
.local_class
.global
== self.global
then
1324 dctx
.add
("<li class='intro'><span title='Introduced'>I</span> {p.html_link_special(dctx, self)}</li>\n")
1326 dctx
.add
("<li class='redef'><span title='Redefined'>R</span> {p.html_link_special(dctx, self)}</li>\n")
1330 # Return true if the global class must be documented according to the visibility configured
1331 fun require_doc
(dctx
: DocContext): Bool
1333 if global
.visibility_level
== 3 and not dctx
.with_private
then return false # Private
1334 if dctx
.public_only
then
1335 var m
= intro_module
1336 if m
!= m
.toplevel_owner
then return false # Unexported
1341 # Fill the body for the page associated to the global class
1342 fun file_page_doc
(dctx
: DocContext)
1344 dctx
.add
("<div class=\"menu\
">\n")
1346 var props
= new Array[MMLocalProperty]
1347 var inh
= new HashMap[MMLocalClass, Array[MMLocalProperty]]
1348 var inhs
= new Array[MMLocalClass]
1349 for g
in global_properties
do
1351 if not p
.require_doc
(dctx
) then continue
1352 if p
.local_class
.global
== global
or g
.is_init_for
(self) or p
isa MMTypeProperty then
1355 var lc
= mmmodule
[p
.local_class
.global
]
1356 if inh
.has_key
(lc
) then
1367 dctx
.add
("<nav class=\"properties filterable\
">\n")
1368 dctx
.add
("<h3>Properties</h3>\n")
1370 dctx
.stage
("<h4>Virtual Types</h4>\n<ul>\n")
1372 if p
isa MMTypeProperty then
1376 dctx
.stage
("</ul>\n")
1379 dctx
.stage
("<h4>Constructors</h4>\n<ul>\n")
1381 if p
.global
.is_init_for
(self) then
1385 dctx
.stage
("</ul>\n")
1388 dctx
.stage
("<h4>Methods</h4>\n<ul>\n")
1390 if not p
.global
.is_init
and p
isa MMMethod then
1394 dctx
.stage
("</ul>\n")
1396 dctx
.add
("</nav>\n")
1398 dctx
.add
("<nav class=\"inheritance filterable\
">\n")
1399 dctx
.add
("<h3>Inheritance</h3>\n")
1400 dctx
.add
("<h4>Superclasses</h4>\n<ul>\n")
1401 for lc
in cshe
.linear_extension
do
1402 if lc
== self then continue
1403 if not lc
.require_doc
(dctx
) then continue
1404 dctx
.add
("<li>{lc.html_link(dctx)}</li>\n")
1407 if cshe
.smallers
.length
== 0 then
1408 dctx
.add
("<h4>No Known Subclasses</h4>\n")
1409 else if cshe
.smallers
.length
<= 100 then
1410 dctx
.add
("<h4>Subclasses</h4>\n")
1412 for lc
in cshe
.smallers
do
1413 if not lc
.require_doc
(dctx
) then continue
1414 dctx
.add
("<li>{lc.html_link(dctx)}</li>\n")
1417 else if cshe
.direct_smallers
.length
<= 100 then
1418 dctx
.add
("<h4>Direct Subclasses Only</h4>\n<ul>\n")
1419 for lc
in cshe
.direct_smallers
do
1420 if not lc
.require_doc
(dctx
) then continue
1421 dctx
.add
("<li>{lc.html_link(dctx)}</li>\n")
1425 dctx
.add
("<h4>Too much Subclasses to list</h4>\n")
1427 dctx
.add
("</nav>\n")
1429 dctx
.add
("</div>\n")
1432 dctx
.add
("<div class=\"content\
">\n")
1433 dctx
.add
("<h1>{name}</h1>\n")
1434 dctx
.add
("<div class='subtitle'>")
1435 if global
.visibility_level
== 2 then
1437 else if global
.visibility_level
== 3 then
1438 dctx
.add
("private ")
1439 else if self.global
.intro
.mmmodule
.toplevel_owner
.visibility_for
(self.global
.intro
.mmmodule
) <= 1 then
1440 dctx
.add
("(unexported) ")
1442 dctx
.add
("{kind} {global.intro.mmmodule.toplevel_owner.html_link(dctx)}::{name}</div>")
1443 dctx
.add
("<div style=\"float
: right
;\
"><a id=\"lblDiffCommit\
"></a></div>")
1444 dctx
.add
("<section class=\"description\
">\n")
1447 var l
= doc
.location
1448 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")
1449 dctx
.add
("<textarea rows=\"1\
" cols=\"76\
" id=\"fileContent\
" class=\"edit\
"></textarea>")
1450 dctx
.add
("<a id=\"cancelBtn\
">Cancel</a><a id=\"commitBtn\
">Commit</a>")
1451 dctx
.add
("<pre id=\"preSave\
" type=\"2\
" class=\"text_label\
" ></pre>")
1454 var cla
= new HashSet[MMLocalClass]
1455 var sm
= new HashSet[MMLocalClass]
1456 var sm2
= new HashSet[MMLocalClass]
1458 while cla
.length
+ sm
.length
< 10 and sm
.length
> 0 do
1462 sm2
.add_all
(x
.cshe
.direct_smallers
)
1468 cla
.add_all
(cshe
.greaters_and_self
)
1471 var name
= "class_{name}"
1472 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")
1475 op
.append
("\"{c.name}\
"[shape=box,margin=0.03];\n")
1477 op
.append
("\"{c.name}\
"[URL=\"{c.html_name}.html\
"];\n")
1479 for c2
in c
.cshe
.direct_greaters
do
1480 if not cla
.has
(c2
) then continue
1481 op
.append
("\"{c.name}\
"->\"{c2.name}\
";\n")
1483 if not c
.cshe
.direct_smallers
.is_empty
then
1485 for c2
in c
.cshe
.direct_smallers
do
1486 if cla
.has
(c2
) then others
= false
1489 op
.append
("\"{c.name}...\
"[label=\"\
"];\n")
1490 op
.append
("\"{c.name}...\
"->\"{c.name}\
"[style=dotted];\n")
1495 dctx
.gen_dot
(op
.to_s
, name
.to_s
, "Inheritance graph for class {name}")
1496 dctx
.add
("</section>\n")
1500 dctx
.stage
("<section class=\"concerns\
">\n")
1501 dctx
.stage
("<h2 class=\"section-header\
">Concerns</h2>\n")
1503 var mods
= new Array[MMModule]
1504 mods
.add
(global
.intro
.mmmodule
.toplevel_owner
)
1505 for lc
in crhe
.greaters
do
1506 if not lc
isa MMSrcLocalClass then continue
1507 var m
= lc
.mmmodule
.toplevel_owner
1508 if not mods
.has
(m
) then mods
.add
(m
)
1511 var intro
= global
.intro
.mmmodule
1516 if m
.short_doc
!= " " then short_doc
= ": {m.short_doc}"
1517 dctx
.add
("<li>{m.html_link_to_anchor}{short_doc}")
1519 for lc
in crhe
.linear_extension
.reversed
do
1520 if lc
.mmmodule
.toplevel_owner
!= m
then continue
1521 if lc
.mmmodule
== m
then continue
1523 if lc
.mmmodule
.short_doc
!= " " then short_doc
= ": {lc.mmmodule.short_doc}"
1524 dctx
.add
("<li>{lc.mmmodule.html_link_to_anchor}{short_doc}</li>")
1530 dctx
.stage
("</section>\n")
1534 dctx
.stage
("<section class=\"types\
">\n")
1535 dctx
.stage
("<h2>Formal and Virtual Types</h2>\n")
1536 for i
in [0..arity
[ do
1537 var f
= get_formal
(i
)
1538 f
.full_documentation
(dctx
, self)
1541 if not p
isa MMTypeProperty then continue
1542 p
.full_documentation
(dctx
, self)
1544 dctx
.stage
("</section>\n")
1548 dctx
.stage
("<section class=\"constructors\
">\n")
1549 dctx
.stage
("<h2 class=\"section-header\
">Constructors</h2>\n")
1551 if not p
.global
.is_init_for
(self) then continue
1552 p
.full_documentation
(dctx
, self)
1554 dctx
.stage
("</section>\n")
1558 dctx
.stage
("<section class=\"methods\
">\n")
1559 dctx
.stage
("<h2 class=\"section-header\
">Methods</h2>\n")
1560 var redefs
= new HashMap[MMModule, HashMap[MMModule, Array[MMMethod]]]
1562 if p
.global
.is_init
then continue
1563 if p
.local_class
.global
!= self.global
then continue
1564 if not p
isa MMMethod then continue
1566 var toplevel_module
= p
.mmmodule
.toplevel_owner
1567 if not redefs
.has_key
(toplevel_module
) then
1568 redefs
[toplevel_module
] = new HashMap[MMModule, Array[MMMethod]]
1571 var nested_module
= p
.mmmodule
1572 if not redefs
[toplevel_module
].has_key
(nested_module
) then
1573 redefs
[toplevel_module
][nested_module
] = new Array[MMMethod]
1576 redefs
[toplevel_module
][nested_module
].add
(p
)
1579 if p
.mmmodule
.toplevel_owner
!= p
.intro_module
then
1580 toplevel_module
= p
.intro_module
1581 nested_module
= p
.global
.intro
.mmmodule
1583 if not redefs
.has_key
(toplevel_module
) then
1584 redefs
[toplevel_module
] = new HashMap[MMModule, Array[MMMethod]]
1586 if not redefs
[toplevel_module
].has_key
(nested_module
) then
1587 redefs
[toplevel_module
][nested_module
] = new Array[MMMethod]
1590 redefs
[toplevel_module
][nested_module
].add
(p
.global
.intro
.as(MMMethod))
1594 # Display toplevel blocks
1596 if not redefs
.has_key
(m
) then continue
1597 dctx
.add
(m
.html_anchor
)
1598 if m
!= global
.intro
.mmmodule
.toplevel_owner
then
1599 dctx
.add
("<h3 class=\"concern-toplevel\
">Methods refined in {m.html_link(dctx)}</h3>")
1602 # Display nested module blocks
1603 for lc
in crhe
.linear_extension
.reversed
do
1604 if lc
.mmmodule
.toplevel_owner
!= m
then continue
1605 var nm
= lc
.mmmodule
1606 if not redefs
[m
].has_key
(nm
) then continue
1607 dctx
.add
(nm
.html_anchor
)
1608 if nm
!= global
.intro
.mmmodule
then
1610 if nm
.short_doc
!= " " then short_doc
= ": {nm.short_doc}"
1611 dctx
.add
("<p class=\"concern-doc\
">{nm.html_name}{short_doc}</p>\n")
1614 var pps
= redefs
[m
][nm
]
1617 p
.full_documentation
(dctx
, self)
1622 if not inhs
.is_empty
then
1624 dctx
.stage
("<h3>Inherited Methods</h3>\n")
1627 dctx
.stage
("<p>Defined in {lc.html_link(dctx)}:")
1629 var ims
= new Array[MMMethod]
1631 if p
.global
.is_init
then continue
1632 if not p
isa MMMethod then continue
1638 dctx
.add
(" {p.html_link(dctx)}")
1639 if i
< ims
.length
- 1 then dctx
.add
(",")
1648 dctx
.add
("</section>\n")
1650 dctx
.add
("</div> <!-- end class {name} -->\n")
1654 redef class MMSrcLocalClass
1660 else if global
.intro
== self then
1663 var bc
= global
.intro
1671 if not n
isa AStdClassdef then
1678 if d
.n_comment
.is_empty
then
1686 redef class MMSignature
1687 # Htlm transcription of the signature (with nested links)
1688 fun to_html
(dctx
: DocContext, with_closure
: Bool): String
1690 var res
= new Buffer
1693 for i
in [0..arity
[ do
1694 if i
> 0 then res
.append
(", ")
1695 res
.append
(self.params
[i
].name
.to_s
)
1697 res
.append
(self[i
].html_link
(dctx
))
1698 if self.vararg_rank
== i
then
1704 if return_type
!= null then
1706 res
.append
(return_type
.html_link
(dctx
))
1708 if with_closure
then
1709 for c
in closures
do
1711 if c
.is_optional
then res
.append
("[")
1712 if c
.is_break
then res
.append
("break ")
1713 res
.append
("!{c.name}")
1714 res
.append
(c
.signature
.to_html
(dctx
, false))
1715 if c
.is_optional
then res
.append
("]")
1723 # Htlm transcription of the type (with nested links)
1724 fun html_link
(dctx
: DocContext): String do return to_s
1727 redef class MMTypeSimpleClass
1728 redef fun html_link
(dctx
) do return local_class
.html_link
(dctx
)
1731 redef class MMTypeGeneric
1732 redef fun html_link
(dctx
)
1734 var res
= new Buffer
1735 res
.append
(local_class
.html_link
(dctx
))
1737 res
.append
(params
[0].html_link
(dctx
))
1738 for i
in [1..params
.length
[ do
1740 res
.append
(params
[i
].html_link
(dctx
))
1747 redef class MMTypeFormalParameter
1748 fun html_anchor
: String
1750 return "FT_{local_class}_{cmangle(name)}"
1752 redef fun html_link
(dctx
)
1754 return "<a href=\"#{html_anchor}\">{name}</a>"
1756 fun full_documentation
(dctx
: DocContext, lc
: MMLocalClass)
1758 dctx
.add
("<article id=\"{html_anchor}\
">\n")
1759 dctx
.add
("<h3 class=\"signature\
">{name}: {bound.html_link(dctx)}</h3>\n")
1760 dctx
.add
("<div class=\"info\
">")
1761 dctx
.add
("formal generic type")
1763 dctx
.add
("</article>")
1767 redef class MMNullableType
1768 redef fun html_link
(dctx
) do return "nullable " + as_notnull
.html_link
(dctx
)
1771 redef class MMVirtualType
1772 redef fun html_link
(dctx
) do return property
.html_link
(dctx
)
1775 var c
= new DocContext