nitdoc: better display of concerns
[nit.git] / src / doc / doc_model.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 # Nitdoc model template parts generation
16 module doc_model
17
18 import model_utils
19 import modelize_property
20 import markdown
21 import doc_templates
22 import ordered_tree
23
24 redef class MDoc
25 # Comment synopsys HTML escaped
26 fun short_comment: String do return content.first.html_escape
27
28 # Full comment HTML escaped
29 fun full_comment: String do return content.join("\n").html_escape
30
31 # Synopsys in a template
32 fun tpl_short_comment: Streamable do return short_markdown
33
34 # Full comment in a template
35 fun tpl_comment: Streamable do return full_markdown
36 end
37
38 redef class Location
39 # Github url based on this location
40 fun github(gitdir: String): String do
41 var base_dir = getcwd.join_path(gitdir).simplify_path
42 var file_loc = getcwd.join_path(file.filename).simplify_path
43 var gith_loc = file_loc.substring(base_dir.length + 1, file_loc.length)
44 return "{gith_loc}:{line_start},{column_start}--{line_end},{column_end}"
45 end
46 end
47
48 redef class MEntity
49 # HTML Escaped name
50 fun nitdoc_name: String is abstract
51
52 # Used as HTML unique ids
53 fun nitdoc_id: String is abstract
54
55 # URL of this entity Nitdoc page
56 fun nitdoc_url: String is abstract
57
58 # A template link to the mentity `nitdoc_anchor`
59 fun tpl_anchor: TplLink do
60 var tpl = new TplLink("#{nitdoc_id}", nitdoc_name)
61 if mdoc != null then
62 tpl.title = mdoc.short_comment
63 end
64 return tpl
65 end
66
67 # A template link to the mentity `nitdoc_url`
68 fun tpl_link: TplLink do
69 var tpl = new TplLink(nitdoc_url, nitdoc_name)
70 if mdoc != null then
71 tpl.title = mdoc.short_comment
72 end
73 return tpl
74 end
75
76 # A template article that briefly describe the entity
77 fun tpl_short_article: TplArticle do
78 var tpl = tpl_article
79 if mdoc != null then
80 tpl.content = mdoc.tpl_short_comment
81 end
82 return tpl
83 end
84
85 # A template article that describe the entity
86 fun tpl_article: TplArticle do
87 var tpl = new TplArticle.with_title(nitdoc_id, tpl_title)
88 tpl.title_classes.add "signature"
89 tpl.subtitle = tpl_namespace
90 tpl.summary_title = nitdoc_name
91 return tpl
92 end
93
94 # A template signature that contains modifiers and parameters
95 fun tpl_declaration: Template is abstract
96
97 # A template namespace
98 fun tpl_namespace: Template is abstract
99
100 # A template definition of the mentity
101 # include name, sysnopsys, comment and namespace
102 fun tpl_definition: TplDefinition is abstract
103
104 # A li element that can go in a list
105 fun tpl_list_item: TplListItem do
106 var lnk = new Template
107 lnk.add new TplLabel.with_classes(tpl_css_classes)
108 lnk.add tpl_link
109 if mdoc != null then
110 lnk.add ": "
111 lnk.add mdoc.short_comment
112 end
113 return new TplListItem.with_content(lnk)
114 end
115
116 fun tpl_css_classes: Array[String] is abstract
117
118 # Box title for this mentity
119 fun tpl_title: Template do
120 var title = new Template
121 title.add tpl_icon
122 title.add tpl_namespace
123 return title
124 end
125
126 # Icon that will be displayed before the title
127 fun tpl_icon: TplIcon do
128 var icon = new TplIcon.with_icon("tag")
129 icon.css_classes.add_all(tpl_css_classes)
130 return icon
131 end
132 end
133
134 redef class MConcern
135 # Return a li element for `self` that can be displayed in a concern list
136 private fun tpl_concern_item: TplListItem do
137 var lnk = new Template
138 lnk.add tpl_anchor
139 if mdoc != null then
140 lnk.add ": "
141 lnk.add mdoc.short_comment
142 end
143 return new TplListItem.with_content(lnk)
144 end
145 end
146
147 redef class MProject
148 redef fun nitdoc_name do return name.html_escape
149 redef fun nitdoc_id do return nitdoc_name
150 redef fun nitdoc_url do return "project_{name}.html"
151
152 redef fun mdoc do
153 if root != null then
154 return root.mdoc
155 end
156 return super
157 end
158
159 redef fun tpl_declaration do
160 var tpl = new Template
161 tpl.add "<span>project "
162 tpl.add tpl_link
163 tpl.add "</span>"
164 return tpl
165 end
166
167 redef fun tpl_namespace do return tpl_link
168
169 redef fun tpl_definition do
170 var tpl = new TplDefinition
171 if mdoc != null then
172 tpl.comment = mdoc.tpl_comment
173 end
174 return tpl
175 end
176
177 redef fun tpl_css_classes do return ["public"]
178 end
179
180 redef class MGroup
181 redef fun nitdoc_name do return name.html_escape
182
183 redef fun nitdoc_id do
184 if parent != null then
185 return "{parent.nitdoc_id}__{nitdoc_name}"
186 end
187 return "{mproject.nitdoc_id}__{nitdoc_name}"
188 end
189
190 redef fun nitdoc_url do return "group_{name}.html"
191
192 redef fun tpl_namespace do
193 var tpl = new Template
194 if mproject != null then
195 tpl.add mproject.tpl_namespace
196 else if parent != null then
197 tpl.add parent.tpl_namespace
198 end
199 if mproject != null and mproject.root != self then
200 tpl.add "::"
201 tpl.add tpl_link
202 end
203 return tpl
204 end
205
206 redef fun tpl_declaration do
207 var tpl = new Template
208 tpl.add "<span>group "
209 tpl.add tpl_link
210 tpl.add "</span>"
211 return tpl
212 end
213
214 redef fun tpl_definition do
215 var tpl = new TplDefinition
216 if mdoc != null then
217 tpl.comment = mdoc.tpl_comment
218 end
219 return tpl
220 end
221
222 redef fun tpl_css_classes do return ["public"]
223 end
224
225 redef class MModule
226 # Is the mmodule created by nitdoc for internal purpose?
227 var is_fictive: Bool writable = false
228
229 redef fun nitdoc_name do return name.html_escape
230
231 redef fun nitdoc_id do
232 if mgroup != null then
233 return "{mgroup.nitdoc_id}__{nitdoc_name}"
234 end
235 return nitdoc_name
236 end
237
238 redef fun nitdoc_url do
239 var res = new FlatBuffer
240 res.append("module_")
241 var mowner = public_owner
242 if mowner != null then
243 res.append("{public_owner.name}_")
244 end
245 res.append("{self.name}.html")
246 return res.to_s
247 end
248
249 redef fun tpl_declaration do
250 var tpl = new Template
251 tpl.add "<span>module "
252 tpl.add tpl_link
253 tpl.add "</span>"
254 return tpl
255 end
256
257 redef fun tpl_namespace do
258 var tpl = new Template
259 if mgroup != null then
260 tpl.add mgroup.tpl_namespace
261 tpl.add "::"
262 end
263 tpl.add tpl_link
264 return tpl
265 end
266
267 redef fun tpl_definition do
268 var tpl = new TplClassDefinition
269 if mdoc != null then
270 tpl.comment = mdoc.tpl_comment
271 end
272 return tpl
273 end
274
275 redef fun tpl_title do
276 var title = new Template
277 title.add tpl_icon
278 title.add tpl_namespace
279 return title
280 end
281
282 redef fun tpl_css_classes do return ["public"]
283 end
284
285 redef class MClass
286 redef fun nitdoc_name do return name.html_escape
287 redef fun nitdoc_id do return "{intro_mmodule.mgroup.mproject}__{name.to_cmangle}"
288 redef fun nitdoc_url do return "class_{public_owner}_{name}.html"
289
290 redef fun mdoc do return intro.mdoc
291
292 redef fun tpl_declaration do return intro.tpl_declaration
293
294 redef fun tpl_namespace do
295 var tpl = new Template
296 tpl.add intro_mmodule.mgroup.mproject.tpl_namespace
297 tpl.add "::<span>"
298 tpl.add tpl_link
299 tpl.add "</span>"
300 return tpl
301 end
302
303 redef fun tpl_title do
304 var title = new Template
305 title.add tpl_icon
306 title.add tpl_link
307 title.add tpl_signature
308 return title
309 end
310
311 redef fun tpl_icon do return intro.tpl_icon
312
313 fun tpl_signature: Template do
314 var tpl = new Template
315 if arity > 0 then
316 tpl.add "["
317 tpl.add intro.parameter_names.join(", ")
318 tpl.add "]"
319 end
320 return tpl
321 end
322
323 redef fun tpl_article do
324 var tpl = super
325 tpl.summary_title = "{nitdoc_name}{tpl_signature.write_to_string}"
326 return tpl
327 end
328
329 redef fun tpl_css_classes do return intro.tpl_css_classes
330 end
331
332 redef class MClassDef
333 redef fun nitdoc_name do return mclass.nitdoc_name
334 redef fun nitdoc_id do return "{mmodule.nitdoc_id}__{name.to_cmangle}"
335 redef fun nitdoc_url do return "{mclass.nitdoc_url}#{nitdoc_id}"
336
337 redef fun tpl_namespace do
338 var tpl = new Template
339 tpl.add mmodule.tpl_namespace
340 tpl.add "::<span>"
341 tpl.add mclass.tpl_link
342 tpl.add "</span>"
343 return tpl
344 end
345
346 redef fun tpl_article do
347 var tpl = new TplArticle(nitdoc_id)
348 tpl.summary_title = "in {mmodule.nitdoc_name}"
349 tpl.title = tpl_declaration
350 tpl.title_classes.add "signature"
351 var title = new Template
352 title.add "in "
353 title.add mmodule.tpl_namespace
354 tpl.subtitle = title
355 if mdoc != null then
356 tpl.content = mdoc.tpl_comment
357 end
358 return tpl
359 end
360
361 redef fun tpl_title do
362 var title = new Template
363 title.add tpl_icon
364 title.add tpl_link
365 title.add tpl_signature
366 return title
367 end
368
369 redef fun tpl_declaration do
370 var tpl = new Template
371 tpl.add tpl_modifiers
372 tpl.add tpl_link
373 tpl.add tpl_signature
374 return tpl
375 end
376
377 fun tpl_signature: Template do
378 var tpl = new Template
379 if not parameter_names.is_empty then
380 tpl.add "["
381 for i in [0..parameter_names.length[ do
382 tpl.add "{parameter_names[i]}: "
383 tpl.add bound_mtype.arguments[i].tpl_signature
384 if i < parameter_names.length - 1 then tpl.add ", "
385 end
386 tpl.add "]"
387 end
388 return tpl
389 end
390
391 redef fun tpl_definition do
392 var tpl = new TplClassDefinition
393 tpl.namespace = tpl_namespace
394 if mdoc != null then
395 tpl.comment = mdoc.tpl_comment
396 end
397 return tpl
398 end
399
400 redef fun tpl_css_classes do
401 var set = new HashSet[String]
402 if is_intro then set.add "intro"
403 set.add_all mclass.intro.modifiers
404 set.add_all modifiers
405 return set.to_a
406 end
407
408 fun tpl_modifiers: Template do
409 var tpl = new Template
410 for modifier in modifiers do
411 if modifier == "public" then continue
412 tpl.add "{modifier} "
413 end
414 return tpl
415 end
416
417 redef fun tpl_list_item do
418 var lnk = new Template
419 lnk.add new TplLabel.with_classes(tpl_css_classes)
420 lnk.add tpl_link
421 if mdoc != null then
422 lnk.add ": "
423 lnk.add mdoc.short_comment
424 else if mclass.intro.mdoc != null then
425 lnk.add ": "
426 lnk.add mclass.intro.mdoc.short_comment
427 end
428 return new TplListItem.with_content(lnk)
429 end
430
431 redef fun tpl_anchor: TplLink do
432 var tpl = new TplLink("#{nitdoc_id}", nitdoc_name)
433 if mdoc != null then
434 tpl.title = mdoc.short_comment
435 else if mclass.intro.mdoc != null then
436 tpl.title = mclass.intro.mdoc.short_comment
437 end
438 return tpl
439 end
440
441 redef fun tpl_link: TplLink do
442 var tpl = new TplLink(nitdoc_url, nitdoc_name)
443 if mdoc != null then
444 tpl.title = mdoc.short_comment
445 else if mclass.intro.mdoc != null then
446 tpl.title = mclass.intro.mdoc.short_comment
447 end
448 return tpl
449 end
450 end
451
452 redef class MProperty
453 redef fun nitdoc_name do return name.html_escape
454 redef fun nitdoc_id do return "{intro_mclassdef.mclass.nitdoc_id}__{name.to_cmangle}"
455 redef fun nitdoc_url do return "proprety_{nitdoc_id}.html"
456
457 redef fun mdoc do return intro.mdoc
458
459 redef fun tpl_namespace do
460 var tpl = new Template
461 tpl.add intro_mclassdef.mclass.tpl_namespace
462 tpl.add "::<span>"
463 tpl.add intro.tpl_link
464 tpl.add "</span>"
465 return tpl
466 end
467
468 redef fun tpl_declaration do return intro.tpl_declaration
469
470 fun tpl_signature: Template do return new Template
471
472 redef fun tpl_title do return intro.tpl_title
473
474 redef fun tpl_icon do return intro.tpl_icon
475
476 redef fun tpl_css_classes do return intro.tpl_css_classes
477 end
478
479 redef class MPropDef
480 redef fun nitdoc_name do return mproperty.nitdoc_name
481 redef fun nitdoc_id do return "{mclassdef.nitdoc_id}__{name.to_cmangle}"
482 redef fun nitdoc_url do return "{mproperty.nitdoc_url}#{nitdoc_id}"
483
484 redef fun tpl_anchor: TplLink do
485 var tpl = new TplLink("#{nitdoc_id}", nitdoc_name)
486 if mdoc != null then
487 tpl.title = mdoc.short_comment
488 else if mproperty.intro.mdoc != null then
489 tpl.title = mproperty.intro.mdoc.short_comment
490 end
491 return tpl
492 end
493
494 redef fun tpl_link: TplLink do
495 var tpl = new TplLink(nitdoc_url, nitdoc_name)
496 if mdoc != null then
497 tpl.title = mdoc.short_comment
498 else if mproperty.intro.mdoc != null then
499 tpl.title = mproperty.intro.mdoc.short_comment
500 end
501 return tpl
502 end
503
504 redef fun tpl_namespace do
505 var tpl = new Template
506 tpl.add mclassdef.tpl_namespace
507 tpl.add "::"
508 tpl.add mproperty.name
509 return tpl
510 end
511
512 redef fun tpl_article do
513 var tpl = new TplArticle(nitdoc_id)
514 tpl.summary_title = "in {mclassdef.nitdoc_name}"
515 var title = new Template
516 title.add "in "
517 title.add mclassdef.tpl_link
518 tpl.title = title
519 tpl.subtitle = tpl_declaration
520 if mdoc != null then
521 tpl.content = mdoc.tpl_comment
522 end
523 return tpl
524 end
525
526 redef fun tpl_title do
527 var title = new Template
528 title.add tpl_icon
529 title.add tpl_link
530 title.add tpl_signature
531 return title
532 end
533
534 redef fun tpl_definition do
535 var tpl = new TplDefinition
536 tpl.namespace = mclassdef.tpl_namespace
537 if mdoc != null then
538 tpl.comment = mdoc.tpl_comment
539 end
540 return tpl
541 end
542
543 redef fun tpl_declaration do
544 var tpl = new Template
545 tpl.add tpl_modifiers
546 tpl.add tpl_link
547 tpl.add tpl_signature
548 return tpl
549 end
550
551 redef fun tpl_css_classes do
552 var set = new HashSet[String]
553 if is_intro then set.add "intro"
554 set.add_all mproperty.intro.modifiers
555 set.add_all modifiers
556 return set.to_a
557 end
558
559 fun tpl_modifiers: Template do
560 var tpl = new Template
561 for modifier in modifiers do
562 if modifier == "public" then continue
563 tpl.add "{modifier} "
564 end
565 return tpl
566 end
567
568 fun tpl_signature: Template do return new Template
569
570 redef fun tpl_list_item do
571 var lnk = new Template
572 lnk.add new TplLabel.with_classes(tpl_css_classes.to_a)
573 lnk.add tpl_link
574 if mdoc != null then
575 lnk.add ": "
576 lnk.add mdoc.short_comment
577 else if mproperty.intro.mdoc != null then
578 lnk.add ": "
579 lnk.add mproperty.intro.mdoc.short_comment
580 end
581 return new TplListItem.with_content(lnk)
582 end
583 end
584
585 redef class MMethod
586 redef fun tpl_signature do
587 var tpl = new Template
588 var params = new Array[String]
589 for param in intro.msignature.mparameters do
590 params.add param.name
591 end
592 if not params.is_empty then
593 tpl.add "("
594 tpl.add params.join(", ")
595 tpl.add ")"
596 end
597 return tpl
598 end
599 end
600
601 redef class MMethodDef
602 redef fun tpl_signature do return msignature.tpl_signature
603 end
604
605 redef class MVirtualTypeProp
606 redef fun tpl_link do return mvirtualtype.tpl_link
607 redef fun tpl_signature do return tpl_link
608 end
609
610 redef class MVirtualTypeDef
611 redef fun tpl_signature do
612 var tpl = new Template
613 tpl.add ": "
614 tpl.add bound.tpl_signature
615 return tpl
616 end
617 end
618
619 redef class MType
620 fun tpl_signature: Template is abstract
621 end
622
623 redef class MClassType
624 redef fun tpl_link do return mclass.tpl_link
625 redef fun tpl_signature do return tpl_link
626 end
627
628 redef class MNullableType
629 redef fun tpl_signature do
630 var tpl = new Template
631 tpl.add "nullable "
632 tpl.add mtype.tpl_signature
633 return tpl
634 end
635 end
636
637 redef class MGenericType
638 redef fun tpl_signature do
639 var tpl = new Template
640 tpl.add tpl_link
641 tpl.add "["
642 for i in [0..arguments.length[ do
643 tpl.add arguments[i].tpl_signature
644 if i < arguments.length - 1 then tpl.add ", "
645 end
646 tpl.add "]"
647 return tpl
648 end
649 end
650
651 redef class MParameterType
652 redef fun tpl_link do
653 var name = mclass.intro.parameter_names[rank]
654 return new TplLink.with_title("{mclass.nitdoc_url}#FT_{name}", name, "formal type")
655 end
656 redef fun tpl_signature do return tpl_link
657 end
658
659 redef class MVirtualType
660 redef fun tpl_link do return mproperty.intro.tpl_link
661 redef fun tpl_signature do return tpl_link
662 end
663
664 redef class MSignature
665 redef fun tpl_signature do
666 var tpl = new Template
667 if not mparameters.is_empty then
668 tpl.add "("
669 for i in [0..mparameters.length[ do
670 tpl.add mparameters[i].tpl_signature
671 if i < mparameters.length - 1 then tpl.add ", "
672 end
673 tpl.add ")"
674 end
675 if return_mtype != null then
676 tpl.add ": "
677 tpl.add return_mtype.tpl_signature
678 end
679 return tpl
680 end
681 end
682
683 redef class MParameter
684 fun tpl_signature: Template do
685 var tpl = new Template
686 tpl.add "{name}: "
687 tpl.add mtype.tpl_signature
688 if is_vararg then tpl.add "..."
689 return tpl
690 end
691 end
692
693 redef class ConcernsTree
694
695 private var seen = new HashSet[MConcern]
696
697 redef fun add(p, e) do
698 if seen.has(e) then return
699 seen.add e
700 super(p, e)
701 end
702
703 fun to_tpl: TplList do
704 var lst = new TplList.with_classes(["list-unstyled", "list-definition"])
705 for r in roots do
706 var li = r.tpl_concern_item
707 lst.add_li li
708 build_list(r, li)
709 end
710 return lst
711 end
712
713 private fun build_list(e: MConcern, li: TplListItem) do
714 if not sub.has_key(e) then return
715 var subs = sub[e]
716 var lst = new TplList.with_classes(["list-unstyled", "list-definition"])
717 for e2 in subs do
718 if e2 isa MGroup and e2.is_root then
719 build_list(e2, li)
720 else
721 var sli = e2.tpl_concern_item
722 lst.add_li sli
723 build_list(e2, sli)
724 end
725 end
726 li.append lst
727 end
728 end