src/doc: change structure so pages can describe multiple mentities
[nit.git] / src / doc / doc_phases / doc_structure.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
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
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
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.
14
15 # Composes the DocComposite tree of a DocPage and organizes its content.
16 module doc_structure
17
18 import doc_concerns
19
20 # StructurePhase populates the DocPage content with section and article.
21 #
22 # This phase only applies structure.
23 # The content of the structure is choosen by the rendering phases.
24 class StructurePhase
25 super DocPhase
26
27 # Used to sort ConcernsTree by rank.
28 private var concerns_sorter = new MConcernRankSorter
29
30 # Used to sort ConcernsTree by name.
31 private var name_sorter = new MEntityNameSorter
32
33 # Populates the given DocModel.
34 redef fun apply do
35 for page in doc.pages do
36 if page isa MEntityPage then page.apply_structure(self, doc)
37 end
38 end
39
40 # TODO index and search page should also be structured here
41 end
42
43 redef class MEntityPage
44
45 # Populates `self` with structure elements like DocComposite ones.
46 #
47 # See `StructurePhase`.
48 fun apply_structure(v: StructurePhase, doc: DocModel) do end
49 end
50
51 redef class MGroupPage
52 redef fun apply_structure(v, doc) do
53 var section = new MEntitySection(mentity)
54 root.add_child section
55 if mentity.is_root then
56 section.add_child new IntroArticle(mentity.mproject)
57 else
58 section.add_child new IntroArticle(mentity)
59 end
60 var concerns = self.concerns
61 if concerns == null or concerns.is_empty then return
62 # FIXME avoid diff
63 mentity.mproject.booster_rank = -1000
64 mentity.booster_rank = -1000
65 concerns.sort_with(v.concerns_sorter)
66 mentity.mproject.booster_rank = 0
67 mentity.booster_rank = 0
68 section.add_child new ConcernsArticle(mentity, concerns)
69 for mentity in concerns do
70 if mentity isa MModule then
71 section.add_child new DefinitionArticle(mentity)
72 else
73 section.add_child new ConcernSection(mentity)
74 end
75 end
76 end
77 end
78
79 redef class MModulePage
80 redef fun apply_structure(v, doc) do
81 var section = new MEntitySection(mentity)
82 root.add_child section
83 section.add_child new IntroArticle(mentity)
84 var concerns = self.concerns
85 if concerns == null or concerns.is_empty then return
86 # FIXME avoid diff
87 mentity.mgroup.mproject.booster_rank = -1000
88 mentity.mgroup.booster_rank = -1000
89 mentity.booster_rank = -1000
90 concerns.sort_with(v.concerns_sorter)
91 mentity.mgroup.mproject.booster_rank = 0
92 mentity.mgroup.booster_rank = 0
93 mentity.booster_rank = 0
94 section.add_child new ConcernsArticle(mentity, concerns)
95 # reference list
96 for mentity in concerns do
97 var ssection = new ConcernSection(mentity)
98 if mentity isa MModule then
99 var mclasses = mclasses_for_mmodule(mentity).to_a
100 v.name_sorter.sort(mclasses)
101 for mclass in mclasses do
102 var article = new DefinitionArticle(mclass)
103 var mclassdefs = mclassdefs_for(mclass).to_a
104 if not mclassdefs.has(mclass.intro) then
105 article.add_child(new DefinitionArticle(mclass.intro))
106 end
107 doc.mainmodule.linearize_mclassdefs(mclassdefs)
108 for mclassdef in mclassdefs do
109 article.add_child(new DefinitionArticle(mclassdef))
110 end
111 ssection.add_child article
112 end
113 end
114 section.add_child ssection
115 end
116 end
117
118 # Filters `self.mclassses` by intro `mmodule`.
119 private fun mclasses_for_mmodule(mmodule: MModule): Set[MClass] do
120 var mclasses = new HashSet[MClass]
121 for mclass in self.mclasses do
122 if mclass.intro.mmodule == mmodule then
123 mclasses.add mclass
124 end
125 end
126 return mclasses
127 end
128
129 # Filters `self.mclassdefs` by `mclass`.
130 private fun mclassdefs_for(mclass: MClass): Set[MClassDef] do
131 var mclassdefs = new HashSet[MClassDef]
132 for mclassdef in self.mclassdefs do
133 if mclassdef.mclass == mclass then
134 mclassdefs.add mclassdef
135 end
136 end
137 return mclassdefs
138 end
139 end
140
141 redef class MClassPage
142 redef fun apply_structure(v, doc) do
143 var section = new MEntitySection(mentity)
144 root.add_child section
145 section.add_child new IntroArticle(mentity)
146 var concerns = self.concerns
147 if concerns == null or concerns.is_empty then return
148 # FIXME diff hack
149 mentity.intro_mmodule.mgroup.mproject.booster_rank = -1000
150 mentity.intro_mmodule.mgroup.booster_rank = -1000
151 mentity.intro_mmodule.booster_rank = -1000
152 concerns.sort_with(v.concerns_sorter)
153 mentity.intro_mmodule.mgroup.mproject.booster_rank = 0
154 mentity.intro_mmodule.mgroup.booster_rank = 0
155 mentity.intro_mmodule.booster_rank = 0
156 section.add_child new ConcernsArticle(mentity, concerns)
157 for mentity in concerns do
158 var ssection = new ConcernSection(mentity)
159 if mentity isa MModule then
160 var mprops = mproperties_for(mentity)
161 var by_kind = new PropertiesByKind.with_elements(mprops)
162 for group in by_kind.groups do
163 v.name_sorter.sort(group)
164 for mprop in group do
165 for mpropdef in mpropdefs_for(mprop, mentity) do
166 ssection.add_child new DefinitionArticle(mpropdef)
167 end
168 end
169 end
170 end
171 section.add_child ssection
172 end
173 end
174
175 # Filters `self.mpropdefs` by `mmodule`.
176 #
177 # FIXME diff hack
178 private fun mproperties_for(mmodule: MModule): Set[MProperty] do
179 var mprops = new HashSet[MProperty]
180 for mpropdef in self.mpropdefs do
181 if mpropdef.mclassdef.mmodule == mmodule then
182 mprops.add mpropdef.mproperty
183 end
184 end
185 return mprops
186 end
187
188 # Filters `self.mpropdefs` by `mproperty`.
189 #
190 # FIXME diff hack
191 private fun mpropdefs_for(mproperty: MProperty, mmodule: MModule): Set[MPropDef] do
192 var mpropdefs = new HashSet[MPropDef]
193 for mpropdef in self.mpropdefs do
194 if mpropdef.mproperty == mproperty and
195 mpropdef.mclassdef.mmodule == mmodule then
196 mpropdefs.add mpropdef
197 end
198 end
199 return mpropdefs
200 end
201 end
202
203 redef class MPropertyPage
204 redef fun apply_structure(v, doc) do
205 var section = new MEntitySection(mentity)
206 root.add_child section
207 section.add_child new IntroArticle(mentity)
208 var concerns = self.concerns
209 if concerns == null or concerns.is_empty then return
210 # FIXME diff hack
211 mentity.intro.mclassdef.mmodule.mgroup.mproject.booster_rank = -1000
212 mentity.intro.mclassdef.mmodule.mgroup.booster_rank = -1000
213 mentity.intro.mclassdef.mmodule.booster_rank = -1000
214 concerns.sort_with(v.concerns_sorter)
215 mentity.intro.mclassdef.mmodule.mgroup.mproject.booster_rank = 0
216 mentity.intro.mclassdef.mmodule.mgroup.booster_rank = 0
217 mentity.intro.mclassdef.mmodule.booster_rank = 0
218 section.add_child new ConcernsArticle(mentity, concerns)
219 for mentity in concerns do
220 var ssection = new ConcernSection(mentity)
221 if mentity isa MModule then
222 # Add mproperties
223 var mpropdefs = mpropdefs_for(mentity).to_a
224 v.name_sorter.sort(mpropdefs)
225 for mpropdef in mpropdefs do
226 ssection.add_child new DefinitionArticle(mpropdef)
227 end
228 end
229 section.add_child ssection
230 end
231 end
232
233 # Filters `self.mpropdefs` by `mmodule`.
234 private fun mpropdefs_for(mmodule: MModule): Set[MPropDef] do
235 var mpropdefs = new HashSet[MPropDef]
236 for mpropdef in self.mpropdefs do
237 if mpropdef.mclassdef.mmodule == mmodule then
238 mpropdefs.add mpropdef
239 end
240 end
241 return mpropdefs
242 end
243 end
244
245 # A DocComposite element about a MEntity.
246 class MEntityComposite
247 super DocComposite
248
249 # MEntity documented by this page element.
250 var mentity: MEntity
251 end
252
253 # A Section about a Concern.
254 #
255 # Those sections are used to build the page summary.
256 class ConcernSection
257 super MEntityComposite
258 super DocSection
259 end
260
261 # An article about a Mentity.
262 #
263 # Used to display textual content about a MEntity.
264 abstract class MEntityArticle
265 super MEntityComposite
266 super DocArticle
267 end
268
269 # A section about a Mentity.
270 #
271 # Used to regroup content about a MEntity.
272 class MEntitySection
273 super MEntityComposite
274 super DocSection
275 end
276
277 # An introduction article about a MEntity.
278 #
279 # Used at the top of a documentation page to introduce the documented MEntity.
280 class IntroArticle
281 super MEntityComposite
282 super DocArticle
283 end
284
285 # An article that display a ConcernsTreee as a list.
286 class ConcernsArticle
287 super MEntityArticle
288
289 # Concerns to list in this article.
290 var concerns: ConcernsTree
291 end
292
293 # An article that display the definition text of a MEntity.
294 class DefinitionArticle
295 super MEntityArticle
296 end