1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 # Nitdoc page generation
20 # The NitdocContext contains all the knowledge used for doc generation
22 private var opt_dir
= new OptionString("output directory", "-d", "--dir")
23 private var opt_source
= new OptionString("link for source (%f for filename, %l for first line, %L for last line)", "--source")
24 private var opt_sharedir
= new OptionString("directory containing nitdoc assets", "--sharedir")
25 private var opt_shareurl
= new OptionString("use shareurl instead of copy shared files", "--shareurl")
26 private var opt_nodot
= new OptionBool("do not generate graphes with graphviz", "--no-dot")
27 private var opt_private
= new OptionBool("also generate private API", "--private")
29 private var opt_custom_title
= new OptionString("custom title for homepage", "--custom-title")
30 private var opt_custom_brand
= new OptionString("custom link to external site", "--custom-brand")
31 private var opt_custom_intro
= new OptionString("custom intro text for homepage", "--custom-overview-text")
32 private var opt_custom_footer
= new OptionString("custom footer text", "--custom-footer-text")
34 private var opt_github_upstream
= new OptionString("Git branch where edited commits will be pulled into (ex: user:repo:branch)", "--github-upstream")
35 private var opt_github_base_sha1
= new OptionString("Git sha1 of base commit used to create pull request", "--github-base-sha1")
36 private var opt_github_gitdir
= new OptionString("Git working directory used to resolve path name (ex: /home/me/myproject/)", "--github-gitdir")
38 private var opt_piwik_tracker
= new OptionString("Piwik tracker URL (ex: nitlanguage.org/piwik/)", "--piwik-tracker")
39 private var opt_piwik_site_id
= new OptionString("Piwik site ID", "--piwik-site-id")
41 private var toolcontext
= new ToolContext
42 private var mbuilder
: ModelBuilder
43 private var mainmodule
: MModule
44 private var output_dir
: String
45 private var min_visibility
: MVisibility
48 var opts
= toolcontext
.option_context
49 opts
.add_option
(opt_dir
, opt_source
, opt_sharedir
, opt_shareurl
, opt_nodot
, opt_private
)
50 opts
.add_option
(opt_custom_title
, opt_custom_footer
, opt_custom_intro
, opt_custom_brand
)
51 opts
.add_option
(opt_github_upstream
, opt_github_base_sha1
, opt_github_gitdir
)
52 opts
.add_option
(opt_piwik_tracker
, opt_piwik_site_id
)
54 var tpl
= new Template
55 tpl
.add
"Usage: nitdoc [OPTION]... <file.nit>...\n"
56 tpl
.add
"Generates HTML pages of API documentation from Nit source files."
57 toolcontext
.tooldescription
= tpl
.write_to_string
58 toolcontext
.process_options
(args
)
61 self.parse
(toolcontext
.option_context
.rest
)
64 private fun process_options
do
65 var output_dir
= opt_dir
.value
66 if output_dir
== null then
69 self.output_dir
= output_dir
70 if opt_private
.value
then
71 min_visibility
= none_visibility
73 min_visibility
= protected_visibility
75 var gh_upstream
= opt_github_upstream
.value
76 var gh_base_sha
= opt_github_base_sha1
.value
77 var gh_gitdir
= opt_github_gitdir
.value
78 if not gh_upstream
== null or not gh_base_sha
== null or not gh_gitdir
== null then
79 if gh_upstream
== null or gh_base_sha
== null or gh_gitdir
== null then
80 print
"Error: Options {opt_github_upstream.names.first}, {opt_github_base_sha1.names.first} and {opt_github_gitdir.names.first} are required to enable the GitHub plugin"
86 private fun parse
(arguments
: Array[String]) do
88 mbuilder
= new ModelBuilder(model
, toolcontext
)
89 var mmodules
= mbuilder
.parse
(arguments
)
90 if mmodules
.is_empty
then return
92 if mmodules
.length
== 1 then
93 mainmodule
= mmodules
.first
95 mainmodule
= new MModule(model
, null, "<main>", new Location(null, 0, 0, 0, 0))
96 mainmodule
.is_fictive
= true
97 mainmodule
.set_imported_mmodules
(mmodules
)
101 fun generate_nitdoc
do
112 private fun init_output_dir
do
113 # create destination dir if it's necessary
114 if not output_dir
.file_exists
then output_dir
.mkdir
116 var sharedir
= opt_sharedir
.value
117 if sharedir
== null then
118 var dir
= toolcontext
.nit_dir
120 print
"Error: Cannot locate nitdoc share files. Uses --sharedir or envvar NIT_DIR"
123 sharedir
= "{dir}/share/nitdoc"
124 if not sharedir
.file_exists
then
125 print
"Error: Cannot locate nitdoc share files. Uses --sharedir or envvar NIT_DIR"
130 if opt_shareurl
.value
== null then
131 sys
.system
("cp -r {sharedir.to_s}/* {output_dir.to_s}/")
133 sys
.system
("cp -r {sharedir.to_s}/resources/ {output_dir.to_s}/resources/")
138 private fun overview
do
139 var overviewpage
= new NitdocOverview(self)
140 overviewpage
.render
.write_to_file
("{output_dir.to_s}/index.html")
143 private fun search
do
144 var searchpage
= new NitdocSearch(self)
145 searchpage
.render
.write_to_file
("{output_dir.to_s}/search.html")
148 private fun groups
do
149 for mproject
in mbuilder
.model
.mprojects
do
150 for mgroup
in mproject
.mgroups
.to_a
do
151 var page
= new NitdocGroup(mgroup
, self)
152 page
.render
.write_to_file
("{output_dir.to_s}/{mgroup.nitdoc_url}")
157 private fun modules
do
158 for mmodule
in mbuilder
.model
.mmodules
do
159 if mmodule
.name
== "<main>" then continue
160 var modulepage
= new NitdocModule(mmodule
, self)
161 modulepage
.render
.write_to_file
("{output_dir.to_s}/{mmodule.nitdoc_url}")
165 private fun classes
do
166 for mclass
in mbuilder
.model
.mclasses
do
167 var classpage
= new NitdocClass(mclass
, self)
168 classpage
.render
.write_to_file
("{output_dir.to_s}/{mclass.nitdoc_url}")
172 private fun properties
do
173 for mproperty
in mbuilder
.model
.mproperties
do
174 var page
= new NitdocProperty(mproperty
, self)
175 page
.render
.write_to_file
("{output_dir.to_s}/{mproperty.nitdoc_url}")
179 private fun quicksearch_list
do
180 var quicksearch
= new QuickSearch(self)
181 quicksearch
.render
.write_to_file
("{output_dir.to_s}/quicksearch-list.js")
185 # Nitdoc QuickSearch list generator
187 # Create a JSON object containing links to:
191 # All entities are grouped by name to make the research easier.
194 private var mmodules
= new HashSet[MModule]
195 private var mclasses
= new HashSet[MClass]
196 private var mpropdefs
= new HashMap[String, Set[MPropDef]]
198 init(ctx
: NitdocContext) do
199 for mmodule
in ctx
.mbuilder
.model
.mmodules
do
200 if mmodule
.name
== "<main>" then continue
203 for mclass
in ctx
.mbuilder
.model
.mclasses
do
204 if mclass
.visibility
< ctx
.min_visibility
then continue
207 for mproperty
in ctx
.mbuilder
.model
.mproperties
do
208 if mproperty
.visibility
< ctx
.min_visibility
then continue
209 if mproperty
isa MAttribute then continue
210 if not mpropdefs
.has_key
(mproperty
.name
) then
211 mpropdefs
[mproperty
.name
] = new HashSet[MPropDef]
213 mpropdefs
[mproperty
.name
].add_all
(mproperty
.mpropdefs
)
217 fun render
: Template do
218 var tpl
= new Template
219 tpl
.add
"var nitdocQuickSearchRawList=\{ "
220 for mmodule
in mmodules
do
221 tpl
.add
"\"{mmodule.name}\
":["
222 tpl
.add
"\{txt:\"{mmodule.full_name}\",url
:\
"{mmodule.nitdoc_url}\"\
},"
225 for mclass in mclasses do
226 var full_name = mclass.intro.mmodule.full_name
227 tpl.add "\
"{mclass.name}\":["
228 tpl.add "\
{txt:\"{full_name}\
",url:\"{mclass.nitdoc_url}\
"\},"
231 for mproperty
, mprops
in mpropdefs
do
232 tpl
.add
"\"{mproperty}\
":["
233 for mpropdef
in mprops
do
234 var full_name
= mpropdef
.mclassdef
.mclass
.full_name
235 tpl
.add
"\{txt:\"{full_name}\",url
:\
"{mpropdef.nitdoc_url}\"\
},"
245 # Define page structure and properties
246 abstract class NitdocPage
248 private var ctx: NitdocContext
249 private var model: Model
250 private var name_sorter = new MEntityNameSorter
252 init(ctx: NitdocContext) do
254 self.model = ctx.mbuilder.model
257 # Render the page as a html template
258 fun render: Template do
260 if ctx.opt_shareurl.value != null then
261 shareurl = ctx.opt_shareurl.value.as(not null)
266 tpl.title = tpl_title
267 tpl.shareurl = shareurl
268 tpl.topmenu = tpl_topmenu
270 tpl.footer = ctx.opt_custom_footer.value
271 tpl.body_attrs.add(new TagAttribute("data-bootstrap-share
", shareurl))
272 tpl.sidebar = tpl_sidebar
275 var tracker_url = ctx.opt_piwik_tracker.value
276 var site_id = ctx.opt_piwik_site_id.value
277 if tracker_url != null and site_id != null then
278 tpl.scripts.add new TplPiwikScript(tracker_url, site_id)
283 # Build page template
284 fun tpl_page: TplPage is abstract
286 # Build page sidebar if any
287 fun tpl_sidebar: nullable TplSidebar do return null
289 # Build page title string
290 fun tpl_title: String do
291 if ctx.opt_custom_title.value != null then
292 return ctx.opt_custom_title.value.to_s
297 # Build top menu template
298 fun tpl_topmenu: TplTopMenu do
299 var topmenu = new TplTopMenu
300 var brand = ctx.opt_custom_brand.value
301 if brand != null then
302 var tpl = new Template
303 tpl.add "<span
class='navbar-brand'>"
311 # Build page content template
312 fun tpl_content is abstract
314 # Clickable graphviz image using dot format
315 # return null if no graph for this page
316 fun tpl_graph(dot: FlatBuffer, name: String, title: nullable String): nullable TplArticle do
317 if ctx.opt_nodot.value then return null
318 var output_dir = ctx.output_dir
319 var file = new OFStream.open("{output_dir}/{name}.dot
")
322 sys.system("\
{ test -f {output_dir}/{name}.png
&& test
-f
{output_dir}/{name}.s
.dot
&& diff
{output_dir}/{name}.dot
{output_dir}/{name}.s
.dot
>/dev
/null 2>&1 ; \
} || \
{ cp {output_dir}/{name}.dot
{output_dir}/{name}.s
.dot
&& dot
-Tpng -o
{output_dir}/{name}.png
-Tcmapx -o
{output_dir}/{name}.map
{output_dir}/{name}.s
.dot
; \
}")
323 var fmap = new IFStream.open("{output_dir}/{name}.map
")
324 var map = fmap.read_all
327 var article = new TplArticle("graph
")
329 if title != null then
330 article.title = title
331 alt = "alt
='{title}'"
333 article.css_classes.add "text-center
"
334 var content = new Template
335 content.add "<img src
='{name}.png' usemap
='#{name}' style
='margin:auto' {alt}/>"
337 article.content = content
341 # A (source) link template for a given location
342 fun tpl_showsource(location: nullable Location): nullable String
344 if location == null then return null
345 var source = ctx.opt_source.value
346 if source == null then return "{location.file.filename.simplify_path}"
347 # THIS IS JUST UGLY ! (but there is no replace yet)
348 var x = source.split_with("%f
")
349 source = x.join(location.file.filename.simplify_path)
350 x = source.split_with("%l
")
351 source = x.join(location.line_start.to_s)
352 x = source.split_with("%L
")
353 source = x.join(location.line_end.to_s)
354 source = source.simplify_path
355 return "<a target
='_blank' title
='Show source' href
=\
"{source.to_s}\">View Source</a
>"
358 # MProject description template
359 fun tpl_mproject_article(mproject: MProject): TplArticle do
360 var article = mproject.tpl_article
361 article.subtitle = mproject.tpl_declaration
362 article.content = mproject.tpl_definition
363 if mproject.mdoc != null then
364 article.content = mproject.mdoc.tpl_short_comment
369 # MGroup description template
370 fun tpl_mgroup_article(mgroup: MGroup): TplArticle do
371 var article = mgroup.tpl_article
372 article.subtitle = mgroup.tpl_declaration
373 article.content = mgroup.tpl_definition
377 # MModule description template
378 fun tpl_mmodule_article(mmodule: MModule): TplArticle do
379 var article = mmodule.tpl_article
380 article.subtitle = mmodule.tpl_declaration
381 article.content = mmodule.tpl_definition
383 var intros = mmodule.intro_mclassdefs(ctx.min_visibility).to_a
384 ctx.mainmodule.linearize_mclassdefs(intros)
385 var intros_art = new TplArticle.with_title("{mmodule.nitdoc_id}_intros
", "Introduces")
386 var intros_lst = new TplList.with_classes(["list-unstyled
", "list-labeled
"])
387 for mclassdef in intros do
388 intros_lst.add_li new TplListItem.with_content(mclassdef.tpl_list_item)
390 if not intros_lst.is_empty then
391 intros_art.content = intros_lst
392 article.add_child intros_art
394 var redefs = mmodule.redef_mclassdefs(ctx.min_visibility).to_a
395 ctx.mainmodule.linearize_mclassdefs(redefs)
396 var redefs_art = new TplArticle.with_title("{mmodule.nitdoc_id}_redefs
", "Redefines")
397 var redefs_lst = new TplList.with_classes(["list-unstyled
", "list-labeled
"])
398 for mclassdef in redefs do
399 redefs_lst.add_li new TplListItem.with_content(mclassdef.tpl_list_item)
401 if not redefs_lst.is_empty then
402 redefs_art.content = redefs_lst
403 article.add_child redefs_art
408 # MClassDef description template
409 fun tpl_mclass_article(mclass: MClass, mclassdefs: Array[MClassDef]): TplArticle do
410 var article = mclass.tpl_article
411 if not mclassdefs.has(mclass.intro) then
413 var intro_article = mclass.intro.tpl_short_article
414 intro_article.source_link = tpl_showsource(mclass.intro.location)
415 article.add_child intro_article
417 ctx.mainmodule.linearize_mclassdefs(mclassdefs)
418 for mclassdef in mclassdefs do
419 # add mclassdef full description
420 var redef_article = mclassdef.tpl_article
421 redef_article.source_link = tpl_showsource(mclassdef.location)
422 article.add_child redef_article
424 var intros = new TplArticle.with_title("{mclassdef.nitdoc_id}_intros
", "Introduces")
425 var intros_lst = new TplList.with_classes(["list-unstyled
", "list-labeled
"])
426 for mpropdef in mclassdef.collect_intro_mpropdefs(ctx.min_visibility) do
427 intros_lst.add_li new TplListItem.with_content(mpropdef.tpl_list_item)
429 if not intros_lst.is_empty then
430 intros.content = intros_lst
431 redef_article.add_child intros
433 var redefs = new TplArticle.with_title("{mclassdef.nitdoc_id}_redefs
", "Redefines")
434 var redefs_lst = new TplList.with_classes(["list-unstyled
", "list-labeled
"])
435 for mpropdef in mclassdef.collect_redef_mpropdefs(ctx.min_visibility) do
436 redefs_lst.add_li new TplListItem.with_content(mpropdef.tpl_list_item)
438 if not redefs_lst.is_empty then
439 redefs.content = redefs_lst
440 redef_article.add_child redefs
446 # MClassDef description template
447 fun tpl_mclassdef_article(mclassdef: MClassDef): TplArticle do
448 var article = mclassdef.tpl_article
449 if mclassdef.is_intro then article.content = null
450 article.source_link = tpl_showsource(mclassdef.location)
454 # MProp description template
455 fun tpl_mprop_article(mproperty: MProperty, mpropdefs: Array[MPropDef]): TplArticle do
456 var article = mproperty.tpl_article
457 if not mpropdefs.has(mproperty.intro) then
459 var intro_article = mproperty.intro.tpl_short_article
460 intro_article.source_link = tpl_showsource(mproperty.intro.location)
461 article.add_child intro_article
463 ctx.mainmodule.linearize_mpropdefs(mpropdefs)
464 for mpropdef in mpropdefs do
465 # add mpropdef description
466 var redef_article = mpropdef.tpl_article
467 redef_article.source_link = tpl_showsource(mpropdef.location)
468 article.add_child redef_article
473 # MProperty description template
474 fun tpl_mpropdef_article(mpropdef: MPropDef): TplArticle do
475 var article = mpropdef.tpl_article
476 if mpropdef.is_intro then article.content = null
477 article.source_link = tpl_showsource(mpropdef.location)
483 # Display a list of modules contained in program
487 init(ctx: NitdocContext) do super(ctx)
489 private var page = new TplPage
490 redef fun tpl_page do return page
492 private var sidebar = new TplSidebar
493 redef fun tpl_sidebar do return sidebar
495 redef fun tpl_title do
496 if ctx.opt_custom_title.value != null then
497 return ctx.opt_custom_title.value.to_s
503 redef fun tpl_topmenu do
505 topmenu.add_item(new TplLink("#", "Overview"), true)
506 topmenu
.add_item
(new TplLink("search.html", "Index"), false)
511 private fun tpl_intro
: TplSection do
512 var section
= new TplSection.with_title
("overview", tpl_title
)
513 var article
= new TplArticle("intro")
514 if ctx
.opt_custom_intro
.value
!= null then
515 article
.content
= ctx
.opt_custom_intro
.value
.to_s
517 section
.add_child article
522 private fun tpl_projects
(section
: TplSection) do
524 var mprojects
= model
.mprojects
.to_a
525 var sorter
= new MConcernRankSorter
526 sorter
.sort mprojects
527 var ssection
= new TplSection.with_title
("projects", "Projects")
528 for mproject
in mprojects
do
529 ssection
.add_child tpl_mproject_article
(mproject
)
531 section
.add_child ssection
534 redef fun tpl_content
do
537 tpl_page
.add_section top
542 # Display a list of modules, classes and properties
546 init(ctx
: NitdocContext) do super(ctx
)
548 private var page
= new TplPage
549 redef fun tpl_page
do return page
551 redef fun tpl_title
do return "Index"
553 redef fun tpl_topmenu
do
555 topmenu
.add_item
(new TplLink("index.html", "Overview"), false)
556 topmenu
.add_item
(new TplLink("#", "Index"), true)
560 redef fun tpl_content
do
561 var tpl
= new TplSearchPage("search_all")
562 var section
= new TplSection("search")
566 for mmodule
in modules_list
do
567 tpl
.modules
.add mmodule
.tpl_link
570 for mclass
in classes_list
do
571 tpl
.classes
.add mclass
.tpl_link
574 for mproperty
in mprops_list
do
576 m
.add mproperty
.intro
.tpl_link
578 m
.add mproperty
.intro
.mclassdef
.mclass
.tpl_link
582 section
.add_child tpl
583 tpl_page
.add_section section
586 # Extract mmodule list to display (sorted by name)
587 private fun modules_list
: Array[MModule] do
588 var sorted
= new Array[MModule]
589 for mmodule
in ctx
.mbuilder
.model
.mmodule_importation_hierarchy
do
590 if mmodule
.name
== "<main>" then continue
593 name_sorter
.sort
(sorted
)
597 # Extract mclass list to display (sorted by name)
598 private fun classes_list
: Array[MClass] do
599 var sorted
= new Array[MClass]
600 for mclass
in ctx
.mbuilder
.model
.mclasses
do
601 if mclass
.visibility
< ctx
.min_visibility
then continue
604 name_sorter
.sort
(sorted
)
608 # Extract mproperty list to display (sorted by name)
609 private fun mprops_list
: Array[MProperty] do
610 var sorted
= new Array[MProperty]
611 for mproperty
in ctx
.mbuilder
.model
.mproperties
do
612 if mproperty
.visibility
< ctx
.min_visibility
then continue
613 if mproperty
isa MAttribute then continue
616 name_sorter
.sort
(sorted
)
622 # Display a flattened view of the group
626 private var mgroup
: MGroup
628 private var concerns
: ConcernsTree
629 private var intros
: Set[MClass]
630 private var redefs
: Set[MClass]
632 init(mgroup
: MGroup, ctx
: NitdocContext) do
636 self.concerns
= model
.concerns_tree
(mgroup
.collect_mmodules
)
637 self.concerns
.sort_with
(new MConcernRankSorter)
638 self.intros
= mgroup
.in_nesting_intro_mclasses
(ctx
.min_visibility
)
639 var redefs
= new HashSet[MClass]
640 for rdef
in mgroup
.in_nesting_redef_mclasses
(ctx
.min_visibility
) do
641 if intros
.has
(rdef
) then continue
647 private var page
= new TplPage
648 redef fun tpl_page
do return page
650 private var sidebar
= new TplSidebar
651 redef fun tpl_sidebar
do return sidebar
653 redef fun tpl_title
do return "{mgroup.nitdoc_name}"
655 redef fun tpl_topmenu
do
657 var mproject
= mgroup
.mproject
658 topmenu
.add_item
(new TplLink("index.html", "Overview"), false)
659 if mgroup
.is_root
then
660 topmenu
.add_item
(new TplLink("#", "{mproject.nitdoc_name}"), true)
662 topmenu
.add_item
(new TplLink(mproject
.nitdoc_url
, "{mproject.nitdoc_name}"), false)
663 topmenu
.add_item
(new TplLink("#", "{mgroup.nitdoc_name}"), true)
665 topmenu
.add_item
(new TplLink("search.html", "Index"), false)
669 # Class list to display in sidebar
670 fun tpl_sidebar_mclasses
do
671 var mclasses
= new HashSet[MClass]
672 mclasses
.add_all intros
673 mclasses
.add_all redefs
674 if mclasses
.is_empty
then return
675 var list
= new TplList.with_classes
(["list-unstyled", "list-labeled"])
677 var sorted
= mclasses
.to_a
678 name_sorter
.sort
(sorted
)
679 for mclass
in sorted
do
680 list
.add_li tpl_sidebar_item
(mclass
)
682 tpl_sidebar
.boxes
.add
new TplSideBox.with_content
("All classes", list
)
685 private fun tpl_sidebar_item
(def
: MClass): Template do
686 var classes
= def
.intro
.tpl_css_classes
.to_a
687 if intros
.has
(def
) then
692 var lnk
= new Template
693 lnk
.add
new TplLabel.with_classes
(classes
)
699 private fun tpl_intro
: TplSection do
700 var section
= new TplSection.with_title
("top", tpl_title
)
701 var article
= new TplArticle("intro")
703 if mgroup
.is_root
then
704 section
.subtitle
= mgroup
.mproject
.tpl_declaration
705 article
.content
= mgroup
.mproject
.tpl_definition
707 section
.subtitle
= mgroup
.tpl_declaration
708 article
.content
= mgroup
.tpl_definition
710 section
.add_child article
714 private fun tpl_concerns
(section
: TplSection) do
715 if concerns
.is_empty
then return
716 section
.add_child
new TplArticle.with_content
("concerns", "Concerns", concerns
.to_tpl
)
719 private fun tpl_groups
(parent
: TplSection) do
720 var lst
= concerns
.to_a
722 for mentity
in lst
do
723 if mentity
isa MProject then
724 section
.add_child
new TplSection(mentity
.nitdoc_id
)
725 else if mentity
isa MGroup then
726 section
.add_child
new TplSection(mentity
.nitdoc_id
)
727 else if mentity
isa MModule then
728 section
.add_child tpl_mmodule_article
(mentity
)
733 redef fun tpl_content
do
738 tpl_page
.add_section top
741 private fun sort_by_mclass
(mclassdefs
: Collection[MClassDef]): Map[MClass, Set[MClassDef]] do
742 var map
= new HashMap[MClass, Set[MClassDef]]
743 for mclassdef
in mclassdefs
do
744 var mclass
= mclassdef
.mclass
745 if not map
.has_key
(mclass
) then map
[mclass
] = new HashSet[MClassDef]
746 map
[mclass
].add mclassdef
753 # Display the list of introduced and redefined classes in module
757 private var mmodule
: MModule
758 private var concerns
: ConcernsTree
759 private var mclasses2mdefs
: Map[MClass, Set[MClassDef]]
760 private var mmodules2mclasses
: Map[MModule, Set[MClass]]
762 init(mmodule
: MModule, ctx
: NitdocContext) do
763 self.mmodule
= mmodule
766 var mclassdefs
= new HashSet[MClassDef]
767 mclassdefs
.add_all mmodule
.intro_mclassdefs
(ctx
.min_visibility
)
768 mclassdefs
.add_all mmodule
.redef_mclassdefs
(ctx
.min_visibility
)
769 self.mclasses2mdefs
= sort_by_mclass
(mclassdefs
)
770 self.mmodules2mclasses
= group_by_mmodule
(mclasses2mdefs
.keys
)
771 self.concerns
= model
.concerns_tree
(mmodules2mclasses
.keys
)
773 mmodule
.mgroup
.mproject
.booster_rank
= -1000
774 mmodule
.mgroup
.booster_rank
= -1000
775 mmodule
.booster_rank
= -1000
776 self.concerns
.sort_with
(new MConcernRankSorter)
777 mmodule
.mgroup
.mproject
.booster_rank
= 0
778 mmodule
.mgroup
.booster_rank
= 0
779 mmodule
.booster_rank
= 0
782 private var page
= new TplPage
783 redef fun tpl_page
do return page
785 private var sidebar
= new TplSidebar
786 redef fun tpl_sidebar
do return sidebar
788 redef fun tpl_title
do return "{mmodule.nitdoc_name}"
790 redef fun tpl_topmenu
do
792 var mproject
= mmodule
.mgroup
.mproject
793 topmenu
.add_item
(new TplLink("index.html", "Overview"), false)
794 topmenu
.add_item
(new TplLink("{mproject.nitdoc_url}", "{mproject.nitdoc_name}"), false)
795 topmenu
.add_item
(new TplLink("#", "{mmodule.nitdoc_name}"), true)
796 topmenu
.add_item
(new TplLink("search.html", "Index"), false)
800 # Class list to display in sidebar
801 fun tpl_sidebar_mclasses
do
802 var mclasses
= new HashSet[MClass]
803 mclasses
.add_all mmodule
.filter_intro_mclasses
(ctx
.min_visibility
)
804 mclasses
.add_all mmodule
.filter_redef_mclasses
(ctx
.min_visibility
)
805 if mclasses
.is_empty
then return
806 var list
= new TplList.with_classes
(["list-unstyled", "list-labeled"])
808 var sorted
= mclasses
.to_a
809 name_sorter
.sort
(sorted
)
810 for mclass
in sorted
do
811 list
.add_li tpl_sidebar_item
(mclass
)
813 tpl_sidebar
.boxes
.add
new TplSideBox.with_content
("All classes", list
)
816 private fun tpl_sidebar_item
(def
: MClass): Template do
817 var classes
= def
.intro
.tpl_css_classes
.to_a
818 if def
.intro_mmodule
== mmodule
then
823 var lnk
= new Template
824 lnk
.add
new TplLabel.with_classes
(classes
)
830 private fun tpl_intro
: TplSection do
831 var section
= new TplSection.with_title
("top", tpl_title
)
832 section
.subtitle
= mmodule
.tpl_declaration
834 var article
= new TplArticle("intro")
835 var def
= mmodule
.tpl_definition
836 var location
= mmodule
.location
837 article
.source_link
= tpl_showsource
(location
)
838 article
.content
= def
839 section
.add_child article
843 # inheritance section
844 private fun tpl_inheritance
(parent
: TplSection) do
845 # Extract relevent modules
846 var imports
= mmodule
.in_importation
.greaters
847 if imports
.length
> 10 then imports
= mmodule
.in_importation
.direct_greaters
848 var clients
= mmodule
.in_importation
.smallers
849 if clients
.length
> 10 then clients
= mmodule
.in_importation
.direct_smallers
852 var section
= new TplSection.with_title
("dependencies", "Dependencies")
855 var mmodules
= new HashSet[MModule]
856 mmodules
.add_all mmodule
.in_nesting
.direct_greaters
857 mmodules
.add_all imports
858 if clients
.length
< 10 then mmodules
.add_all clients
860 var graph
= tpl_dot
(mmodules
)
861 if graph
!= null then section
.add_child graph
864 var lst
= new Array[MModule]
865 for dep
in imports
do
866 if dep
.is_fictive
then continue
867 if dep
== mmodule
then continue
870 if not lst
.is_empty
then
872 section
.add_child tpl_list
("imports", "Imports", lst
)
876 lst
= new Array[MModule]
877 for dep
in clients
do
878 if dep
.is_fictive
then continue
879 if dep
== mmodule
then continue
882 if not lst
.is_empty
then
884 section
.add_child tpl_list
("clients", "Clients", lst
)
887 parent
.add_child section
890 private fun tpl_list
(id
: String, title
: String, mmodules
: Array[MModule]): TplArticle do
891 var article
= new TplArticle.with_title
(id
, title
)
892 var list
= new TplList.with_classes
(["list-unstyled", "list-definition"])
893 for mmodule
in mmodules
do list
.elts
.add mmodule
.tpl_list_item
894 article
.content
= list
898 private fun tpl_concerns
(parent
: TplSection) do
899 if concerns
.is_empty
then return
900 parent
.add_child
new TplArticle.with_content
("concerns", "Concerns", concerns
.to_tpl
)
903 private fun tpl_mclasses
(parent
: TplSection) do
904 for mentity
in concerns
do
905 if mentity
isa MProject then
906 parent
.add_child
new TplSection(mentity
.nitdoc_id
)
907 else if mentity
isa MGroup then
908 parent
.add_child
new TplSection(mentity
.nitdoc_id
)
909 else if mentity
isa MModule then
910 var section
= new TplSection(mentity
.nitdoc_id
)
911 var title
= new Template
912 if mentity
== mmodule
then
914 section
.summary_title
= "in {mentity.nitdoc_name}"
917 section
.summary_title
= "from {mentity.nitdoc_name}"
919 title
.add mentity
.tpl_namespace
920 section
.title
= title
922 var mclasses
= mmodules2mclasses
[mentity
].to_a
923 name_sorter
.sort
(mclasses
)
924 for mclass
in mclasses
do
925 section
.add_child tpl_mclass_article
(mclass
, mclasses2mdefs
[mclass
].to_a
)
927 parent
.add_child section
932 private fun group_by_mmodule
(mclasses
: Collection[MClass]): Map[MModule, Set[MClass]] do
933 var res
= new HashMap[MModule, Set[MClass]]
934 for mclass
in mclasses
do
935 var mmodule
= mclass
.intro_mmodule
936 if not res
.has_key
(mmodule
) then
937 res
[mmodule
] = new HashSet[MClass]
939 res
[mmodule
].add
(mclass
)
944 redef fun tpl_content
do
950 tpl_page
.add_section top
953 # Genrate dot hierarchy for class inheritance
954 fun tpl_dot
(mmodules
: Collection[MModule]): nullable TplArticle do
955 var poset
= new POSet[MModule]
956 for mmodule
in mmodules
do
957 if mmodule
.is_fictive
then continue
958 poset
.add_node mmodule
959 for omodule
in mmodules
do
960 if mmodule
.is_fictive
then continue
961 poset
.add_node mmodule
962 if mmodule
.in_importation
< omodule
then
963 poset
.add_edge
(mmodule
, omodule
)
968 var op
= new FlatBuffer
969 var name
= "dep_{mmodule.name}"
970 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")
971 for mmodule
in poset
do
972 if mmodule
== self.mmodule
then
973 op
.append
("\"{mmodule.name}\
"[shape=box,margin=0.03];\n")
975 op
.append
("\"{mmodule.name}\
"[URL=\"{mmodule.nitdoc_url}\
"];\n")
977 for omodule
in poset
[mmodule
].direct_greaters
do
978 op
.append
("\"{mmodule.name}\
"->\"{omodule.name}\
";\n")
982 return tpl_graph
(op
, name
, null)
985 private fun sort_by_mclass
(mclassdefs
: Collection[MClassDef]): Map[MClass, Set[MClassDef]] do
986 var map
= new HashMap[MClass, Set[MClassDef]]
987 for mclassdef
in mclassdefs
do
988 var mclass
= mclassdef
.mclass
989 if not map
.has_key
(mclass
) then map
[mclass
] = new HashSet[MClassDef]
990 map
[mclass
].add mclassdef
997 # Display a list properties defined or redefined for this class
1001 private var mclass
: MClass
1002 private var concerns
: ConcernsTree
1003 private var mprops2mdefs
: Map[MProperty, Set[MPropDef]]
1004 private var mmodules2mprops
: Map[MModule, Set[MProperty]]
1006 init(mclass
: MClass, ctx
: NitdocContext) do
1007 self.mclass
= mclass
1009 var mpropdefs
= new HashSet[MPropDef]
1010 mpropdefs
.add_all mclass
.intro_mpropdefs
(ctx
.min_visibility
)
1011 mpropdefs
.add_all mclass
.redef_mpropdefs
(ctx
.min_visibility
)
1012 self.mprops2mdefs
= sort_by_mproperty
(mpropdefs
)
1013 self.mmodules2mprops
= sort_by_mmodule
(mprops2mdefs
.keys
)
1014 self.concerns
= model
.concerns_tree
(mmodules2mprops
.keys
)
1015 self.concerns
.sort_with
(new MConcernRankSorter)
1018 private var page
= new TplPage
1019 redef fun tpl_page
do return page
1021 private var sidebar
= new TplSidebar
1022 redef fun tpl_sidebar
do return sidebar
1024 redef fun tpl_title
do return "{mclass.nitdoc_name}{mclass.tpl_signature.write_to_string}"
1026 redef fun tpl_topmenu
do
1028 var mproject
= mclass
.intro_mmodule
.mgroup
.mproject
1029 topmenu
.add_item
(new TplLink("index.html", "Overview"), false)
1030 topmenu
.add_item
(new TplLink("{mproject.nitdoc_url}", "{mproject.nitdoc_name}"), false)
1031 topmenu
.add_item
(new TplLink("#", "{mclass.nitdoc_name}"), true)
1032 topmenu
.add_item
(new TplLink("search.html", "Index"), false)
1036 # Property list to display in sidebar
1037 fun tpl_sidebar_properties
do
1038 var kind_map
= sort_by_kind
(mclass_inherited_mprops
)
1039 var summary
= new TplList.with_classes
(["list-unstyled"])
1041 tpl_sidebar_list
("Virtual types", kind_map
["type"].to_a
, summary
)
1042 tpl_sidebar_list
("Constructors", kind_map
["init"].to_a
, summary
)
1043 tpl_sidebar_list
("Methods", kind_map
["fun"].to_a
, summary
)
1044 tpl_sidebar
.boxes
.add
new TplSideBox.with_content
("All properties", summary
)
1047 private fun tpl_sidebar_list
(name
: String, mprops
: Array[MProperty], summary
: TplList) do
1048 if mprops
.is_empty
then return
1049 name_sorter
.sort
(mprops
)
1050 var entry
= new TplListItem.with_content
(name
)
1051 var list
= new TplList.with_classes
(["list-unstyled", "list-labeled"])
1052 for mprop
in mprops
do
1053 list
.add_li tpl_sidebar_item
(mprop
)
1056 summary
.elts
.add entry
1059 private fun tpl_sidebar_item
(mprop
: MProperty): Template do
1060 var classes
= mprop
.intro
.tpl_css_classes
.to_a
1061 if not mprops2mdefs
.has_key
(mprop
) then
1062 classes
.add
"inherit"
1063 var lnk
= new Template
1064 lnk
.add
new TplLabel.with_classes
(classes
)
1065 lnk
.add mprop
.intro
.tpl_link
1068 var defs
= mprops2mdefs
[mprop
]
1069 if defs
.has
(mprop
.intro
) then
1074 var lnk
= new Template
1075 lnk
.add
new TplLabel.with_classes
(classes
)
1076 lnk
.add mprop
.intro
.tpl_anchor
1080 private fun tpl_intro
: TplSection do
1081 var section
= new TplSection.with_title
("top", tpl_title
)
1082 section
.subtitle
= mclass
.intro
.tpl_declaration
1083 var article
= new TplArticle("comment")
1084 if mclass
.mdoc
!= null then
1085 article
.content
= mclass
.mdoc
.tpl_comment
1087 section
.add_child article
1091 private fun tpl_concerns
(parent
: TplSection) do
1093 var section
= new TplSection.with_title
("intro", "Introduction")
1094 section
.summary_title
= "Introduction"
1095 section
.add_child tpl_mclassdef_article
(mclass
.intro
)
1096 parent
.add_child section
1098 if concerns
.is_empty
then return
1099 parent
.add_child
new TplArticle.with_content
("concerns", "Concerns", concerns
.to_tpl
)
1102 private fun tpl_inheritance
(parent
: TplSection) do
1104 var hparents
= new HashSet[MClass]
1105 for c
in mclass
.in_hierarchy
(ctx
.mainmodule
).direct_greaters
do
1106 if c
.visibility
< ctx
.min_visibility
then continue
1111 var hancestors
= new HashSet[MClass]
1112 for c
in mclass
.in_hierarchy
(ctx
.mainmodule
).greaters
do
1113 if c
== mclass
then continue
1114 if c
.visibility
< ctx
.min_visibility
then continue
1115 if hparents
.has
(c
) then continue
1120 var hchildren
= new HashSet[MClass]
1121 for c
in mclass
.in_hierarchy
(ctx
.mainmodule
).direct_smallers
do
1122 if c
.visibility
< ctx
.min_visibility
then continue
1127 var hdescendants
= new HashSet[MClass]
1128 for c
in mclass
.in_hierarchy
(ctx
.mainmodule
).smallers
do
1129 if c
== mclass
then continue
1130 if c
.visibility
< ctx
.min_visibility
then continue
1131 if hchildren
.has
(c
) then continue
1136 var section
= new TplSection.with_title
("inheritance", "Inheritance")
1139 var mclasses
= new HashSet[MClass]
1140 mclasses
.add_all hancestors
1141 mclasses
.add_all hparents
1142 if hchildren
.length
< 10 then mclasses
.add_all hchildren
1143 if hdescendants
.length
< 10 then mclasses
.add_all hdescendants
1145 var graph
= tpl_dot
(mclasses
)
1146 if graph
!= null then section
.add_child graph
1149 if not hparents
.is_empty
then
1150 var lst
= hparents
.to_a
1151 name_sorter
.sort lst
1152 section
.add_child tpl_list
("parents", "Parents", lst
)
1156 if not hancestors
.is_empty
then
1157 var lst
= hancestors
.to_a
1158 name_sorter
.sort lst
1159 section
.add_child tpl_list
("ancestors", "Ancestors", lst
)
1163 if not hchildren
.is_empty
and hchildren
.length
< 15 then
1164 var lst
= hchildren
.to_a
1165 name_sorter
.sort lst
1166 section
.add_child tpl_list
("children", "Children", lst
)
1170 if not hdescendants
.is_empty
and hchildren
.length
< 15 then
1171 var lst
= hdescendants
.to_a
1172 name_sorter
.sort lst
1173 section
.add_child tpl_list
("descendants", "Descendants", lst
)
1176 parent
.add_child section
1179 private fun tpl_list
(id
: String, title
: String, elts
: Array[MClass]): TplArticle do
1180 var article
= new TplArticle.with_title
(id
, title
)
1181 var list
= new TplList.with_classes
(["list-unstyled", "list-definition"])
1182 for elt
in elts
do list
.elts
.add elt
.tpl_list_item
1183 article
.content
= list
1187 private fun tpl_properties
(parent
: TplSection) do
1188 var lst
= concerns
.to_a
1189 for mentity
in lst
do
1190 if mentity
isa MProject then
1191 parent
.add_child
new TplSection(mentity
.nitdoc_id
)
1192 else if mentity
isa MGroup then
1193 parent
.add_child
new TplSection(mentity
.nitdoc_id
)
1194 else if mentity
isa MModule then
1195 var section
= new TplSection(mentity
.nitdoc_id
)
1196 var title
= new Template
1198 title
.add mentity
.tpl_namespace
1199 section
.title
= title
1200 section
.summary_title
= "in {mentity.nitdoc_name}"
1203 var mprops
= mmodules2mprops
[mentity
]
1204 var kind_map
= sort_by_kind
(mprops
)
1207 var elts
= kind_map
["type"].to_a
1208 name_sorter
.sort
(elts
)
1210 var defs
= mprops2mdefs
[elt
].to_a
1211 section
.add_child tpl_mprop_article
(elt
, defs
)
1215 elts
= kind_map
["init"].to_a
1216 name_sorter
.sort
(elts
)
1218 var defs
= mprops2mdefs
[elt
].to_a
1219 section
.add_child tpl_mprop_article
(elt
, defs
)
1223 elts
= kind_map
["fun"].to_a
1224 name_sorter
.sort
(elts
)
1226 var defs
= mprops2mdefs
[elt
].to_a
1227 section
.add_child tpl_mprop_article
(elt
, defs
)
1229 parent
.add_child section
1234 redef fun tpl_content
do
1235 tpl_sidebar_properties
1237 tpl_inheritance
(top
)
1240 tpl_page
.add_section top
1243 private fun sort_by_mproperty
(mpropdefs
: Collection[MPropDef]): Map[MProperty, Set[MPropDef]] do
1244 var map
= new HashMap[MProperty, Set[MPropDef]]
1245 for mpropdef
in mpropdefs
do
1246 var mproperty
= mpropdef
.mproperty
1247 if not map
.has_key
(mproperty
) then map
[mproperty
] = new HashSet[MPropDef]
1248 map
[mproperty
].add mpropdef
1253 private fun sort_by_mmodule
(mprops
: Collection[MProperty]): Map[MModule, Set[MProperty]] do
1254 var map
= new HashMap[MModule, Set[MProperty]]
1255 for mprop
in mprops
do
1256 var mpropdefs
= mprops2mdefs
[mprop
].to_a
1257 ctx
.mainmodule
.linearize_mpropdefs
(mpropdefs
)
1258 var mmodule
= mpropdefs
.first
.mclassdef
.mmodule
1259 if not map
.has_key
(mmodule
) then map
[mmodule
] = new HashSet[MProperty]
1260 map
[mmodule
].add mprop
1265 private fun sort_by_kind
(mprops
: Collection[MProperty]): Map[String, Set[MProperty]] do
1266 var map
= new HashMap[String, Set[MProperty]]
1267 map
["type"] = new HashSet[MProperty]
1268 map
["init"] = new HashSet[MProperty]
1269 map
["fun"] = new HashSet[MProperty]
1270 for mprop
in mprops
do
1271 if mprop
isa MVirtualTypeProp then
1272 map
["type"].add mprop
1273 else if mprop
isa MMethod then
1274 if mprop
.is_init
then
1275 map
["init"].add mprop
1277 map
["fun"].add mprop
1284 private fun mclass_inherited_mprops
: Set[MProperty] do
1285 var res
= new HashSet[MProperty]
1286 var local
= mclass
.local_mproperties
(ctx
.min_visibility
)
1287 for mprop
in mclass
.inherited_mproperties
(ctx
.mainmodule
, ctx
.min_visibility
) do
1288 if local
.has
(mprop
) then continue
1289 #if mprop isa MMethod and mprop.is_init then continue
1290 if mprop
.intro
.mclassdef
.mclass
.name
== "Object" and
1291 (mprop
.visibility
== protected_visibility
or
1292 mprop
.intro
.mclassdef
.mmodule
.name
!= "kernel") then continue
1299 private fun collect_mmodules
(mprops
: Collection[MProperty]): Set[MModule] do
1300 var res
= new HashSet[MModule]
1301 for mprop
in mprops
do
1302 if mprops2mdefs
.has_key
(mprop
) then
1303 for mpropdef
in mprops2mdefs
[mprop
] do res
.add mpropdef
.mclassdef
.mmodule
1309 private fun sort_by_public_owner
(mmodules
: Collection[MModule]): Map[MModule, Set[MModule]] do
1310 var map
= new HashMap[MModule, Set[MModule]]
1311 for mmodule
in mmodules
do
1313 if mmodule
.public_owner
!= null then owner
= mmodule
.public_owner
.as(not null)
1314 if not map
.has_key
(owner
) then map
[owner
] = new HashSet[MModule]
1315 map
[owner
].add mmodule
1320 # Generate dot hierarchy for classes
1321 fun tpl_dot
(mclasses
: Collection[MClass]): nullable TplArticle do
1322 var poset
= new POSet[MClass]
1324 for mclass
in mclasses
do
1325 poset
.add_node mclass
1326 for oclass
in mclasses
do
1327 poset
.add_node oclass
1328 if mclass
.in_hierarchy
(ctx
.mainmodule
) < oclass
then
1329 poset
.add_edge
(mclass
, oclass
)
1334 var op
= new FlatBuffer
1335 var name
= "dep_{mclass.name}"
1336 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")
1339 op
.append
("\"{c.name}\
"[shape=box,margin=0.03];\n")
1341 op
.append
("\"{c.name}\
"[URL=\"{c.nitdoc_url}\
"];\n")
1343 for c2
in poset
[c
].direct_greaters
do
1344 op
.append
("\"{c.name}\
"->\"{c2.name}\
";\n")
1348 return tpl_graph
(op
, name
, null)
1353 class NitdocProperty
1356 private var mproperty
: MProperty
1357 private var concerns
: ConcernsTree
1358 private var mmodules2mdefs
: Map[MModule, Set[MPropDef]]
1360 init(mproperty
: MProperty, ctx
: NitdocContext) do
1361 self.mproperty
= mproperty
1363 self.mmodules2mdefs
= sort_by_mmodule
(collect_mpropdefs
)
1364 self.concerns
= model
.concerns_tree
(mmodules2mdefs
.keys
)
1365 self.concerns
.sort_with
(new MConcernRankSorter)
1368 private fun collect_mpropdefs
: Set[MPropDef] do
1369 var res
= new HashSet[MPropDef]
1370 for mpropdef
in mproperty
.mpropdefs
do
1371 if not mpropdef
.is_intro
then res
.add mpropdef
1376 private var page
= new TplPage
1377 redef fun tpl_page
do return page
1379 private var sidebar
= new TplSidebar
1380 redef fun tpl_sidebar
do return sidebar
1382 redef fun tpl_title
do
1383 return "{mproperty.nitdoc_name}{mproperty.tpl_signature.write_to_string}"
1386 redef fun tpl_topmenu
do
1388 var mmodule
= mproperty
.intro_mclassdef
.mmodule
1389 var mproject
= mmodule
.mgroup
.mproject
1390 var mclass
= mproperty
.intro_mclassdef
.mclass
1391 topmenu
.add_item
(new TplLink("index.html", "Overview"), false)
1392 topmenu
.add_item
(new TplLink("{mproject.nitdoc_url}", "{mproject.nitdoc_name}"), false)
1393 topmenu
.add_item
(new TplLink("{mclass.nitdoc_url}", "{mclass.nitdoc_name}"), false)
1394 topmenu
.add_item
(new TplLink("#", "{mproperty.nitdoc_name}"), true)
1395 topmenu
.add_item
(new TplLink("search.html", "Index"), false)
1399 private fun tpl_intro
: TplSection do
1400 var section
= new TplSection.with_title
("top", tpl_title
)
1401 section
.subtitle
= mproperty
.tpl_declaration
1402 var article
= new TplArticle("comment")
1403 if mproperty
.intro
.mdoc
!= null then
1404 article
.content
= mproperty
.intro
.mdoc
.tpl_comment
1406 section
.add_child article
1410 private fun tpl_properties
(parent
: TplSection) do
1412 var section
= new TplSection.with_title
("intro", "Introduction")
1413 section
.summary_title
= "Introduction"
1414 section
.add_child tpl_mpropdef_article
(mproperty
.intro
)
1415 parent
.add_child section
1418 if concerns
.is_empty
then return
1419 parent
.add_child
new TplArticle.with_content
("Concerns", "Concerns", concerns
.to_tpl
)
1422 var lst
= concerns
.to_a
1423 for mentity
in lst
do
1424 if mentity
isa MProject then
1425 parent
.add_child
new TplSection(mentity
.nitdoc_id
)
1426 else if mentity
isa MGroup then
1427 parent
.add_child
new TplSection(mentity
.nitdoc_id
)
1428 else if mentity
isa MModule then
1429 var ssection
= new TplSection(mentity
.nitdoc_id
)
1430 var title
= new Template
1432 title
.add mentity
.tpl_namespace
1433 ssection
.title
= title
1434 ssection
.summary_title
= "in {mentity.nitdoc_name}"
1437 var mpropdefs
= mmodules2mdefs
[mentity
].to_a
1438 name_sorter
.sort
(mpropdefs
)
1439 for mpropdef
in mpropdefs
do
1440 ssection
.add_child tpl_mpropdef_article
(mpropdef
)
1442 parent
.add_child ssection
1447 redef fun tpl_content
do
1450 tpl_page
.add_section top
1453 private fun sort_by_mmodule
(mpropdefs
: Collection[MPropDef]): Map[MModule, Set[MPropDef]] do
1454 var map
= new HashMap[MModule, Set[MPropDef]]
1455 for mpropdef
in mpropdefs
do
1456 var mmodule
= mpropdef
.mclassdef
.mmodule
1457 if not map
.has_key
(mmodule
) then map
[mmodule
] = new HashSet[MPropDef]
1458 map
[mmodule
].add mpropdef