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
21 redef class ToolContext
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 output_dir
: String
42 private var min_visibility
: MVisibility
47 var opts
= option_context
48 opts
.add_option
(opt_dir
, opt_source
, opt_sharedir
, opt_shareurl
, opt_nodot
, opt_private
)
49 opts
.add_option
(opt_custom_title
, opt_custom_footer
, opt_custom_intro
, opt_custom_brand
)
50 opts
.add_option
(opt_github_upstream
, opt_github_base_sha1
, opt_github_gitdir
)
51 opts
.add_option
(opt_piwik_tracker
, opt_piwik_site_id
)
53 var tpl
= new Template
54 tpl
.add
"Usage: nitdoc [OPTION]... <file.nit>...\n"
55 tpl
.add
"Generates HTML pages of API documentation from Nit source files."
56 tooldescription
= tpl
.write_to_string
59 redef fun process_options
(args
) do
63 var output_dir
= opt_dir
.value
64 if output_dir
== null then
67 self.output_dir
= output_dir
69 if opt_private
.value
then
70 min_visibility
= none_visibility
72 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"
87 # The Nitdoc class explores the model and generate pages for each mentities found
91 var mainmodule
: MModule
104 private fun init_output_dir
do
105 # create destination dir if it's necessary
106 var output_dir
= ctx
.output_dir
107 if not output_dir
.file_exists
then output_dir
.mkdir
109 var sharedir
= ctx
.opt_sharedir
.value
110 if sharedir
== null then
111 var dir
= ctx
.nit_dir
112 sharedir
= dir
/"share/nitdoc"
113 if not sharedir
.file_exists
then
114 print
"Error: Cannot locate nitdoc share files. Uses --sharedir or envvar NIT_DIR"
119 if ctx
.opt_shareurl
.value
== null then
120 sys
.system
("cp -r -- {sharedir.to_s.escape_to_sh}/* {output_dir.to_s.escape_to_sh}/")
122 sys
.system
("cp -r -- {sharedir.to_s.escape_to_sh}/resources/ {output_dir.to_s.escape_to_sh}/resources/")
127 private fun overview
do
128 var page
= new NitdocOverview(ctx
, model
, mainmodule
)
129 page
.render
.write_to_file
("{ctx.output_dir.to_s}/{page.page_url}")
132 private fun search
do
133 var page
= new NitdocSearch(ctx
, model
, mainmodule
)
134 page
.render
.write_to_file
("{ctx.output_dir.to_s}/{page.page_url}")
137 private fun groups
do
138 for mproject
in model
.mprojects
do
139 for mgroup
in mproject
.mgroups
.to_a
do
140 var page
= new NitdocGroup(ctx
, model
, mainmodule
, mgroup
)
141 page
.render
.write_to_file
("{ctx.output_dir.to_s}/{page.page_url}")
146 private fun modules
do
147 for mmodule
in model
.mmodules
do
148 if mmodule
.is_fictive
then continue
149 var page
= new NitdocModule(ctx
, model
, mainmodule
, mmodule
)
150 page
.render
.write_to_file
("{ctx.output_dir.to_s}/{page.page_url}")
154 private fun classes
do
155 for mclass
in model
.mclasses
do
156 if mclass
.visibility
<= ctx
.min_visibility
then continue
157 var page
= new NitdocClass(ctx
, model
, mainmodule
, mclass
)
158 page
.render
.write_to_file
("{ctx.output_dir.to_s}/{page.page_url}")
162 private fun properties
do
163 for mproperty
in model
.mproperties
do
164 if mproperty
.visibility
<= ctx
.min_visibility
then continue
165 var page
= new NitdocProperty(ctx
, model
, mainmodule
, mproperty
)
166 page
.render
.write_to_file
("{ctx.output_dir.to_s}/{page.page_url}")
170 private fun quicksearch_list
do
171 var quicksearch
= new QuickSearch(ctx
, model
)
172 quicksearch
.render
.write_to_file
("{ctx.output_dir.to_s}/quicksearch-list.js")
176 # Nitdoc QuickSearch list generator
178 # Create a JSON object containing links to:
182 # All entities are grouped by name to make the research easier.
185 private var mmodules
= new HashSet[MModule]
186 private var mclasses
= new HashSet[MClass]
187 private var mpropdefs
= new HashMap[String, Set[MPropDef]]
193 for mmodule
in model
.mmodules
do
194 if mmodule
.is_fictive
then continue
197 for mclass
in model
.mclasses
do
198 if mclass
.visibility
< ctx
.min_visibility
then continue
201 for mproperty
in model
.mproperties
do
202 if mproperty
.visibility
< ctx
.min_visibility
then continue
203 if mproperty
isa MAttribute then continue
204 if not mpropdefs
.has_key
(mproperty
.name
) then
205 mpropdefs
[mproperty
.name
] = new HashSet[MPropDef]
207 mpropdefs
[mproperty
.name
].add_all
(mproperty
.mpropdefs
)
211 fun render
: Template do
212 var tpl
= new Template
213 tpl
.add
"var nitdocQuickSearchRawList=\{ "
214 for mmodule
in mmodules
do
215 tpl
.add
"\"{mmodule.name}\
":["
216 tpl
.add
"\{txt:\"{mmodule.full_name}\",url
:\
"{mmodule.nitdoc_url}\"\
},"
219 for mclass in mclasses do
220 var full_name = mclass.intro.mmodule.full_name
221 tpl.add "\
"{mclass.name}\":["
222 tpl.add "\
{txt:\"{full_name}\
",url:\"{mclass.nitdoc_url}\
"\},"
225 for mproperty
, mprops
in mpropdefs
do
226 tpl
.add
"\"{mproperty}\
":["
227 for mpropdef
in mprops
do
228 var full_name
= mpropdef
.mclassdef
.mclass
.full_name
229 var cls_url
= mpropdef
.mclassdef
.mclass
.nitdoc_url
230 var def_url
= "{cls_url}#{mpropdef.mproperty.nitdoc_id}"
231 tpl
.add
"\{txt:\"{full_name}\",url
:\
"{def_url}\"\
},"
241 # Define page structure and properties
242 abstract class NitdocPage
244 private var ctx: ToolContext
245 private var model: Model
246 private var mainmodule: MModule
247 private var name_sorter = new MEntityNameSorter
249 # Render the page as a html template
250 fun render: Template do
252 if ctx.opt_shareurl.value != null then
253 shareurl = ctx.opt_shareurl.value.as(not null)
258 tpl.title = tpl_title
260 tpl.shareurl = shareurl
261 tpl.topmenu = tpl_topmenu
263 tpl.footer = ctx.opt_custom_footer.value
264 tpl.body_attrs.add(new TagAttribute("data-bootstrap-share
", shareurl))
265 tpl.sidebar = tpl_sidebar
268 var tracker_url = ctx.opt_piwik_tracker.value
269 var site_id = ctx.opt_piwik_site_id.value
270 if tracker_url != null and site_id != null then
271 tpl.scripts.add new TplPiwikScript(tracker_url, site_id)
277 fun page_url: String is abstract
279 # Build page template
280 fun tpl_page: TplPage is abstract
282 # Build page sidebar if any
283 fun tpl_sidebar: nullable TplSidebar do return null
285 # Build page title string
286 fun tpl_title: String do
287 if ctx.opt_custom_title.value != null then
288 return ctx.opt_custom_title.value.to_s
293 # Build top menu template
294 fun tpl_topmenu: TplTopMenu do
295 var topmenu = new TplTopMenu(page_url)
296 var brand = ctx.opt_custom_brand.value
297 if brand != null then
298 var tpl = new Template
299 tpl.add "<span
class='navbar-brand'>"
304 topmenu.add_link new TplLink("index
.html
", "Overview")
305 topmenu.add_link new TplLink("search
.html
", "Index")
309 # Build page content template
310 fun tpl_content is abstract
312 # Clickable graphviz image using dot format
313 # return null if no graph for this page
314 fun tpl_graph(dot: Buffer, name: String, title: nullable String): nullable TplArticle do
315 if ctx.opt_nodot.value then return null
316 var output_dir = ctx.output_dir
317 var path = output_dir / name
318 var path_sh = path.escape_to_sh
319 var file = new OFStream.open("{path}.dot
")
322 sys.system("\
{ test -f {path_sh}.png
&& test
-f
{path_sh}.s
.dot
&& diff
-- {path_sh}.dot
{path_sh}.s
.dot
>/dev
/null 2>&1 ; \
} || \
{ cp -- {path_sh}.dot
{path_sh}.s
.dot
&& dot
-Tpng -o
{path_sh}.png
-Tcmapx -o
{path_sh}.map
{path_sh}.s
.dot
; \
}")
323 var fmap = new IFStream.open("{path}.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.html_escape}'"
333 article.css_classes.add "text-center
"
334 var content = new Template
335 var name_html = name.html_escape
336 content.add "<img src
='{name_html}.png' usemap
='#{name_html}' style
='margin:auto' {alt}/>"
338 article.content = content
342 # A (source) link template for a given location
343 fun tpl_showsource(location: nullable Location): nullable String
345 if location == null then return null
346 var source = ctx.opt_source.value
347 if source == null then
348 var url = location.file.filename.simplify_path
349 return "<a target
='_blank' title
='Show source' href
=\
"{url}\">View Source</a
>"
351 # THIS IS JUST UGLY ! (but there is no replace yet)
352 var x = source.split_with("%f
")
353 source = x.join(location.file.filename.simplify_path)
354 x = source.split_with("%l
")
355 source = x.join(location.line_start.to_s)
356 x = source.split_with("%L
")
357 source = x.join(location.line_end.to_s)
358 source = source.simplify_path
359 return "<a target
='_blank' title
='Show source' href
=\
"{source.to_s}\">View Source</a
>"
362 # MProject description template
363 fun tpl_mproject_article(mproject: MProject): TplArticle do
364 var article = mproject.tpl_article
365 article.subtitle = mproject.tpl_declaration
366 article.content = mproject.tpl_definition
367 if mproject.mdoc != null then
368 article.content = mproject.mdoc.tpl_short_comment
373 # MGroup description template
374 fun tpl_mgroup_article(mgroup: MGroup): TplArticle do
375 var article = mgroup.tpl_article
376 article.subtitle = mgroup.tpl_declaration
377 article.content = mgroup.tpl_definition
381 # MModule description template
382 fun tpl_mmodule_article(mmodule: MModule): TplArticle do
383 var article = mmodule.tpl_article
384 article.subtitle = mmodule.tpl_declaration
385 article.content = mmodule.tpl_definition
387 var intros = mmodule.intro_mclassdefs(ctx.min_visibility).to_a
388 if not intros.is_empty then
389 mainmodule.linearize_mclassdefs(intros)
390 var intros_art = new TplArticle.with_title("{mmodule.nitdoc_id}_intros
", "Introduces")
391 var intros_lst = new TplList.with_classes(["list-unstyled
", "list-labeled
"])
392 for mclassdef in intros do
393 intros_lst.add_li mclassdef.tpl_list_item
395 if not intros_lst.is_empty then
396 intros_art.content = intros_lst
397 article.add_child intros_art
400 var redefs = mmodule.redef_mclassdefs(ctx.min_visibility).to_a
401 if not redefs.is_empty then
402 mainmodule.linearize_mclassdefs(redefs)
403 var redefs_art = new TplArticle.with_title("{mmodule.nitdoc_id}_redefs
", "Redefines")
404 var redefs_lst = new TplList.with_classes(["list-unstyled
", "list-labeled
"])
405 for mclassdef in redefs do
406 redefs_lst.add_li mclassdef.tpl_list_item
408 if not redefs_lst.is_empty then
409 redefs_art.content = redefs_lst
410 article.add_child redefs_art
416 # MClassDef description template
417 fun tpl_mclass_article(mclass: MClass, mclassdefs: Array[MClassDef]): TplArticle do
418 var article = mclass.tpl_article
419 if not mclassdefs.has(mclass.intro) then
421 var intro_article = mclass.intro.tpl_short_article
422 intro_article.source_link = tpl_showsource(mclass.intro.location)
423 article.add_child intro_article
425 mainmodule.linearize_mclassdefs(mclassdefs)
426 for mclassdef in mclassdefs do
427 # add mclassdef full description
428 var redef_article = mclassdef.tpl_article
429 redef_article.source_link = tpl_showsource(mclassdef.location)
430 article.add_child redef_article
432 var intros = new TplArticle.with_title("{mclassdef.nitdoc_id}_intros
", "Introduces")
433 var intros_lst = new TplList.with_classes(["list-unstyled
", "list-labeled
"])
434 for mpropdef in mclassdef.collect_intro_mpropdefs(ctx.min_visibility) do
435 intros_lst.add_li mpropdef.tpl_list_item
437 if not intros_lst.is_empty then
438 intros.content = intros_lst
439 redef_article.add_child intros
441 var redefs = new TplArticle.with_title("{mclassdef.nitdoc_id}_redefs
", "Redefines")
442 var redefs_lst = new TplList.with_classes(["list-unstyled
", "list-labeled
"])
443 for mpropdef in mclassdef.collect_redef_mpropdefs(ctx.min_visibility) do
444 redefs_lst.add_li mpropdef.tpl_list_item
446 if not redefs_lst.is_empty then
447 redefs.content = redefs_lst
448 redef_article.add_child redefs
454 # MClassDef description template
455 fun tpl_mclassdef_article(mclassdef: MClassDef): TplArticle do
456 var article = mclassdef.tpl_article
457 if mclassdef.is_intro then article.content = null
458 article.source_link = tpl_showsource(mclassdef.location)
462 # MProp description template
464 # `main_mpropdef`: The most important mpropdef to display
465 # `local_mpropdefs`: List of other locally defined mpropdefs to display
466 # `lin`: full linearization from local_mpropdefs to intro (displayed in redef tree)
467 fun tpl_mprop_article(main_mpropdef: MPropDef, local_mpropdefs: Array[MPropDef],
468 lin: Array[MPropDef]): TplArticle do
469 var mprop = main_mpropdef.mproperty
470 var article = new TplArticle(mprop.nitdoc_id)
471 var title = new Template
472 title.add mprop.tpl_icon
473 title.add "<span id
='{main_mpropdef.nitdoc_id}'></span
>"
474 if main_mpropdef.is_intro then
475 title.add mprop.tpl_link
476 title.add mprop.intro.tpl_signature
478 var cls_url = mprop.intro.mclassdef.mclass.nitdoc_url
479 var def_url = "{cls_url}#{mprop.nitdoc_id}"
480 var lnk
= new TplLink.with_title
(def_url
, mprop
.name
, "Go to introduction")
484 article
.title
= title
485 article
.title_classes
.add
"signature"
486 article
.summary_title
= "{mprop.nitdoc_name}"
487 article
.subtitle
= main_mpropdef
.tpl_namespace
488 if main_mpropdef
.mdoc
!= null then
489 article
.content
= main_mpropdef
.mdoc
.tpl_comment
491 var subarticle
= new TplArticle("{main_mpropdef.nitdoc_id}_redefs")
492 # Add redef in same `MClass`
493 if local_mpropdefs
.length
> 1 then
494 for mpropdef
in local_mpropdefs
do
495 if mpropdef
== main_mpropdef
then continue
496 var redef_article
= new TplArticle("{mpropdef.nitdoc_id}")
497 var redef_title
= new Template
498 redef_title
.add
"also redef in "
499 redef_title
.add mpropdef
.tpl_namespace
500 redef_article
.title
= redef_title
501 redef_article
.title_classes
.add
"signature info"
502 redef_article
.css_classes
.add
"nospace"
503 var redef_content
= new Template
504 if mpropdef
.mdoc
!= null then
505 redef_content
.add mpropdef
.mdoc
.tpl_comment
507 redef_article
.content
= redef_content
508 subarticle
.add_child redef_article
512 if lin
.length
> 1 then
513 var lin_article
= new TplArticle("{main_mpropdef.nitdoc_id}_lin")
514 lin_article
.title
= "Inheritance"
515 var lst
= new TplList.with_classes
(["list-unstyled", "list-labeled"])
516 for mpropdef
in lin
do
517 lst
.add_li mpropdef
.tpl_inheritance_item
519 lin_article
.content
= lst
520 subarticle
.add_child lin_article
522 article
.add_child subarticle
526 # MProperty description template
527 fun tpl_mpropdef_article
(mpropdef
: MPropDef): TplArticle do
528 var article
= mpropdef
.tpl_article
529 article
.source_link
= tpl_showsource
(mpropdef
.location
)
535 # Display a list of modules contained in program
539 private var page
= new TplPage
540 redef fun tpl_page
do return page
542 private var sidebar
= new TplSidebar
543 redef fun tpl_sidebar
do return sidebar
545 redef fun tpl_title
do
546 if ctx
.opt_custom_title
.value
!= null then
547 return ctx
.opt_custom_title
.value
.to_s
553 redef fun page_url
do return "index.html"
556 private fun tpl_intro
: TplSection do
557 var section
= new TplSection.with_title
("overview", tpl_title
)
558 var article
= new TplArticle("intro")
559 if ctx
.opt_custom_intro
.value
!= null then
560 article
.content
= ctx
.opt_custom_intro
.value
.to_s
562 section
.add_child article
567 private fun tpl_projects
(section
: TplSection) do
569 var mprojects
= model
.mprojects
.to_a
570 var sorter
= new MConcernRankSorter
571 sorter
.sort mprojects
572 var ssection
= new TplSection.with_title
("projects", "Projects")
573 for mproject
in mprojects
do
574 ssection
.add_child tpl_mproject_article
(mproject
)
576 section
.add_child ssection
579 redef fun tpl_content
do
582 tpl_page
.add_section top
587 # Display a list of modules, classes and properties
591 private var page
= new TplPage
592 redef fun tpl_page
do return page
594 redef fun tpl_title
do return "Index"
596 redef fun page_url
do return "search.html"
598 redef fun tpl_content
do
599 var tpl
= new TplSearchPage("search_all")
600 var section
= new TplSection("search")
604 for mmodule
in modules_list
do
605 tpl
.modules
.add mmodule
.tpl_link
608 for mclass
in classes_list
do
609 tpl
.classes
.add mclass
.tpl_link
612 for mproperty
in mprops_list
do
614 m
.add mproperty
.intro
.tpl_link
616 m
.add mproperty
.intro
.mclassdef
.mclass
.tpl_link
620 section
.add_child tpl
621 tpl_page
.add_section section
624 # Extract mmodule list to display (sorted by name)
625 private fun modules_list
: Array[MModule] do
626 var sorted
= new Array[MModule]
627 for mmodule
in model
.mmodule_importation_hierarchy
do
628 if mmodule
.is_fictive
then continue
631 name_sorter
.sort
(sorted
)
635 # Extract mclass list to display (sorted by name)
636 private fun classes_list
: Array[MClass] do
637 var sorted
= new Array[MClass]
638 for mclass
in model
.mclasses
do
639 if mclass
.visibility
< ctx
.min_visibility
then continue
642 name_sorter
.sort
(sorted
)
646 # Extract mproperty list to display (sorted by name)
647 private fun mprops_list
: Array[MProperty] do
648 var sorted
= new Array[MProperty]
649 for mproperty
in model
.mproperties
do
650 if mproperty
.visibility
< ctx
.min_visibility
then continue
651 if mproperty
isa MAttribute then continue
654 name_sorter
.sort
(sorted
)
660 # Display a flattened view of the group
664 private var mgroup
: MGroup
666 private var concerns
: ConcernsTree is noinit
667 private var intros
: Set[MClass] is noinit
668 private var redefs
: Set[MClass] is noinit
671 self.concerns
= model
.concerns_tree
(mgroup
.collect_mmodules
)
672 self.concerns
.sort_with
(new MConcernRankSorter)
673 self.intros
= mgroup
.in_nesting_intro_mclasses
(ctx
.min_visibility
)
674 var redefs
= new HashSet[MClass]
675 for rdef
in mgroup
.in_nesting_redef_mclasses
(ctx
.min_visibility
) do
676 if intros
.has
(rdef
) then continue
682 private var page
= new TplPage
683 redef fun tpl_page
do return page
685 private var sidebar
= new TplSidebar
686 redef fun tpl_sidebar
do return sidebar
688 redef fun tpl_title
do return mgroup
.nitdoc_name
690 redef fun page_url
do return mgroup
.nitdoc_url
692 redef fun tpl_topmenu
do
694 var mproject
= mgroup
.mproject
695 if not mgroup
.is_root
then
696 topmenu
.add_link
new TplLink(mproject
.nitdoc_url
, mproject
.nitdoc_name
)
698 topmenu
.add_link
new TplLink(page_url
, mproject
.nitdoc_name
)
702 # Class list to display in sidebar
703 fun tpl_sidebar_mclasses
do
704 var mclasses
= new HashSet[MClass]
705 mclasses
.add_all intros
706 mclasses
.add_all redefs
707 if mclasses
.is_empty
then return
708 var list
= new TplList.with_classes
(["list-unstyled", "list-labeled"])
710 var sorted
= mclasses
.to_a
711 name_sorter
.sort
(sorted
)
712 for mclass
in sorted
do
713 list
.add_li tpl_sidebar_item
(mclass
)
715 tpl_sidebar
.boxes
.add
new TplSideBox.with_content
("All classes", list
)
718 private fun tpl_sidebar_item
(def
: MClass): TplListItem do
719 var classes
= def
.intro
.tpl_css_classes
.to_a
720 if intros
.has
(def
) then
725 var lnk
= new Template
726 lnk
.add
new TplLabel.with_classes
(classes
)
728 return new TplListItem.with_content
(lnk
)
732 private fun tpl_intro
: TplSection do
733 var section
= new TplSection.with_title
("top", tpl_title
)
734 var article
= new TplArticle("intro")
736 if mgroup
.is_root
then
737 section
.subtitle
= mgroup
.mproject
.tpl_declaration
738 article
.content
= mgroup
.mproject
.tpl_definition
740 section
.subtitle
= mgroup
.tpl_declaration
741 article
.content
= mgroup
.tpl_definition
743 section
.add_child article
747 private fun tpl_concerns
(section
: TplSection) do
748 if concerns
.is_empty
then return
749 section
.add_child
new TplArticle.with_content
("concerns", "Concerns", concerns
.to_tpl
)
752 private fun tpl_groups
(parent
: TplSection) do
753 var lst
= concerns
.to_a
755 for mentity
in lst
do
756 if mentity
isa MProject then
757 section
.add_child
new TplSection(mentity
.nitdoc_id
)
758 else if mentity
isa MGroup then
759 section
.add_child
new TplSection(mentity
.nitdoc_id
)
760 else if mentity
isa MModule then
761 section
.add_child tpl_mmodule_article
(mentity
)
766 redef fun tpl_content
do
771 tpl_page
.add_section top
774 private fun sort_by_mclass
(mclassdefs
: Collection[MClassDef]): Map[MClass, Set[MClassDef]] do
775 var map
= new HashMap[MClass, Set[MClassDef]]
776 for mclassdef
in mclassdefs
do
777 var mclass
= mclassdef
.mclass
778 if not map
.has_key
(mclass
) then map
[mclass
] = new HashSet[MClassDef]
779 map
[mclass
].add mclassdef
786 # Display the list of introduced and redefined classes in module
790 private var mmodule
: MModule
791 private var concerns
: ConcernsTree is noinit
792 private var mclasses2mdefs
: Map[MClass, Set[MClassDef]] is noinit
793 private var mmodules2mclasses
: Map[MModule, Set[MClass]] is noinit
797 var mclassdefs
= new HashSet[MClassDef]
798 mclassdefs
.add_all mmodule
.intro_mclassdefs
(ctx
.min_visibility
)
799 mclassdefs
.add_all mmodule
.redef_mclassdefs
(ctx
.min_visibility
)
800 self.mclasses2mdefs
= sort_by_mclass
(mclassdefs
)
801 self.mmodules2mclasses
= group_by_mmodule
(mclasses2mdefs
.keys
)
802 self.concerns
= model
.concerns_tree
(mmodules2mclasses
.keys
)
804 mmodule
.mgroup
.mproject
.booster_rank
= -1000
805 mmodule
.mgroup
.booster_rank
= -1000
806 mmodule
.booster_rank
= -1000
807 self.concerns
.sort_with
(new MConcernRankSorter)
808 mmodule
.mgroup
.mproject
.booster_rank
= 0
809 mmodule
.mgroup
.booster_rank
= 0
810 mmodule
.booster_rank
= 0
813 private var page
= new TplPage
814 redef fun tpl_page
do return page
816 private var sidebar
= new TplSidebar
817 redef fun tpl_sidebar
do return sidebar
819 redef fun tpl_title
do return mmodule
.nitdoc_name
820 redef fun page_url
do return mmodule
.nitdoc_url
822 redef fun tpl_topmenu
do
824 var mproject
= mmodule
.mgroup
.mproject
825 topmenu
.add_link
new TplLink(mproject
.nitdoc_url
, mproject
.nitdoc_name
)
826 topmenu
.add_link
new TplLink(page_url
, mmodule
.nitdoc_name
)
830 # Class list to display in sidebar
831 fun tpl_sidebar_mclasses
do
832 var mclasses
= new HashSet[MClass]
833 mclasses
.add_all mmodule
.filter_intro_mclasses
(ctx
.min_visibility
)
834 mclasses
.add_all mmodule
.filter_redef_mclasses
(ctx
.min_visibility
)
835 if mclasses
.is_empty
then return
836 var list
= new TplList.with_classes
(["list-unstyled", "list-labeled"])
838 var sorted
= mclasses
.to_a
839 name_sorter
.sort
(sorted
)
840 for mclass
in sorted
do
841 list
.add_li tpl_sidebar_item
(mclass
)
843 tpl_sidebar
.boxes
.add
new TplSideBox.with_content
("All classes", list
)
846 private fun tpl_sidebar_item
(def
: MClass): TplListItem do
847 var classes
= def
.intro
.tpl_css_classes
.to_a
848 if def
.intro_mmodule
== mmodule
then
853 var lnk
= new Template
854 lnk
.add
new TplLabel.with_classes
(classes
)
856 return new TplListItem.with_content
(lnk
)
860 private fun tpl_intro
: TplSection do
861 var section
= new TplSection.with_title
("top", tpl_title
)
862 section
.subtitle
= mmodule
.tpl_declaration
864 var article
= new TplArticle("intro")
865 var def
= mmodule
.tpl_definition
866 var location
= mmodule
.location
867 article
.source_link
= tpl_showsource
(location
)
868 article
.content
= def
869 section
.add_child article
873 # inheritance section
874 private fun tpl_inheritance
(parent
: TplSection) do
875 # Extract relevent modules
876 var imports
= mmodule
.in_importation
.greaters
877 if imports
.length
> 10 then imports
= mmodule
.in_importation
.direct_greaters
878 var clients
= mmodule
.in_importation
.smallers
879 if clients
.length
> 10 then clients
= mmodule
.in_importation
.direct_smallers
882 var section
= new TplSection.with_title
("dependencies", "Dependencies")
885 var mmodules
= new HashSet[MModule]
886 mmodules
.add_all mmodule
.in_nesting
.direct_greaters
887 mmodules
.add_all imports
888 if clients
.length
< 10 then mmodules
.add_all clients
890 var graph
= tpl_dot
(mmodules
)
891 if graph
!= null then section
.add_child graph
894 var lst
= new Array[MModule]
895 for dep
in imports
do
896 if dep
.is_fictive
then continue
897 if dep
== mmodule
then continue
900 if not lst
.is_empty
then
902 section
.add_child tpl_list
("imports", "Imports", lst
)
906 lst
= new Array[MModule]
907 for dep
in clients
do
908 if dep
.is_fictive
then continue
909 if dep
== mmodule
then continue
912 if not lst
.is_empty
then
914 section
.add_child tpl_list
("clients", "Clients", lst
)
917 parent
.add_child section
920 private fun tpl_list
(id
: String, title
: String, mmodules
: Array[MModule]): TplArticle do
921 var article
= new TplArticle.with_title
(id
, title
)
922 var list
= new TplList.with_classes
(["list-unstyled", "list-definition"])
923 for mmodule
in mmodules
do list
.elts
.add mmodule
.tpl_list_item
924 article
.content
= list
928 private fun tpl_concerns
(parent
: TplSection) do
929 if concerns
.is_empty
then return
930 parent
.add_child
new TplArticle.with_content
("concerns", "Concerns", concerns
.to_tpl
)
933 private fun tpl_mclasses
(parent
: TplSection) do
934 for mentity
in concerns
do
935 if mentity
isa MProject then
936 parent
.add_child
new TplSection(mentity
.nitdoc_id
)
937 else if mentity
isa MGroup then
938 parent
.add_child
new TplSection(mentity
.nitdoc_id
)
939 else if mentity
isa MModule then
940 var section
= new TplSection(mentity
.nitdoc_id
)
941 var title
= new Template
942 if mentity
== mmodule
then
944 section
.summary_title
= "in {mentity.nitdoc_name}"
947 section
.summary_title
= "from {mentity.nitdoc_name}"
949 title
.add mentity
.tpl_namespace
950 section
.title
= title
952 var mclasses
= mmodules2mclasses
[mentity
].to_a
953 name_sorter
.sort
(mclasses
)
954 for mclass
in mclasses
do
955 section
.add_child tpl_mclass_article
(mclass
, mclasses2mdefs
[mclass
].to_a
)
957 parent
.add_child section
962 private fun group_by_mmodule
(mclasses
: Collection[MClass]): Map[MModule, Set[MClass]] do
963 var res
= new HashMap[MModule, Set[MClass]]
964 for mclass
in mclasses
do
965 var mmodule
= mclass
.intro_mmodule
966 if not res
.has_key
(mmodule
) then
967 res
[mmodule
] = new HashSet[MClass]
969 res
[mmodule
].add
(mclass
)
974 redef fun tpl_content
do
980 tpl_page
.add_section top
983 # Genrate dot hierarchy for class inheritance
984 fun tpl_dot
(mmodules
: Collection[MModule]): nullable TplArticle do
985 var poset
= new POSet[MModule]
986 for mmodule
in mmodules
do
987 if mmodule
.is_fictive
then continue
988 poset
.add_node mmodule
989 for omodule
in mmodules
do
990 if mmodule
.is_fictive
then continue
991 poset
.add_node mmodule
992 if mmodule
.in_importation
< omodule
then
993 poset
.add_edge
(mmodule
, omodule
)
998 var op
= new RopeBuffer
999 var name
= "dep_module_{mmodule.nitdoc_id}"
1000 op
.append
("digraph \"{name.escape_to_dot}\
" \{ 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")
1001 for mmodule
in poset
do
1002 if mmodule
== self.mmodule
then
1003 op
.append
("\"{mmodule.name.escape_to_dot}\
"[shape=box,margin=0.03];\n")
1005 op
.append
("\"{mmodule.name.escape_to_dot}\
"[URL=\"{mmodule.nitdoc_url.escape_to_dot}\
"];\n")
1007 for omodule
in poset
[mmodule
].direct_greaters
do
1008 op
.append
("\"{mmodule.name.escape_to_dot}\
"->\"{omodule.name.escape_to_dot}\
";\n")
1012 return tpl_graph
(op
, name
, null)
1015 private fun sort_by_mclass
(mclassdefs
: Collection[MClassDef]): Map[MClass, Set[MClassDef]] do
1016 var map
= new HashMap[MClass, Set[MClassDef]]
1017 for mclassdef
in mclassdefs
do
1018 var mclass
= mclassdef
.mclass
1019 if not map
.has_key
(mclass
) then map
[mclass
] = new HashSet[MClassDef]
1020 map
[mclass
].add mclassdef
1027 # Display a list properties defined or redefined for this class
1031 private var mclass
: MClass
1032 private var concerns
: ConcernsTree is noinit
1033 private var mprops2mdefs
: Map[MProperty, Set[MPropDef]] is noinit
1034 private var mmodules2mprops
: Map[MModule, Set[MProperty]] is noinit
1037 var mpropdefs
= new HashSet[MPropDef]
1038 mpropdefs
.add_all mclass
.intro_mpropdefs
(ctx
.min_visibility
)
1039 mpropdefs
.add_all mclass
.redef_mpropdefs
(ctx
.min_visibility
)
1040 self.mprops2mdefs
= sort_by_mproperty
(mpropdefs
)
1041 self.mmodules2mprops
= sort_by_mmodule
(mprops2mdefs
.keys
)
1042 self.concerns
= model
.concerns_tree
(mmodules2mprops
.keys
)
1043 self.concerns
.sort_with
(new MConcernRankSorter)
1046 private var page
= new TplPage
1047 redef fun tpl_page
do return page
1049 private var sidebar
= new TplSidebar
1050 redef fun tpl_sidebar
do return sidebar
1052 redef fun tpl_title
do return "{mclass.nitdoc_name}{mclass.tpl_signature.write_to_string}"
1053 redef fun page_url
do return mclass
.nitdoc_url
1055 redef fun tpl_topmenu
do
1057 var mproject
= mclass
.intro_mmodule
.mgroup
.mproject
1058 topmenu
.add_link
new TplLink("{mproject.nitdoc_url}", "{mproject.nitdoc_name}")
1059 topmenu
.add_link
new TplLink(page_url
, mclass
.nitdoc_name
)
1063 # Property list to display in sidebar
1064 fun tpl_sidebar_properties
do
1065 var kind_map
= sort_by_kind
(mclass_inherited_mprops
)
1066 var summary
= new TplList.with_classes
(["list-unstyled"])
1068 tpl_sidebar_list
("Virtual types", kind_map
["type"].to_a
, summary
)
1069 tpl_sidebar_list
("Constructors", kind_map
["init"].to_a
, summary
)
1070 tpl_sidebar_list
("Methods", kind_map
["fun"].to_a
, summary
)
1071 tpl_sidebar
.boxes
.add
new TplSideBox.with_content
("All properties", summary
)
1074 private fun tpl_sidebar_list
(name
: String, mprops
: Array[MProperty], summary
: TplList) do
1075 if mprops
.is_empty
then return
1076 name_sorter
.sort
(mprops
)
1077 var entry
= new TplListItem.with_content
(name
)
1078 var list
= new TplList.with_classes
(["list-unstyled", "list-labeled"])
1079 for mprop
in mprops
do
1080 list
.add_li tpl_sidebar_item
(mprop
)
1083 summary
.elts
.add entry
1086 private fun tpl_sidebar_item
(mprop
: MProperty): TplListItem do
1087 var classes
= mprop
.intro
.tpl_css_classes
.to_a
1088 if not mprops2mdefs
.has_key
(mprop
) then
1089 classes
.add
"inherit"
1090 var cls_url
= mprop
.intro
.mclassdef
.mclass
.nitdoc_url
1091 var def_url
= "{cls_url}#{mprop.nitdoc_id}"
1092 var lnk
= new TplLink(def_url
, mprop
.name
)
1093 if mprop
.intro
.mdoc
!= null then lnk
.title
= mprop
.intro
.mdoc
.short_comment
1094 var item
= new Template
1095 item
.add
new TplLabel.with_classes
(classes
)
1097 return new TplListItem.with_content
(item
)
1099 var defs
= mprops2mdefs
[mprop
]
1100 if defs
.has
(mprop
.intro
) then
1105 var lnk
= new Template
1106 lnk
.add
new TplLabel.with_classes
(classes
)
1107 lnk
.add mprop
.tpl_anchor
1108 return new TplListItem.with_content
(lnk
)
1111 private fun tpl_intro
: TplSection do
1112 var section
= new TplSection.with_title
("top", tpl_title
)
1113 section
.subtitle
= mclass
.intro
.tpl_declaration
1114 var article
= new TplArticle("comment")
1115 if mclass
.mdoc
!= null then
1116 article
.content
= mclass
.mdoc
.tpl_comment
1118 section
.add_child article
1122 private fun tpl_concerns
(parent
: TplSection) do
1124 var section
= new TplSection.with_title
("intro", "Introduction")
1125 section
.summary_title
= "Introduction"
1126 section
.add_child tpl_mclassdef_article
(mclass
.intro
)
1127 parent
.add_child section
1129 if concerns
.is_empty
then return
1130 parent
.add_child
new TplArticle.with_content
("concerns", "Concerns", concerns
.to_tpl
)
1133 private fun tpl_inheritance
(parent
: TplSection) do
1135 var hparents
= new HashSet[MClass]
1136 for c
in mclass
.in_hierarchy
(mainmodule
).direct_greaters
do
1137 if c
.visibility
< ctx
.min_visibility
then continue
1142 var hancestors
= new HashSet[MClass]
1143 for c
in mclass
.in_hierarchy
(mainmodule
).greaters
do
1144 if c
== mclass
then continue
1145 if c
.visibility
< ctx
.min_visibility
then continue
1146 if hparents
.has
(c
) then continue
1151 var hchildren
= new HashSet[MClass]
1152 for c
in mclass
.in_hierarchy
(mainmodule
).direct_smallers
do
1153 if c
.visibility
< ctx
.min_visibility
then continue
1158 var hdescendants
= new HashSet[MClass]
1159 for c
in mclass
.in_hierarchy
(mainmodule
).smallers
do
1160 if c
== mclass
then continue
1161 if c
.visibility
< ctx
.min_visibility
then continue
1162 if hchildren
.has
(c
) then continue
1167 var section
= new TplSection.with_title
("inheritance", "Inheritance")
1170 var mclasses
= new HashSet[MClass]
1171 mclasses
.add_all hancestors
1172 mclasses
.add_all hparents
1173 mclasses
.add_all hchildren
1174 mclasses
.add_all hdescendants
1176 var graph
= tpl_dot
(mclasses
)
1177 if graph
!= null then section
.add_child graph
1180 if not hparents
.is_empty
then
1181 var lst
= hparents
.to_a
1182 name_sorter
.sort lst
1183 section
.add_child tpl_list
("parents", "Parents", lst
)
1187 if not hancestors
.is_empty
then
1188 var lst
= hancestors
.to_a
1189 name_sorter
.sort lst
1190 section
.add_child tpl_list
("ancestors", "Ancestors", lst
)
1194 if not hchildren
.is_empty
then
1195 var lst
= hchildren
.to_a
1196 name_sorter
.sort lst
1197 section
.add_child tpl_list
("children", "Children", lst
)
1201 if not hdescendants
.is_empty
then
1202 var lst
= hdescendants
.to_a
1203 name_sorter
.sort lst
1204 section
.add_child tpl_list
("descendants", "Descendants", lst
)
1207 parent
.add_child section
1210 private fun tpl_list
(id
: String, title
: String, elts
: Array[MClass]): TplArticle do
1211 var article
= new TplArticle.with_title
(id
, title
)
1212 if elts
.length
> 20 then
1213 var tpl
= new Template
1216 if e
!= elts
.last
then tpl
.add
", "
1218 article
.content
= tpl
1220 var list
= new TplList.with_classes
(["list-unstyled", "list-definition"])
1221 for elt
in elts
do list
.elts
.add elt
.tpl_list_item
1222 article
.content
= list
1227 private fun tpl_properties
(parent
: TplSection) do
1228 var lst
= concerns
.to_a
1229 for mentity
in lst
do
1230 if mentity
isa MProject then
1231 parent
.add_child
new TplSection(mentity
.nitdoc_id
)
1232 else if mentity
isa MGroup then
1233 parent
.add_child
new TplSection(mentity
.nitdoc_id
)
1234 else if mentity
isa MModule then
1235 var section
= new TplSection(mentity
.nitdoc_id
)
1236 var title
= new Template
1238 title
.add mentity
.tpl_namespace
1239 section
.title
= title
1240 section
.summary_title
= "in {mentity.nitdoc_name}"
1243 var mprops
= mmodules2mprops
[mentity
]
1244 var kind_map
= sort_by_kind
(mprops
)
1247 for article
in tpl_mproperty_articles
(kind_map
, "type") do
1248 section
.add_child article
1251 for article
in tpl_mproperty_articles
(kind_map
, "init") do
1252 section
.add_child article
1255 for article
in tpl_mproperty_articles
(kind_map
, "fun") do
1256 section
.add_child article
1258 parent
.add_child section
1263 private fun tpl_mproperty_articles
(kind_map
: Map[String, Set[MProperty]],
1264 kind_name
: String): Sequence[TplArticle] do
1265 var articles
= new List[TplArticle]
1266 var elts
= kind_map
[kind_name
].to_a
1267 name_sorter
.sort
(elts
)
1269 var local_defs
= mprops2mdefs
[elt
]
1270 # var all_defs = elt.mpropdefs
1271 var all_defs
= new HashSet[MPropDef]
1272 for local_def
in local_defs
do
1273 all_defs
.add local_def
1274 var mpropdef
= local_def
1275 while not mpropdef
.is_intro
do
1276 mpropdef
= mpropdef
.lookup_next_definition
(mainmodule
, mpropdef
.mclassdef
.bound_mtype
)
1277 all_defs
.add mpropdef
1280 var loc_lin
= local_defs
.to_a
1281 mainmodule
.linearize_mpropdefs
(loc_lin
)
1282 var all_lin
= all_defs
.to_a
1283 mainmodule
.linearize_mpropdefs
(all_lin
)
1284 articles
.add tpl_mprop_article
(loc_lin
.first
, loc_lin
, all_lin
)
1289 redef fun tpl_content
do
1290 tpl_sidebar_properties
1292 tpl_inheritance
(top
)
1295 tpl_page
.add_section top
1298 private fun sort_by_mproperty
(mpropdefs
: Collection[MPropDef]): Map[MProperty, Set[MPropDef]] do
1299 var map
= new HashMap[MProperty, Set[MPropDef]]
1300 for mpropdef
in mpropdefs
do
1301 var mproperty
= mpropdef
.mproperty
1302 if not map
.has_key
(mproperty
) then map
[mproperty
] = new HashSet[MPropDef]
1303 map
[mproperty
].add mpropdef
1308 private fun sort_by_mmodule
(mprops
: Collection[MProperty]): Map[MModule, Set[MProperty]] do
1309 var map
= new HashMap[MModule, Set[MProperty]]
1310 for mprop
in mprops
do
1311 var mpropdefs
= mprops2mdefs
[mprop
].to_a
1312 mainmodule
.linearize_mpropdefs
(mpropdefs
)
1313 var mmodule
= mpropdefs
.first
.mclassdef
.mmodule
1314 if not map
.has_key
(mmodule
) then map
[mmodule
] = new HashSet[MProperty]
1315 map
[mmodule
].add mprop
1320 private fun sort_by_kind
(mprops
: Collection[MProperty]): Map[String, Set[MProperty]] do
1321 var map
= new HashMap[String, Set[MProperty]]
1322 map
["type"] = new HashSet[MProperty]
1323 map
["init"] = new HashSet[MProperty]
1324 map
["fun"] = new HashSet[MProperty]
1325 for mprop
in mprops
do
1326 if mprop
isa MVirtualTypeProp then
1327 map
["type"].add mprop
1328 else if mprop
isa MMethod then
1329 if mprop
.is_init
then
1330 map
["init"].add mprop
1332 map
["fun"].add mprop
1339 private fun mclass_inherited_mprops
: Set[MProperty] do
1340 var res
= new HashSet[MProperty]
1341 var local
= mclass
.local_mproperties
(ctx
.min_visibility
)
1342 for mprop
in mclass
.inherited_mproperties
(mainmodule
, ctx
.min_visibility
) do
1343 if local
.has
(mprop
) then continue
1344 #if mprop isa MMethod and mprop.is_init then continue
1345 if mprop
.intro
.mclassdef
.mclass
.name
== "Object" and
1346 (mprop
.visibility
== protected_visibility
or
1347 mprop
.intro
.mclassdef
.mmodule
.name
!= "kernel") then continue
1354 private fun collect_mmodules
(mprops
: Collection[MProperty]): Set[MModule] do
1355 var res
= new HashSet[MModule]
1356 for mprop
in mprops
do
1357 if mprops2mdefs
.has_key
(mprop
) then
1358 for mpropdef
in mprops2mdefs
[mprop
] do res
.add mpropdef
.mclassdef
.mmodule
1364 # Generate dot hierarchy for classes
1365 fun tpl_dot
(mclasses
: Collection[MClass]): nullable TplArticle do
1366 var poset
= new POSet[MClass]
1368 for mclass
in mclasses
do
1369 poset
.add_node mclass
1370 for oclass
in mclasses
do
1371 if mclass
== oclass
then continue
1372 poset
.add_node oclass
1373 if mclass
.in_hierarchy
(mainmodule
) < oclass
then
1374 poset
.add_edge
(mclass
, oclass
)
1379 var op
= new RopeBuffer
1380 var name
= "dep_class_{mclass.nitdoc_id}"
1381 op
.append
("digraph \"{name.escape_to_dot}\
" \{ 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")
1382 var classes
= poset
.to_a
1383 var todo
= new Array[MClass]
1384 var done
= new HashSet[MClass]
1385 mainmodule
.linearize_mclasses
(classes
)
1386 if not classes
.is_empty
then todo
.add classes
.first
1387 while not todo
.is_empty
do
1389 if done
.has
(c
) then continue
1392 op
.append
("\"{c.name.escape_to_dot}\
"[shape=box,margin=0.03];\n")
1394 op
.append
("\"{c.name.escape_to_dot}\
"[URL=\"{c.nitdoc_url.escape_to_dot}\
"];\n")
1396 var smallers
= poset
[c
].direct_smallers
1397 if smallers
.length
< 10 then
1398 for c2
in smallers
do
1399 op
.append
("\"{c2.name.escape_to_dot}\
"->\"{c.name.escape_to_dot}\
";\n")
1401 todo
.add_all smallers
1403 op
.append
("\"...\
"->\"{c.name.escape_to_dot}\
";\n")
1407 return tpl_graph
(op
, name
, null)
1412 class NitdocProperty
1415 private var mproperty
: MProperty
1416 private var concerns
: ConcernsTree is noinit
1417 private var mmodules2mdefs
: Map[MModule, Set[MPropDef]] is noinit
1420 self.mproperty
= mproperty
1421 self.mmodules2mdefs
= sort_by_mmodule
(collect_mpropdefs
)
1422 self.concerns
= model
.concerns_tree
(mmodules2mdefs
.keys
)
1423 self.concerns
.sort_with
(new MConcernRankSorter)
1426 private fun collect_mpropdefs
: Set[MPropDef] do
1427 var res
= new HashSet[MPropDef]
1428 for mpropdef
in mproperty
.mpropdefs
do
1429 if not mpropdef
.is_intro
then res
.add mpropdef
1434 private var page
= new TplPage
1435 redef fun tpl_page
do return page
1437 private var sidebar
= new TplSidebar
1438 redef fun tpl_sidebar
do return sidebar
1440 redef fun tpl_title
do
1441 return "{mproperty.nitdoc_name}{mproperty.tpl_signature.write_to_string}"
1444 redef fun page_url
do return mproperty
.nitdoc_url
1446 redef fun tpl_topmenu
do
1448 var mmodule
= mproperty
.intro_mclassdef
.mmodule
1449 var mproject
= mmodule
.mgroup
.mproject
1450 var mclass
= mproperty
.intro_mclassdef
.mclass
1451 topmenu
.add_link
new TplLink("{mproject.nitdoc_url}", "{mproject.nitdoc_name}")
1452 topmenu
.add_link
new TplLink("{mclass.nitdoc_url}", "{mclass.nitdoc_name}")
1453 topmenu
.add_link
new TplLink(page_url
, mproperty
.nitdoc_name
)
1457 private fun tpl_intro
: TplSection do
1458 var title
= new Template
1459 title
.add mproperty
.nitdoc_name
1460 title
.add mproperty
.intro
.tpl_signature
1461 var section
= new TplSection.with_title
("top", title
)
1462 section
.subtitle
= mproperty
.tpl_namespace
1463 section
.summary_title
= mproperty
.nitdoc_name
1467 private fun tpl_properties
(parent
: TplSection) do
1469 var section
= new TplSection.with_title
("intro", "Introduction")
1470 section
.summary_title
= "Introduction"
1471 section
.add_child tpl_mpropdef_article
(mproperty
.intro
)
1472 parent
.add_child section
1475 if concerns
.is_empty
then return
1476 parent
.add_child
new TplArticle.with_content
("Concerns", "Concerns", concerns
.to_tpl
)
1479 var lst
= concerns
.to_a
1480 for mentity
in lst
do
1481 if mentity
isa MProject then
1482 parent
.add_child
new TplSection(mentity
.nitdoc_id
)
1483 else if mentity
isa MGroup then
1484 parent
.add_child
new TplSection(mentity
.nitdoc_id
)
1485 else if mentity
isa MModule then
1486 var ssection
= new TplSection(mentity
.nitdoc_id
)
1487 var title
= new Template
1489 title
.add mentity
.tpl_namespace
1490 ssection
.title
= title
1491 ssection
.summary_title
= "in {mentity.nitdoc_name}"
1494 var mpropdefs
= mmodules2mdefs
[mentity
].to_a
1495 name_sorter
.sort
(mpropdefs
)
1496 for mpropdef
in mpropdefs
do
1497 ssection
.add_child tpl_mpropdef_article
(mpropdef
)
1499 parent
.add_child ssection
1504 redef fun tpl_content
do
1507 tpl_page
.add_section top
1510 private fun sort_by_mmodule
(mpropdefs
: Collection[MPropDef]): Map[MModule, Set[MPropDef]] do
1511 var map
= new HashMap[MModule, Set[MPropDef]]
1512 for mpropdef
in mpropdefs
do
1513 var mmodule
= mpropdef
.mclassdef
.mmodule
1514 if not map
.has_key
(mmodule
) then map
[mmodule
] = new HashSet[MPropDef]
1515 map
[mmodule
].add mpropdef