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
90 var mainmodule
: MModule
93 init(ctx
: ToolContext, model
: Model, mainmodule
: MModule) do
96 self.mainmodule
= mainmodule
110 private fun init_output_dir
do
111 # create destination dir if it's necessary
112 var output_dir
= ctx
.output_dir
113 if not output_dir
.file_exists
then output_dir
.mkdir
115 var sharedir
= ctx
.opt_sharedir
.value
116 if sharedir
== null then
117 var dir
= ctx
.nit_dir
119 print
"Error: Cannot locate nitdoc share files. Uses --sharedir or envvar NIT_DIR"
122 sharedir
= "{dir}/share/nitdoc"
123 if not sharedir
.file_exists
then
124 print
"Error: Cannot locate nitdoc share files. Uses --sharedir or envvar NIT_DIR"
129 if ctx
.opt_shareurl
.value
== null then
130 sys
.system
("cp -r {sharedir.to_s}/* {output_dir.to_s}/")
132 sys
.system
("cp -r {sharedir.to_s}/resources/ {output_dir.to_s}/resources/")
137 private fun overview
do
138 var page
= new NitdocOverview(ctx
, model
, mainmodule
)
139 page
.render
.write_to_file
("{ctx.output_dir.to_s}/{page.page_url}")
142 private fun search
do
143 var page
= new NitdocSearch(ctx
, model
, mainmodule
)
144 page
.render
.write_to_file
("{ctx.output_dir.to_s}/{page.page_url}")
147 private fun groups
do
148 for mproject
in model
.mprojects
do
149 for mgroup
in mproject
.mgroups
.to_a
do
150 var page
= new NitdocGroup(ctx
, model
, mainmodule
, mgroup
)
151 page
.render
.write_to_file
("{ctx.output_dir.to_s}/{page.page_url}")
156 private fun modules
do
157 for mmodule
in model
.mmodules
do
158 if mmodule
.is_fictive
then continue
159 var page
= new NitdocModule(ctx
, model
, mainmodule
, mmodule
)
160 page
.render
.write_to_file
("{ctx.output_dir.to_s}/{page.page_url}")
164 private fun classes
do
165 for mclass
in model
.mclasses
do
166 if mclass
.visibility
<= ctx
.min_visibility
then continue
167 var page
= new NitdocClass(ctx
, model
, mainmodule
, mclass
)
168 page
.render
.write_to_file
("{ctx.output_dir.to_s}/{page.page_url}")
172 private fun properties
do
173 for mproperty
in model
.mproperties
do
174 if mproperty
.visibility
<= ctx
.min_visibility
then continue
175 var page
= new NitdocProperty(ctx
, model
, mainmodule
, mproperty
)
176 page
.render
.write_to_file
("{ctx.output_dir.to_s}/{page.page_url}")
180 private fun quicksearch_list
do
181 var quicksearch
= new QuickSearch(ctx
, model
)
182 quicksearch
.render
.write_to_file
("{ctx.output_dir.to_s}/quicksearch-list.js")
186 # Nitdoc QuickSearch list generator
188 # Create a JSON object containing links to:
192 # All entities are grouped by name to make the research easier.
195 private var mmodules
= new HashSet[MModule]
196 private var mclasses
= new HashSet[MClass]
197 private var mpropdefs
= new HashMap[String, Set[MPropDef]]
199 init(ctx
: ToolContext, model
: Model) do
200 for mmodule
in model
.mmodules
do
201 if mmodule
.is_fictive
then continue
204 for mclass
in model
.mclasses
do
205 if mclass
.visibility
< ctx
.min_visibility
then continue
208 for mproperty
in model
.mproperties
do
209 if mproperty
.visibility
< ctx
.min_visibility
then continue
210 if mproperty
isa MAttribute then continue
211 if not mpropdefs
.has_key
(mproperty
.name
) then
212 mpropdefs
[mproperty
.name
] = new HashSet[MPropDef]
214 mpropdefs
[mproperty
.name
].add_all
(mproperty
.mpropdefs
)
218 fun render
: Template do
219 var tpl
= new Template
220 tpl
.add
"var nitdocQuickSearchRawList=\{ "
221 for mmodule
in mmodules
do
222 tpl
.add
"\"{mmodule.name}\
":["
223 tpl
.add
"\{txt:\"{mmodule.full_name}\",url
:\
"{mmodule.nitdoc_url}\"\
},"
226 for mclass in mclasses do
227 var full_name = mclass.intro.mmodule.full_name
228 tpl.add "\
"{mclass.name}\":["
229 tpl.add "\
{txt:\"{full_name}\
",url:\"{mclass.nitdoc_url}\
"\},"
232 for mproperty
, mprops
in mpropdefs
do
233 tpl
.add
"\"{mproperty}\
":["
234 for mpropdef
in mprops
do
235 var full_name
= mpropdef
.mclassdef
.mclass
.full_name
236 var cls_url
= mpropdef
.mclassdef
.mclass
.nitdoc_url
237 var def_url
= "{cls_url}#{mpropdef.mproperty.nitdoc_id}"
238 tpl
.add
"\{txt:\"{full_name}\",url
:\
"{def_url}\"\
},"
248 # Define page structure and properties
249 abstract class NitdocPage
251 private var ctx: ToolContext
252 private var model: Model
253 private var mainmodule: MModule
254 private var name_sorter = new MEntityNameSorter
256 init(ctx: ToolContext, model: Model, mainmodule: MModule) do
259 self.mainmodule = mainmodule
262 # Render the page as a html template
263 fun render: Template do
265 if ctx.opt_shareurl.value != null then
266 shareurl = ctx.opt_shareurl.value.as(not null)
271 tpl.title = tpl_title
273 tpl.shareurl = shareurl
274 tpl.topmenu = tpl_topmenu
276 tpl.footer = ctx.opt_custom_footer.value
277 tpl.body_attrs.add(new TagAttribute("data-bootstrap-share
", shareurl))
278 tpl.sidebar = tpl_sidebar
281 var tracker_url = ctx.opt_piwik_tracker.value
282 var site_id = ctx.opt_piwik_site_id.value
283 if tracker_url != null and site_id != null then
284 tpl.scripts.add new TplPiwikScript(tracker_url, site_id)
290 fun page_url: String is abstract
292 # Build page template
293 fun tpl_page: TplPage is abstract
295 # Build page sidebar if any
296 fun tpl_sidebar: nullable TplSidebar do return null
298 # Build page title string
299 fun tpl_title: String do
300 if ctx.opt_custom_title.value != null then
301 return ctx.opt_custom_title.value.to_s
306 # Build top menu template
307 fun tpl_topmenu: TplTopMenu do
308 var topmenu = new TplTopMenu(page_url)
309 var brand = ctx.opt_custom_brand.value
310 if brand != null then
311 var tpl = new Template
312 tpl.add "<span
class='navbar-brand'>"
317 topmenu.add_link new TplLink("index
.html
", "Overview")
318 topmenu.add_link new TplLink("search
.html
", "Index")
322 # Build page content template
323 fun tpl_content is abstract
325 # Clickable graphviz image using dot format
326 # return null if no graph for this page
327 fun tpl_graph(dot: FlatBuffer, name: String, title: nullable String): nullable TplArticle do
328 if ctx.opt_nodot.value then return null
329 var output_dir = ctx.output_dir
330 var file = new OFStream.open("{output_dir}/{name}.dot
")
333 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
; \
}")
334 var fmap = new IFStream.open("{output_dir}/{name}.map
")
335 var map = fmap.read_all
338 var article = new TplArticle("graph
")
340 if title != null then
341 article.title = title
342 alt = "alt
='{title}'"
344 article.css_classes.add "text-center
"
345 var content = new Template
346 content.add "<img src
='{name}.png' usemap
='#{name}' style
='margin:auto' {alt}/>"
348 article.content = content
352 # A (source) link template for a given location
353 fun tpl_showsource(location: nullable Location): nullable String
355 if location == null then return null
356 var source = ctx.opt_source.value
357 if source == null then
358 var url = location.file.filename.simplify_path
359 return "<a target
='_blank' title
='Show source' href
=\
"{url}\">View Source</a
>"
361 # THIS IS JUST UGLY ! (but there is no replace yet)
362 var x = source.split_with("%f
")
363 source = x.join(location.file.filename.simplify_path)
364 x = source.split_with("%l
")
365 source = x.join(location.line_start.to_s)
366 x = source.split_with("%L
")
367 source = x.join(location.line_end.to_s)
368 source = source.simplify_path
369 return "<a target
='_blank' title
='Show source' href
=\
"{source.to_s}\">View Source</a
>"
372 # MProject description template
373 fun tpl_mproject_article(mproject: MProject): TplArticle do
374 var article = mproject.tpl_article
375 article.subtitle = mproject.tpl_declaration
376 article.content = mproject.tpl_definition
377 if mproject.mdoc != null then
378 article.content = mproject.mdoc.tpl_short_comment
383 # MGroup description template
384 fun tpl_mgroup_article(mgroup: MGroup): TplArticle do
385 var article = mgroup.tpl_article
386 article.subtitle = mgroup.tpl_declaration
387 article.content = mgroup.tpl_definition
391 # MModule description template
392 fun tpl_mmodule_article(mmodule: MModule): TplArticle do
393 var article = mmodule.tpl_article
394 article.subtitle = mmodule.tpl_declaration
395 article.content = mmodule.tpl_definition
397 var intros = mmodule.intro_mclassdefs(ctx.min_visibility).to_a
398 if not intros.is_empty then
399 mainmodule.linearize_mclassdefs(intros)
400 var intros_art = new TplArticle.with_title("{mmodule.nitdoc_id}_intros
", "Introduces")
401 var intros_lst = new TplList.with_classes(["list-unstyled
", "list-labeled
"])
402 for mclassdef in intros do
403 intros_lst.add_li mclassdef.tpl_list_item
405 if not intros_lst.is_empty then
406 intros_art.content = intros_lst
407 article.add_child intros_art
410 var redefs = mmodule.redef_mclassdefs(ctx.min_visibility).to_a
411 if not redefs.is_empty then
412 mainmodule.linearize_mclassdefs(redefs)
413 var redefs_art = new TplArticle.with_title("{mmodule.nitdoc_id}_redefs
", "Redefines")
414 var redefs_lst = new TplList.with_classes(["list-unstyled
", "list-labeled
"])
415 for mclassdef in redefs do
416 redefs_lst.add_li mclassdef.tpl_list_item
418 if not redefs_lst.is_empty then
419 redefs_art.content = redefs_lst
420 article.add_child redefs_art
426 # MClassDef description template
427 fun tpl_mclass_article(mclass: MClass, mclassdefs: Array[MClassDef]): TplArticle do
428 var article = mclass.tpl_article
429 if not mclassdefs.has(mclass.intro) then
431 var intro_article = mclass.intro.tpl_short_article
432 intro_article.source_link = tpl_showsource(mclass.intro.location)
433 article.add_child intro_article
435 mainmodule.linearize_mclassdefs(mclassdefs)
436 for mclassdef in mclassdefs do
437 # add mclassdef full description
438 var redef_article = mclassdef.tpl_article
439 redef_article.source_link = tpl_showsource(mclassdef.location)
440 article.add_child redef_article
442 var intros = new TplArticle.with_title("{mclassdef.nitdoc_id}_intros
", "Introduces")
443 var intros_lst = new TplList.with_classes(["list-unstyled
", "list-labeled
"])
444 for mpropdef in mclassdef.collect_intro_mpropdefs(ctx.min_visibility) do
445 intros_lst.add_li mpropdef.tpl_list_item
447 if not intros_lst.is_empty then
448 intros.content = intros_lst
449 redef_article.add_child intros
451 var redefs = new TplArticle.with_title("{mclassdef.nitdoc_id}_redefs
", "Redefines")
452 var redefs_lst = new TplList.with_classes(["list-unstyled
", "list-labeled
"])
453 for mpropdef in mclassdef.collect_redef_mpropdefs(ctx.min_visibility) do
454 redefs_lst.add_li mpropdef.tpl_list_item
456 if not redefs_lst.is_empty then
457 redefs.content = redefs_lst
458 redef_article.add_child redefs
464 # MClassDef description template
465 fun tpl_mclassdef_article(mclassdef: MClassDef): TplArticle do
466 var article = mclassdef.tpl_article
467 if mclassdef.is_intro then article.content = null
468 article.source_link = tpl_showsource(mclassdef.location)
472 # MProp description template
474 # `main_mpropdef`: The most important mpropdef to display
475 # `local_mpropdefs`: List of other locally defined mpropdefs to display
476 # `lin`: full linearization from local_mpropdefs to intro (displayed in redef tree)
477 fun tpl_mprop_article(main_mpropdef: MPropDef, local_mpropdefs: Array[MPropDef],
478 lin: Array[MPropDef]): TplArticle do
479 var mprop = main_mpropdef.mproperty
480 var article = new TplArticle(mprop.nitdoc_id)
481 var title = new Template
482 title.add mprop.tpl_icon
483 title.add "<span id
='{main_mpropdef.nitdoc_id}'></span
>"
484 if main_mpropdef.is_intro then
485 title.add mprop.tpl_link
486 title.add mprop.intro.tpl_signature
488 var cls_url = mprop.intro.mclassdef.mclass.nitdoc_url
489 var def_url = "{cls_url}#{mprop.nitdoc_id}"
490 var lnk
= new TplLink.with_title
(def_url
, mprop
.name
, "Go to introduction")
494 article
.title
= title
495 article
.title_classes
.add
"signature"
496 article
.summary_title
= "{mprop.nitdoc_name}"
497 article
.subtitle
= main_mpropdef
.tpl_namespace
498 if main_mpropdef
.mdoc
!= null then
499 article
.content
= main_mpropdef
.mdoc
.tpl_comment
501 var subarticle
= new TplArticle("{main_mpropdef.nitdoc_id}_redefs")
502 # Add redef in same `MClass`
503 if local_mpropdefs
.length
> 1 then
504 for mpropdef
in local_mpropdefs
do
505 if mpropdef
== main_mpropdef
then continue
506 var redef_article
= new TplArticle("{mpropdef.nitdoc_id}")
507 var redef_title
= new Template
508 redef_title
.add
"also redef in "
509 redef_title
.add mpropdef
.tpl_namespace
510 redef_article
.title
= redef_title
511 redef_article
.title_classes
.add
"signature info"
512 redef_article
.css_classes
.add
"nospace"
513 var redef_content
= new Template
514 if mpropdef
.mdoc
!= null then
515 redef_content
.add mpropdef
.mdoc
.tpl_comment
517 redef_article
.content
= redef_content
518 subarticle
.add_child redef_article
522 if lin
.length
> 1 then
523 var lin_article
= new TplArticle("{main_mpropdef.nitdoc_id}_lin")
524 lin_article
.title
= "Inheritance"
525 var lst
= new TplList.with_classes
(["list-unstyled", "list-labeled"])
526 for mpropdef
in lin
do
527 lst
.add_li mpropdef
.tpl_inheritance_item
529 lin_article
.content
= lst
530 subarticle
.add_child lin_article
532 article
.add_child subarticle
536 # MProperty description template
537 fun tpl_mpropdef_article
(mpropdef
: MPropDef): TplArticle do
538 var article
= mpropdef
.tpl_article
539 article
.source_link
= tpl_showsource
(mpropdef
.location
)
545 # Display a list of modules contained in program
549 private var page
= new TplPage
550 redef fun tpl_page
do return page
552 private var sidebar
= new TplSidebar
553 redef fun tpl_sidebar
do return sidebar
555 redef fun tpl_title
do
556 if ctx
.opt_custom_title
.value
!= null then
557 return ctx
.opt_custom_title
.value
.to_s
563 redef fun page_url
do return "index.html"
566 private fun tpl_intro
: TplSection do
567 var section
= new TplSection.with_title
("overview", tpl_title
)
568 var article
= new TplArticle("intro")
569 if ctx
.opt_custom_intro
.value
!= null then
570 article
.content
= ctx
.opt_custom_intro
.value
.to_s
572 section
.add_child article
577 private fun tpl_projects
(section
: TplSection) do
579 var mprojects
= model
.mprojects
.to_a
580 var sorter
= new MConcernRankSorter
581 sorter
.sort mprojects
582 var ssection
= new TplSection.with_title
("projects", "Projects")
583 for mproject
in mprojects
do
584 ssection
.add_child tpl_mproject_article
(mproject
)
586 section
.add_child ssection
589 redef fun tpl_content
do
592 tpl_page
.add_section top
597 # Display a list of modules, classes and properties
601 private var page
= new TplPage
602 redef fun tpl_page
do return page
604 redef fun tpl_title
do return "Index"
606 redef fun page_url
do return "search.html"
608 redef fun tpl_content
do
609 var tpl
= new TplSearchPage("search_all")
610 var section
= new TplSection("search")
614 for mmodule
in modules_list
do
615 tpl
.modules
.add mmodule
.tpl_link
618 for mclass
in classes_list
do
619 tpl
.classes
.add mclass
.tpl_link
622 for mproperty
in mprops_list
do
624 m
.add mproperty
.intro
.tpl_link
626 m
.add mproperty
.intro
.mclassdef
.mclass
.tpl_link
630 section
.add_child tpl
631 tpl_page
.add_section section
634 # Extract mmodule list to display (sorted by name)
635 private fun modules_list
: Array[MModule] do
636 var sorted
= new Array[MModule]
637 for mmodule
in model
.mmodule_importation_hierarchy
do
638 if mmodule
.is_fictive
then continue
641 name_sorter
.sort
(sorted
)
645 # Extract mclass list to display (sorted by name)
646 private fun classes_list
: Array[MClass] do
647 var sorted
= new Array[MClass]
648 for mclass
in model
.mclasses
do
649 if mclass
.visibility
< ctx
.min_visibility
then continue
652 name_sorter
.sort
(sorted
)
656 # Extract mproperty list to display (sorted by name)
657 private fun mprops_list
: Array[MProperty] do
658 var sorted
= new Array[MProperty]
659 for mproperty
in model
.mproperties
do
660 if mproperty
.visibility
< ctx
.min_visibility
then continue
661 if mproperty
isa MAttribute then continue
664 name_sorter
.sort
(sorted
)
670 # Display a flattened view of the group
674 private var mgroup
: MGroup
676 private var concerns
: ConcernsTree
677 private var intros
: Set[MClass]
678 private var redefs
: Set[MClass]
680 init(ctx
: ToolContext, model
: Model, mainmodule
: MModule, mgroup
: MGroup) do
683 self.concerns
= model
.concerns_tree
(mgroup
.collect_mmodules
)
684 self.concerns
.sort_with
(new MConcernRankSorter)
685 self.intros
= mgroup
.in_nesting_intro_mclasses
(ctx
.min_visibility
)
686 var redefs
= new HashSet[MClass]
687 for rdef
in mgroup
.in_nesting_redef_mclasses
(ctx
.min_visibility
) do
688 if intros
.has
(rdef
) then continue
694 private var page
= new TplPage
695 redef fun tpl_page
do return page
697 private var sidebar
= new TplSidebar
698 redef fun tpl_sidebar
do return sidebar
700 redef fun tpl_title
do return mgroup
.nitdoc_name
702 redef fun page_url
do return mgroup
.nitdoc_url
704 redef fun tpl_topmenu
do
706 var mproject
= mgroup
.mproject
707 if not mgroup
.is_root
then
708 topmenu
.add_link
new TplLink(mproject
.nitdoc_url
, mproject
.nitdoc_name
)
710 topmenu
.add_link
new TplLink(page_url
, mproject
.nitdoc_name
)
714 # Class list to display in sidebar
715 fun tpl_sidebar_mclasses
do
716 var mclasses
= new HashSet[MClass]
717 mclasses
.add_all intros
718 mclasses
.add_all redefs
719 if mclasses
.is_empty
then return
720 var list
= new TplList.with_classes
(["list-unstyled", "list-labeled"])
722 var sorted
= mclasses
.to_a
723 name_sorter
.sort
(sorted
)
724 for mclass
in sorted
do
725 list
.add_li tpl_sidebar_item
(mclass
)
727 tpl_sidebar
.boxes
.add
new TplSideBox.with_content
("All classes", list
)
730 private fun tpl_sidebar_item
(def
: MClass): TplListItem do
731 var classes
= def
.intro
.tpl_css_classes
.to_a
732 if intros
.has
(def
) then
737 var lnk
= new Template
738 lnk
.add
new TplLabel.with_classes
(classes
)
740 return new TplListItem.with_content
(lnk
)
744 private fun tpl_intro
: TplSection do
745 var section
= new TplSection.with_title
("top", tpl_title
)
746 var article
= new TplArticle("intro")
748 if mgroup
.is_root
then
749 section
.subtitle
= mgroup
.mproject
.tpl_declaration
750 article
.content
= mgroup
.mproject
.tpl_definition
752 section
.subtitle
= mgroup
.tpl_declaration
753 article
.content
= mgroup
.tpl_definition
755 section
.add_child article
759 private fun tpl_concerns
(section
: TplSection) do
760 if concerns
.is_empty
then return
761 section
.add_child
new TplArticle.with_content
("concerns", "Concerns", concerns
.to_tpl
)
764 private fun tpl_groups
(parent
: TplSection) do
765 var lst
= concerns
.to_a
767 for mentity
in lst
do
768 if mentity
isa MProject then
769 section
.add_child
new TplSection(mentity
.nitdoc_id
)
770 else if mentity
isa MGroup then
771 section
.add_child
new TplSection(mentity
.nitdoc_id
)
772 else if mentity
isa MModule then
773 section
.add_child tpl_mmodule_article
(mentity
)
778 redef fun tpl_content
do
783 tpl_page
.add_section top
786 private fun sort_by_mclass
(mclassdefs
: Collection[MClassDef]): Map[MClass, Set[MClassDef]] do
787 var map
= new HashMap[MClass, Set[MClassDef]]
788 for mclassdef
in mclassdefs
do
789 var mclass
= mclassdef
.mclass
790 if not map
.has_key
(mclass
) then map
[mclass
] = new HashSet[MClassDef]
791 map
[mclass
].add mclassdef
798 # Display the list of introduced and redefined classes in module
802 private var mmodule
: MModule
803 private var concerns
: ConcernsTree
804 private var mclasses2mdefs
: Map[MClass, Set[MClassDef]]
805 private var mmodules2mclasses
: Map[MModule, Set[MClass]]
808 init(ctx
: ToolContext, model
: Model, mainmodule
: MModule, mmodule
: MModule) do
810 self.mmodule
= mmodule
811 var mclassdefs
= new HashSet[MClassDef]
812 mclassdefs
.add_all mmodule
.intro_mclassdefs
(ctx
.min_visibility
)
813 mclassdefs
.add_all mmodule
.redef_mclassdefs
(ctx
.min_visibility
)
814 self.mclasses2mdefs
= sort_by_mclass
(mclassdefs
)
815 self.mmodules2mclasses
= group_by_mmodule
(mclasses2mdefs
.keys
)
816 self.concerns
= model
.concerns_tree
(mmodules2mclasses
.keys
)
818 mmodule
.mgroup
.mproject
.booster_rank
= -1000
819 mmodule
.mgroup
.booster_rank
= -1000
820 mmodule
.booster_rank
= -1000
821 self.concerns
.sort_with
(new MConcernRankSorter)
822 mmodule
.mgroup
.mproject
.booster_rank
= 0
823 mmodule
.mgroup
.booster_rank
= 0
824 mmodule
.booster_rank
= 0
827 private var page
= new TplPage
828 redef fun tpl_page
do return page
830 private var sidebar
= new TplSidebar
831 redef fun tpl_sidebar
do return sidebar
833 redef fun tpl_title
do return mmodule
.nitdoc_name
834 redef fun page_url
do return mmodule
.nitdoc_url
836 redef fun tpl_topmenu
do
838 var mproject
= mmodule
.mgroup
.mproject
839 topmenu
.add_link
new TplLink(mproject
.nitdoc_url
, mproject
.nitdoc_name
)
840 topmenu
.add_link
new TplLink(page_url
, mmodule
.nitdoc_name
)
844 # Class list to display in sidebar
845 fun tpl_sidebar_mclasses
do
846 var mclasses
= new HashSet[MClass]
847 mclasses
.add_all mmodule
.filter_intro_mclasses
(ctx
.min_visibility
)
848 mclasses
.add_all mmodule
.filter_redef_mclasses
(ctx
.min_visibility
)
849 if mclasses
.is_empty
then return
850 var list
= new TplList.with_classes
(["list-unstyled", "list-labeled"])
852 var sorted
= mclasses
.to_a
853 name_sorter
.sort
(sorted
)
854 for mclass
in sorted
do
855 list
.add_li tpl_sidebar_item
(mclass
)
857 tpl_sidebar
.boxes
.add
new TplSideBox.with_content
("All classes", list
)
860 private fun tpl_sidebar_item
(def
: MClass): TplListItem do
861 var classes
= def
.intro
.tpl_css_classes
.to_a
862 if def
.intro_mmodule
== mmodule
then
867 var lnk
= new Template
868 lnk
.add
new TplLabel.with_classes
(classes
)
870 return new TplListItem.with_content
(lnk
)
874 private fun tpl_intro
: TplSection do
875 var section
= new TplSection.with_title
("top", tpl_title
)
876 section
.subtitle
= mmodule
.tpl_declaration
878 var article
= new TplArticle("intro")
879 var def
= mmodule
.tpl_definition
880 var location
= mmodule
.location
881 article
.source_link
= tpl_showsource
(location
)
882 article
.content
= def
883 section
.add_child article
887 # inheritance section
888 private fun tpl_inheritance
(parent
: TplSection) do
889 # Extract relevent modules
890 var imports
= mmodule
.in_importation
.greaters
891 if imports
.length
> 10 then imports
= mmodule
.in_importation
.direct_greaters
892 var clients
= mmodule
.in_importation
.smallers
893 if clients
.length
> 10 then clients
= mmodule
.in_importation
.direct_smallers
896 var section
= new TplSection.with_title
("dependencies", "Dependencies")
899 var mmodules
= new HashSet[MModule]
900 mmodules
.add_all mmodule
.in_nesting
.direct_greaters
901 mmodules
.add_all imports
902 if clients
.length
< 10 then mmodules
.add_all clients
904 var graph
= tpl_dot
(mmodules
)
905 if graph
!= null then section
.add_child graph
908 var lst
= new Array[MModule]
909 for dep
in imports
do
910 if dep
.is_fictive
then continue
911 if dep
== mmodule
then continue
914 if not lst
.is_empty
then
916 section
.add_child tpl_list
("imports", "Imports", lst
)
920 lst
= new Array[MModule]
921 for dep
in clients
do
922 if dep
.is_fictive
then continue
923 if dep
== mmodule
then continue
926 if not lst
.is_empty
then
928 section
.add_child tpl_list
("clients", "Clients", lst
)
931 parent
.add_child section
934 private fun tpl_list
(id
: String, title
: String, mmodules
: Array[MModule]): TplArticle do
935 var article
= new TplArticle.with_title
(id
, title
)
936 var list
= new TplList.with_classes
(["list-unstyled", "list-definition"])
937 for mmodule
in mmodules
do list
.elts
.add mmodule
.tpl_list_item
938 article
.content
= list
942 private fun tpl_concerns
(parent
: TplSection) do
943 if concerns
.is_empty
then return
944 parent
.add_child
new TplArticle.with_content
("concerns", "Concerns", concerns
.to_tpl
)
947 private fun tpl_mclasses
(parent
: TplSection) do
948 for mentity
in concerns
do
949 if mentity
isa MProject then
950 parent
.add_child
new TplSection(mentity
.nitdoc_id
)
951 else if mentity
isa MGroup then
952 parent
.add_child
new TplSection(mentity
.nitdoc_id
)
953 else if mentity
isa MModule then
954 var section
= new TplSection(mentity
.nitdoc_id
)
955 var title
= new Template
956 if mentity
== mmodule
then
958 section
.summary_title
= "in {mentity.nitdoc_name}"
961 section
.summary_title
= "from {mentity.nitdoc_name}"
963 title
.add mentity
.tpl_namespace
964 section
.title
= title
966 var mclasses
= mmodules2mclasses
[mentity
].to_a
967 name_sorter
.sort
(mclasses
)
968 for mclass
in mclasses
do
969 section
.add_child tpl_mclass_article
(mclass
, mclasses2mdefs
[mclass
].to_a
)
971 parent
.add_child section
976 private fun group_by_mmodule
(mclasses
: Collection[MClass]): Map[MModule, Set[MClass]] do
977 var res
= new HashMap[MModule, Set[MClass]]
978 for mclass
in mclasses
do
979 var mmodule
= mclass
.intro_mmodule
980 if not res
.has_key
(mmodule
) then
981 res
[mmodule
] = new HashSet[MClass]
983 res
[mmodule
].add
(mclass
)
988 redef fun tpl_content
do
994 tpl_page
.add_section top
997 # Genrate dot hierarchy for class inheritance
998 fun tpl_dot
(mmodules
: Collection[MModule]): nullable TplArticle do
999 var poset
= new POSet[MModule]
1000 for mmodule
in mmodules
do
1001 if mmodule
.is_fictive
then continue
1002 poset
.add_node mmodule
1003 for omodule
in mmodules
do
1004 if mmodule
.is_fictive
then continue
1005 poset
.add_node mmodule
1006 if mmodule
.in_importation
< omodule
then
1007 poset
.add_edge
(mmodule
, omodule
)
1012 var op
= new FlatBuffer
1013 var name
= "dep_{mmodule.name}"
1014 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")
1015 for mmodule
in poset
do
1016 if mmodule
== self.mmodule
then
1017 op
.append
("\"{mmodule.name}\
"[shape=box,margin=0.03];\n")
1019 op
.append
("\"{mmodule.name}\
"[URL=\"{mmodule.nitdoc_url}\
"];\n")
1021 for omodule
in poset
[mmodule
].direct_greaters
do
1022 op
.append
("\"{mmodule.name}\
"->\"{omodule.name}\
";\n")
1026 return tpl_graph
(op
, name
, null)
1029 private fun sort_by_mclass
(mclassdefs
: Collection[MClassDef]): Map[MClass, Set[MClassDef]] do
1030 var map
= new HashMap[MClass, Set[MClassDef]]
1031 for mclassdef
in mclassdefs
do
1032 var mclass
= mclassdef
.mclass
1033 if not map
.has_key
(mclass
) then map
[mclass
] = new HashSet[MClassDef]
1034 map
[mclass
].add mclassdef
1041 # Display a list properties defined or redefined for this class
1045 private var mclass
: MClass
1046 private var concerns
: ConcernsTree
1047 private var mprops2mdefs
: Map[MProperty, Set[MPropDef]]
1048 private var mmodules2mprops
: Map[MModule, Set[MProperty]]
1050 init(ctx
: ToolContext, model
: Model, mainmodule
: MModule, mclass
: MClass) do
1052 self.mclass
= mclass
1053 var mpropdefs
= new HashSet[MPropDef]
1054 mpropdefs
.add_all mclass
.intro_mpropdefs
(ctx
.min_visibility
)
1055 mpropdefs
.add_all mclass
.redef_mpropdefs
(ctx
.min_visibility
)
1056 self.mprops2mdefs
= sort_by_mproperty
(mpropdefs
)
1057 self.mmodules2mprops
= sort_by_mmodule
(mprops2mdefs
.keys
)
1058 self.concerns
= model
.concerns_tree
(mmodules2mprops
.keys
)
1059 self.concerns
.sort_with
(new MConcernRankSorter)
1062 private var page
= new TplPage
1063 redef fun tpl_page
do return page
1065 private var sidebar
= new TplSidebar
1066 redef fun tpl_sidebar
do return sidebar
1068 redef fun tpl_title
do return "{mclass.nitdoc_name}{mclass.tpl_signature.write_to_string}"
1069 redef fun page_url
do return mclass
.nitdoc_url
1071 redef fun tpl_topmenu
do
1073 var mproject
= mclass
.intro_mmodule
.mgroup
.mproject
1074 topmenu
.add_link
new TplLink("{mproject.nitdoc_url}", "{mproject.nitdoc_name}")
1075 topmenu
.add_link
new TplLink(page_url
, mclass
.nitdoc_name
)
1079 # Property list to display in sidebar
1080 fun tpl_sidebar_properties
do
1081 var kind_map
= sort_by_kind
(mclass_inherited_mprops
)
1082 var summary
= new TplList.with_classes
(["list-unstyled"])
1084 tpl_sidebar_list
("Virtual types", kind_map
["type"].to_a
, summary
)
1085 tpl_sidebar_list
("Constructors", kind_map
["init"].to_a
, summary
)
1086 tpl_sidebar_list
("Methods", kind_map
["fun"].to_a
, summary
)
1087 tpl_sidebar
.boxes
.add
new TplSideBox.with_content
("All properties", summary
)
1090 private fun tpl_sidebar_list
(name
: String, mprops
: Array[MProperty], summary
: TplList) do
1091 if mprops
.is_empty
then return
1092 name_sorter
.sort
(mprops
)
1093 var entry
= new TplListItem.with_content
(name
)
1094 var list
= new TplList.with_classes
(["list-unstyled", "list-labeled"])
1095 for mprop
in mprops
do
1096 list
.add_li tpl_sidebar_item
(mprop
)
1099 summary
.elts
.add entry
1102 private fun tpl_sidebar_item
(mprop
: MProperty): TplListItem do
1103 var classes
= mprop
.intro
.tpl_css_classes
.to_a
1104 if not mprops2mdefs
.has_key
(mprop
) then
1105 classes
.add
"inherit"
1106 var cls_url
= mprop
.intro
.mclassdef
.mclass
.nitdoc_url
1107 var def_url
= "{cls_url}#{mprop.nitdoc_id}"
1108 var lnk
= new TplLink(def_url
, mprop
.name
)
1109 if mprop
.intro
.mdoc
!= null then lnk
.title
= mprop
.intro
.mdoc
.short_comment
1110 var item
= new Template
1111 item
.add
new TplLabel.with_classes
(classes
)
1113 return new TplListItem.with_content
(item
)
1115 var defs
= mprops2mdefs
[mprop
]
1116 if defs
.has
(mprop
.intro
) then
1121 var lnk
= new Template
1122 lnk
.add
new TplLabel.with_classes
(classes
)
1123 lnk
.add mprop
.tpl_anchor
1124 return new TplListItem.with_content
(lnk
)
1127 private fun tpl_intro
: TplSection do
1128 var section
= new TplSection.with_title
("top", tpl_title
)
1129 section
.subtitle
= mclass
.intro
.tpl_declaration
1130 var article
= new TplArticle("comment")
1131 if mclass
.mdoc
!= null then
1132 article
.content
= mclass
.mdoc
.tpl_comment
1134 section
.add_child article
1138 private fun tpl_concerns
(parent
: TplSection) do
1140 var section
= new TplSection.with_title
("intro", "Introduction")
1141 section
.summary_title
= "Introduction"
1142 section
.add_child tpl_mclassdef_article
(mclass
.intro
)
1143 parent
.add_child section
1145 if concerns
.is_empty
then return
1146 parent
.add_child
new TplArticle.with_content
("concerns", "Concerns", concerns
.to_tpl
)
1149 private fun tpl_inheritance
(parent
: TplSection) do
1151 var hparents
= new HashSet[MClass]
1152 for c
in mclass
.in_hierarchy
(mainmodule
).direct_greaters
do
1153 if c
.visibility
< ctx
.min_visibility
then continue
1158 var hancestors
= new HashSet[MClass]
1159 for c
in mclass
.in_hierarchy
(mainmodule
).greaters
do
1160 if c
== mclass
then continue
1161 if c
.visibility
< ctx
.min_visibility
then continue
1162 if hparents
.has
(c
) then continue
1167 var hchildren
= new HashSet[MClass]
1168 for c
in mclass
.in_hierarchy
(mainmodule
).direct_smallers
do
1169 if c
.visibility
< ctx
.min_visibility
then continue
1174 var hdescendants
= new HashSet[MClass]
1175 for c
in mclass
.in_hierarchy
(mainmodule
).smallers
do
1176 if c
== mclass
then continue
1177 if c
.visibility
< ctx
.min_visibility
then continue
1178 if hchildren
.has
(c
) then continue
1183 var section
= new TplSection.with_title
("inheritance", "Inheritance")
1186 var mclasses
= new HashSet[MClass]
1187 mclasses
.add_all hancestors
1188 mclasses
.add_all hparents
1189 mclasses
.add_all hchildren
1190 mclasses
.add_all hdescendants
1192 var graph
= tpl_dot
(mclasses
)
1193 if graph
!= null then section
.add_child graph
1196 if not hparents
.is_empty
then
1197 var lst
= hparents
.to_a
1198 name_sorter
.sort lst
1199 section
.add_child tpl_list
("parents", "Parents", lst
)
1203 if not hancestors
.is_empty
then
1204 var lst
= hancestors
.to_a
1205 name_sorter
.sort lst
1206 section
.add_child tpl_list
("ancestors", "Ancestors", lst
)
1210 if not hchildren
.is_empty
then
1211 var lst
= hchildren
.to_a
1212 name_sorter
.sort lst
1213 section
.add_child tpl_list
("children", "Children", lst
)
1217 if not hdescendants
.is_empty
then
1218 var lst
= hdescendants
.to_a
1219 name_sorter
.sort lst
1220 section
.add_child tpl_list
("descendants", "Descendants", lst
)
1223 parent
.add_child section
1226 private fun tpl_list
(id
: String, title
: String, elts
: Array[MClass]): TplArticle do
1227 var article
= new TplArticle.with_title
(id
, title
)
1228 if elts
.length
> 20 then
1229 var tpl
= new Template
1232 if e
!= elts
.last
then tpl
.add
", "
1234 article
.content
= tpl
1236 var list
= new TplList.with_classes
(["list-unstyled", "list-definition"])
1237 for elt
in elts
do list
.elts
.add elt
.tpl_list_item
1238 article
.content
= list
1243 private fun tpl_properties
(parent
: TplSection) do
1244 var lst
= concerns
.to_a
1245 for mentity
in lst
do
1246 if mentity
isa MProject then
1247 parent
.add_child
new TplSection(mentity
.nitdoc_id
)
1248 else if mentity
isa MGroup then
1249 parent
.add_child
new TplSection(mentity
.nitdoc_id
)
1250 else if mentity
isa MModule then
1251 var section
= new TplSection(mentity
.nitdoc_id
)
1252 var title
= new Template
1254 title
.add mentity
.tpl_namespace
1255 section
.title
= title
1256 section
.summary_title
= "in {mentity.nitdoc_name}"
1259 var mprops
= mmodules2mprops
[mentity
]
1260 var kind_map
= sort_by_kind
(mprops
)
1263 for article
in tpl_mproperty_articles
(kind_map
, "type") do
1264 section
.add_child article
1267 for article
in tpl_mproperty_articles
(kind_map
, "init") do
1268 section
.add_child article
1271 for article
in tpl_mproperty_articles
(kind_map
, "fun") do
1272 section
.add_child article
1274 parent
.add_child section
1279 private fun tpl_mproperty_articles
(kind_map
: Map[String, Set[MProperty]],
1280 kind_name
: String): Sequence[TplArticle] do
1281 var articles
= new List[TplArticle]
1282 var elts
= kind_map
[kind_name
].to_a
1283 name_sorter
.sort
(elts
)
1285 var local_defs
= mprops2mdefs
[elt
]
1286 # var all_defs = elt.mpropdefs
1287 var all_defs
= new HashSet[MPropDef]
1288 for local_def
in local_defs
do
1289 all_defs
.add local_def
1290 var mpropdef
= local_def
1291 while not mpropdef
.is_intro
do
1292 mpropdef
= mpropdef
.lookup_next_definition
(mainmodule
, mpropdef
.mclassdef
.bound_mtype
)
1293 all_defs
.add mpropdef
1296 var loc_lin
= local_defs
.to_a
1297 mainmodule
.linearize_mpropdefs
(loc_lin
)
1298 var all_lin
= all_defs
.to_a
1299 mainmodule
.linearize_mpropdefs
(all_lin
)
1300 articles
.add tpl_mprop_article
(loc_lin
.first
, loc_lin
, all_lin
)
1305 redef fun tpl_content
do
1306 tpl_sidebar_properties
1308 tpl_inheritance
(top
)
1311 tpl_page
.add_section top
1314 private fun sort_by_mproperty
(mpropdefs
: Collection[MPropDef]): Map[MProperty, Set[MPropDef]] do
1315 var map
= new HashMap[MProperty, Set[MPropDef]]
1316 for mpropdef
in mpropdefs
do
1317 var mproperty
= mpropdef
.mproperty
1318 if not map
.has_key
(mproperty
) then map
[mproperty
] = new HashSet[MPropDef]
1319 map
[mproperty
].add mpropdef
1324 private fun sort_by_mmodule
(mprops
: Collection[MProperty]): Map[MModule, Set[MProperty]] do
1325 var map
= new HashMap[MModule, Set[MProperty]]
1326 for mprop
in mprops
do
1327 var mpropdefs
= mprops2mdefs
[mprop
].to_a
1328 mainmodule
.linearize_mpropdefs
(mpropdefs
)
1329 var mmodule
= mpropdefs
.first
.mclassdef
.mmodule
1330 if not map
.has_key
(mmodule
) then map
[mmodule
] = new HashSet[MProperty]
1331 map
[mmodule
].add mprop
1336 private fun sort_by_kind
(mprops
: Collection[MProperty]): Map[String, Set[MProperty]] do
1337 var map
= new HashMap[String, Set[MProperty]]
1338 map
["type"] = new HashSet[MProperty]
1339 map
["init"] = new HashSet[MProperty]
1340 map
["fun"] = new HashSet[MProperty]
1341 for mprop
in mprops
do
1342 if mprop
isa MVirtualTypeProp then
1343 map
["type"].add mprop
1344 else if mprop
isa MMethod then
1345 if mprop
.is_init
then
1346 map
["init"].add mprop
1348 map
["fun"].add mprop
1355 private fun mclass_inherited_mprops
: Set[MProperty] do
1356 var res
= new HashSet[MProperty]
1357 var local
= mclass
.local_mproperties
(ctx
.min_visibility
)
1358 for mprop
in mclass
.inherited_mproperties
(mainmodule
, ctx
.min_visibility
) do
1359 if local
.has
(mprop
) then continue
1360 #if mprop isa MMethod and mprop.is_init then continue
1361 if mprop
.intro
.mclassdef
.mclass
.name
== "Object" and
1362 (mprop
.visibility
== protected_visibility
or
1363 mprop
.intro
.mclassdef
.mmodule
.name
!= "kernel") then continue
1370 private fun collect_mmodules
(mprops
: Collection[MProperty]): Set[MModule] do
1371 var res
= new HashSet[MModule]
1372 for mprop
in mprops
do
1373 if mprops2mdefs
.has_key
(mprop
) then
1374 for mpropdef
in mprops2mdefs
[mprop
] do res
.add mpropdef
.mclassdef
.mmodule
1380 # Generate dot hierarchy for classes
1381 fun tpl_dot
(mclasses
: Collection[MClass]): nullable TplArticle do
1382 var poset
= new POSet[MClass]
1384 for mclass
in mclasses
do
1385 poset
.add_node mclass
1386 for oclass
in mclasses
do
1387 if mclass
== oclass
then continue
1388 poset
.add_node oclass
1389 if mclass
.in_hierarchy
(mainmodule
) < oclass
then
1390 poset
.add_edge
(mclass
, oclass
)
1395 var op
= new FlatBuffer
1396 var name
= "dep_{mclass.name}"
1397 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")
1398 var classes
= poset
.to_a
1399 var todo
= new Array[MClass]
1400 var done
= new HashSet[MClass]
1401 mainmodule
.linearize_mclasses
(classes
)
1402 if not classes
.is_empty
then todo
.add classes
.first
1403 while not todo
.is_empty
do
1405 if done
.has
(c
) then continue
1408 op
.append
("\"{c.name}\
"[shape=box,margin=0.03];\n")
1410 op
.append
("\"{c.name}\
"[URL=\"{c.nitdoc_url}\
"];\n")
1412 var smallers
= poset
[c
].direct_smallers
1413 if smallers
.length
< 10 then
1414 for c2
in smallers
do
1415 op
.append
("\"{c2.name}\
"->\"{c.name}\
";\n")
1417 todo
.add_all smallers
1419 op
.append
("\"...\
"->\"{c.name}\
";\n")
1423 return tpl_graph
(op
, name
, null)
1428 class NitdocProperty
1431 private var mproperty
: MProperty
1432 private var concerns
: ConcernsTree
1433 private var mmodules2mdefs
: Map[MModule, Set[MPropDef]]
1435 init(ctx
: ToolContext, model
: Model, mainmodule
: MModule, mproperty
: MProperty) do
1437 self.mproperty
= mproperty
1438 self.mmodules2mdefs
= sort_by_mmodule
(collect_mpropdefs
)
1439 self.concerns
= model
.concerns_tree
(mmodules2mdefs
.keys
)
1440 self.concerns
.sort_with
(new MConcernRankSorter)
1443 private fun collect_mpropdefs
: Set[MPropDef] do
1444 var res
= new HashSet[MPropDef]
1445 for mpropdef
in mproperty
.mpropdefs
do
1446 if not mpropdef
.is_intro
then res
.add mpropdef
1451 private var page
= new TplPage
1452 redef fun tpl_page
do return page
1454 private var sidebar
= new TplSidebar
1455 redef fun tpl_sidebar
do return sidebar
1457 redef fun tpl_title
do
1458 return "{mproperty.nitdoc_name}{mproperty.tpl_signature.write_to_string}"
1461 redef fun page_url
do return mproperty
.nitdoc_url
1463 redef fun tpl_topmenu
do
1465 var mmodule
= mproperty
.intro_mclassdef
.mmodule
1466 var mproject
= mmodule
.mgroup
.mproject
1467 var mclass
= mproperty
.intro_mclassdef
.mclass
1468 topmenu
.add_link
new TplLink("{mproject.nitdoc_url}", "{mproject.nitdoc_name}")
1469 topmenu
.add_link
new TplLink("{mclass.nitdoc_url}", "{mclass.nitdoc_name}")
1470 topmenu
.add_link
new TplLink(page_url
, mproperty
.nitdoc_name
)
1474 private fun tpl_intro
: TplSection do
1475 var title
= new Template
1476 title
.add mproperty
.nitdoc_name
1477 title
.add mproperty
.intro
.tpl_signature
1478 var section
= new TplSection.with_title
("top", title
)
1479 section
.subtitle
= mproperty
.tpl_namespace
1480 section
.summary_title
= mproperty
.nitdoc_name
1484 private fun tpl_properties
(parent
: TplSection) do
1486 var section
= new TplSection.with_title
("intro", "Introduction")
1487 section
.summary_title
= "Introduction"
1488 section
.add_child tpl_mpropdef_article
(mproperty
.intro
)
1489 parent
.add_child section
1492 if concerns
.is_empty
then return
1493 parent
.add_child
new TplArticle.with_content
("Concerns", "Concerns", concerns
.to_tpl
)
1496 var lst
= concerns
.to_a
1497 for mentity
in lst
do
1498 if mentity
isa MProject then
1499 parent
.add_child
new TplSection(mentity
.nitdoc_id
)
1500 else if mentity
isa MGroup then
1501 parent
.add_child
new TplSection(mentity
.nitdoc_id
)
1502 else if mentity
isa MModule then
1503 var ssection
= new TplSection(mentity
.nitdoc_id
)
1504 var title
= new Template
1506 title
.add mentity
.tpl_namespace
1507 ssection
.title
= title
1508 ssection
.summary_title
= "in {mentity.nitdoc_name}"
1511 var mpropdefs
= mmodules2mdefs
[mentity
].to_a
1512 name_sorter
.sort
(mpropdefs
)
1513 for mpropdef
in mpropdefs
do
1514 ssection
.add_child tpl_mpropdef_article
(mpropdef
)
1516 parent
.add_child ssection
1521 redef fun tpl_content
do
1524 tpl_page
.add_section top
1527 private fun sort_by_mmodule
(mpropdefs
: Collection[MPropDef]): Map[MModule, Set[MPropDef]] do
1528 var map
= new HashMap[MModule, Set[MPropDef]]
1529 for mpropdef
in mpropdefs
do
1530 var mmodule
= mpropdef
.mclassdef
.mmodule
1531 if not map
.has_key
(mmodule
) then map
[mmodule
] = new HashSet[MPropDef]
1532 map
[mmodule
].add mpropdef