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 # Composes the DocComposite tree of a DocPage and organizes its content.
21 # StructurePhase populates the DocPage content with section and article.
23 # This phase only applies structure.
24 # The content of the structure is choosen by the rendering phases.
28 # Used to sort ConcernsTree by rank.
29 private var concerns_sorter
= new MConcernRankSorter
31 # Used to sort ConcernsTree by name.
32 private var name_sorter
= new MEntityNameSorter
34 # Populates the given DocModel.
36 for page
in doc
.pages
.values
do page
.apply_structure
(self, doc
)
42 # Populates `self` with structure elements like DocComposite ones.
44 # See `StructurePhase`.
45 fun apply_structure
(v
: StructurePhase, doc
: DocModel) do end
48 redef class OverviewPage
49 redef fun apply_structure
(v
, doc
) do
50 var article
= new HomeArticle("home.article", "Home")
51 root
.add_child article
53 var mpackages
= doc
.model
.mpackages
.to_a
54 var sorter
= new MConcernRankSorter
56 var section
= new DocSection("packages.section", "Packages")
57 for mpackage
in mpackages
do
58 section
.add_child
new DefinitionArticle("{mpackage.nitdoc_id}.definition", null, mpackage
)
60 article
.add_child section
64 redef class SearchPage
65 redef fun apply_structure
(v
, doc
) do
66 var mmodules
= doc
.mmodules
.to_a
67 v
.name_sorter
.sort
(mmodules
)
68 var mclasses
= doc
.mclasses
.to_a
69 v
.name_sorter
.sort
(mclasses
)
70 var mprops
= doc
.mproperties
.to_a
71 v
.name_sorter
.sort
(mprops
)
72 root
.add_child
new IndexArticle("index.article", null, mmodules
, mclasses
, mprops
)
76 redef class MGroupPage
77 redef fun apply_structure
(v
, doc
) do
78 var section
= new MEntitySection("{mentity.nitdoc_name}.section", null, mentity
)
79 root
.add_child section
80 if mentity
.is_root
then
81 section
.add_child
new IntroArticle("{mentity.mpackage.nitdoc_id}.intro", null, mentity
.mpackage
)
83 section
.add_child
new IntroArticle("{mentity.nitdoc_id}.intro", null, mentity
)
85 var concerns
= self.concerns
86 if concerns
== null or concerns
.is_empty
then return
88 mentity
.mpackage
.booster_rank
= -1000
89 mentity
.booster_rank
= -1000
90 concerns
.sort_with
(v
.concerns_sorter
)
91 mentity
.mpackage
.booster_rank
= 0
92 mentity
.booster_rank
= 0
93 section
.add_child
new ConcernsArticle("{mentity.nitdoc_id}.concerns", null, mentity
, concerns
)
94 for mentity
in concerns
do
95 var ssection
= new ConcernSection("{mentity.nitdoc_id}.concern", null, mentity
)
96 if mentity
isa MModule then
97 ssection
.add_child
new DefinitionArticle("{mentity.nitdoc_id}.definition", null, mentity
)
99 section
.add_child ssection
104 redef class MModulePage
105 redef fun apply_structure
(v
, doc
) do
106 var section
= new MEntitySection("{mentity.nitdoc_name}.section", null, mentity
)
107 root
.add_child section
108 section
.add_child
new IntroArticle("{mentity.nitdoc_id}.intro", null, mentity
)
109 var concerns
= self.concerns
110 if concerns
== null or concerns
.is_empty
then return
112 mentity
.mgroup
.mpackage
.booster_rank
= -1000
113 mentity
.mgroup
.booster_rank
= -1000
114 mentity
.booster_rank
= -1000
115 concerns
.sort_with
(v
.concerns_sorter
)
116 mentity
.mgroup
.mpackage
.booster_rank
= 0
117 mentity
.mgroup
.booster_rank
= 0
118 mentity
.booster_rank
= 0
119 section
.add_child
new ConcernsArticle("{mentity.nitdoc_id}.concerns", null, mentity
, concerns
)
121 for mentity
in concerns
do
122 var ssection
= new ConcernSection("{mentity.nitdoc_id}.concern", null, mentity
)
123 if mentity
isa MModule then
124 var mclasses
= mclasses_for_mmodule
(mentity
).to_a
125 v
.name_sorter
.sort
(mclasses
)
126 for mclass
in mclasses
do
127 var article
= new DefinitionListArticle(
128 "{mclass.intro.nitdoc_id}.definition-list", null, mclass
)
129 var mclassdefs
= mclassdefs_for
(mclass
).to_a
130 if not mclassdefs
.has
(mclass
.intro
) then
131 article
.add_child
(new DefinitionArticle(
132 "{mclass.intro.nitdoc_id}.definition", null, mclass
.intro
))
134 doc
.mainmodule
.linearize_mclassdefs
(mclassdefs
)
135 for mclassdef
in mclassdefs
do
136 article
.add_child
(new DefinitionArticle(
137 "{mclassdef.nitdoc_id}.definition", null, mclassdef
))
139 ssection
.add_child article
142 section
.add_child ssection
146 # Filters `self.mclassses` by intro `mmodule`.
147 private fun mclasses_for_mmodule
(mmodule
: MModule): Set[MClass] do
148 var mclasses
= new HashSet[MClass]
149 for mclass
in self.mclasses
do
150 if mclass
.intro_mmodule
== mmodule
then
157 # Filters `self.mclassdefs` by `mclass`.
158 private fun mclassdefs_for
(mclass
: MClass): Set[MClassDef] do
159 var mclassdefs
= new HashSet[MClassDef]
160 for mclassdef
in self.mclassdefs
do
161 if mclassdef
.mclass
== mclass
then
162 mclassdefs
.add mclassdef
169 redef class MClassPage
170 redef fun apply_structure
(v
, doc
) do
171 var section
= new MEntitySection("{mentity.nitdoc_name}.section", null, mentity
)
172 root
.add_child section
173 section
.add_child
new IntroArticle("{mentity.nitdoc_id}.intro", null, mentity
)
174 var concerns
= self.concerns
175 if concerns
== null or concerns
.is_empty
then return
177 mentity
.intro_mmodule
.mgroup
.mpackage
.booster_rank
= -1000
178 mentity
.intro_mmodule
.mgroup
.booster_rank
= -1000
179 mentity
.intro_mmodule
.booster_rank
= -1000
180 concerns
.sort_with
(v
.concerns_sorter
)
181 mentity
.intro_mmodule
.mgroup
.mpackage
.booster_rank
= 0
182 mentity
.intro_mmodule
.mgroup
.booster_rank
= 0
183 mentity
.intro_mmodule
.booster_rank
= 0
184 var constructors
= new DocSection("{mentity.nitdoc_id}.constructors", "Constructors")
185 var minit
= mentity
.root_init
186 if minit
!= null then
187 constructors
.add_child
new DefinitionArticle("{minit.nitdoc_id}.definition", null, minit
)
189 section
.add_child constructors
190 section
.add_child
new ConcernsArticle("{mentity.nitdoc_id}.concerns", null, mentity
, concerns
)
191 for mentity
in concerns
do
192 var ssection
= new ConcernSection("{mentity.nitdoc_id}.concern", null, mentity
)
193 if mentity
isa MModule then
194 var mprops
= mproperties_for
(mentity
)
195 var by_kind
= new PropertiesByKind.with_elements
(mprops
)
196 for group
in by_kind
.groups
do
197 v
.name_sorter
.sort
(group
)
198 for mprop
in group
do
199 for mpropdef
in mpropdefs_for
(mprop
, mentity
) do
200 if mpropdef
isa MMethodDef and mpropdef
.mproperty
.is_init
then
201 if mpropdef
== minit
then continue
202 constructors
.add_child
new DefinitionArticle(
203 "{mpropdef.nitdoc_id}.definition", null, mpropdef
)
205 ssection
.add_child
new DefinitionArticle(
206 "{mpropdef.nitdoc_id}.definition", null, mpropdef
)
212 section
.add_child ssection
216 # Filters `self.mpropdefs` by `mmodule`.
219 private fun mproperties_for
(mmodule
: MModule): Set[MProperty] do
220 var mprops
= new HashSet[MProperty]
221 for mpropdef
in self.mpropdefs
do
222 if mpropdef
.mclassdef
.mmodule
== mmodule
then
223 mprops
.add mpropdef
.mproperty
229 # Filters `self.mpropdefs` by `mproperty`.
232 private fun mpropdefs_for
(mproperty
: MProperty, mmodule
: MModule): Set[MPropDef] do
233 var mpropdefs
= new HashSet[MPropDef]
234 for mpropdef
in self.mpropdefs
do
235 if mpropdef
.mproperty
== mproperty
and
236 mpropdef
.mclassdef
.mmodule
== mmodule
then
237 mpropdefs
.add mpropdef
244 redef class MPropertyPage
245 redef fun apply_structure
(v
, doc
) do
246 var section
= new MEntitySection("{mentity.nitdoc_name}.section", null, mentity
)
247 root
.add_child section
248 section
.add_child
new IntroArticle("{mentity.nitdoc_id}.intro", null, mentity
)
249 var concerns
= self.concerns
250 if concerns
== null or concerns
.is_empty
then return
252 mentity
.intro
.mclassdef
.mmodule
.mgroup
.mpackage
.booster_rank
= -1000
253 mentity
.intro
.mclassdef
.mmodule
.mgroup
.booster_rank
= -1000
254 mentity
.intro
.mclassdef
.mmodule
.booster_rank
= -1000
255 concerns
.sort_with
(v
.concerns_sorter
)
256 mentity
.intro
.mclassdef
.mmodule
.mgroup
.mpackage
.booster_rank
= 0
257 mentity
.intro
.mclassdef
.mmodule
.mgroup
.booster_rank
= 0
258 mentity
.intro
.mclassdef
.mmodule
.booster_rank
= 0
259 section
.add_child
new ConcernsArticle("{mentity.nitdoc_id}.concerns", null, mentity
, concerns
)
260 for mentity
in concerns
do
261 var ssection
= new ConcernSection("{mentity.nitdoc_id}.concern", null, mentity
)
262 if mentity
isa MModule then
264 var mpropdefs
= mpropdefs_for
(mentity
).to_a
265 v
.name_sorter
.sort
(mpropdefs
)
266 for mpropdef
in mpropdefs
do
267 ssection
.add_child
new DefinitionArticle(
268 "{mpropdef.nitdoc_id}.definition", null, mpropdef
)
271 section
.add_child ssection
275 # Filters `self.mpropdefs` by `mmodule`.
276 private fun mpropdefs_for
(mmodule
: MModule): Set[MPropDef] do
277 var mpropdefs
= new HashSet[MPropDef]
278 for mpropdef
in self.mpropdefs
do
279 if mpropdef
.mclassdef
.mmodule
== mmodule
then
280 mpropdefs
.add mpropdef
287 # A group of sections that can be displayed together in a tab.
289 # Display the first child and hide less relevant data in other panels.
294 # A group of sections that can be displayed together in a tab panel.
299 # A DocComposite element about a MEntity.
300 class MEntityComposite
303 redef fun title
do return mentity
.nitdoc_name
305 # MEntity documented by this page element.
309 # A Section about a Concern.
311 # Those sections are used to build the page summary.
313 super MEntityComposite
316 redef fun is_toc_hidden
do return is_hidden
319 # An article about a Mentity.
321 # Used to display textual content about a MEntity.
322 abstract class MEntityArticle
323 super MEntityComposite
327 # An article that displays a list of mentities.
328 class MEntitiesListArticle
331 # MEntities to display.
332 var mentities
: Array[MEntity]
334 redef fun is_hidden
do return mentities
.is_empty
338 # A section about a Mentity.
340 # Used to regroup content about a MEntity.
342 super MEntityComposite
346 # An introduction article about a MEntity.
348 # Used at the top of a documentation page to introduce the documented MEntity.
350 super MEntityComposite
353 redef var is_hidden
= false
354 redef var is_toc_hidden
= true
357 # An article that display a ConcernsTreee as a list.
358 class ConcernsArticle
361 # Concerns to list in this article.
362 var concerns
: ConcernsTree
364 redef fun is_hidden
do return concerns
.is_empty
367 # An article that displays a list of definition belonging to a MEntity.
368 class DefinitionListArticle
373 # An article that display the definition text of a MEntity.
374 class DefinitionArticle
377 redef var is_hidden
= false
380 # The main package article.
385 # An article that display an index of mmodules, mclasses and mproperties.
389 # List of mmodules to display.
390 var mmodules
: Array[MModule]
392 # List of mclasses to display.
393 var mclasses
: Array[MClass]
395 # List of mproperties to display.
396 var mprops
: Array[MProperty]
398 redef fun is_hidden
do
399 return mmodules
.is_empty
and mclasses
.is_empty
and mprops
.is_empty
405 # Sort MConcerns based on the module importation hierarchy ranking
406 # see also: `MConcern::concern_rank` and `MConcern::booster_rank`
408 # Comparison is made with the formula:
411 # a.concern_rank + a.booster_rank <=> b.concern_rank + b.booster_ran
414 # If both `a` and `b` have the same ranking,
415 # ordering is based on lexicographic comparison of `a.name` and `b.name`
416 class MConcernRankSorter
418 redef type COMPARED: MConcern
420 redef fun compare
(a
, b
) do
421 if a
.concern_rank
== b
.concern_rank
then
422 return a
.name
<=> b
.name
424 return a
.concern_rank
+ a
.booster_rank
<=> b
.concern_rank
+ b
.booster_rank
430 # Boost a MConcern rank
431 # see: `MConcernRankSorter`
432 # Use a positive booster to push down a result in the list
433 # A negative booster can be used to push up the result
434 var booster_rank
: Int = 0 is writable
436 # Concern ranking used for ordering
437 # see: `MConcernRankSorter`
438 # Rank can be positive or negative
439 fun concern_rank
: Int is abstract
443 redef var concern_rank
is lazy
do
445 for mgroup
in mgroups
do
446 var mmax
= mgroup
.concern_rank
447 if mmax
> max
then max
= mmax
454 redef var concern_rank
is lazy
do
456 for mmodule
in mmodules
do
457 var mmax
= mmodule
.concern_rank
458 if mmax
> max
then max
= mmax
465 redef var concern_rank
is lazy
do
467 for p
in in_importation
.direct_greaters
do
468 var pmax
= p
.concern_rank
469 if pmax
> max
then max
= pmax