model: remove `new_msignature` and special call as the new signature is the method...
[nit.git] / src / web / model_html.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 # Translate mentities to html blocks.
16 module model_html
17
18 import model
19 import doc::doc_down
20 import html::bootstrap
21
22 redef class MEntity
23
24 # Returns the MEntity name escaped for html.
25 #
26 # * MPackage: `foo`
27 # * MGroup: `foo`
28 # * MModule: `foo`
29 # * MClass: `Foo[E]`
30 # * MClassDef: `Foo[E]`
31 # * MProperty: `foo(e)`
32 # * MPropdef: `foo(e)`
33 var html_name: String is lazy do return name.html_escape
34
35 # MEntity namespace escaped for html.
36 fun html_raw_namespace: String is abstract
37
38 # Link to MEntity in the web server.
39 # TODO this should be parameterizable... but how?
40 fun html_link: Link do return new Link("/doc/{html_raw_namespace}", html_name)
41
42 # Returns the list of keyword used in `self` declaration.
43 fun html_modifiers: Array[String] is abstract
44
45 # Returns the complete MEntity declaration decorated with HTML.
46 #
47 # * MPackage: `package foo`
48 # * MGroup: `group foo`
49 # * MModule: `module foo`
50 # * MClass: `private abstract class Foo[E: Object]`
51 # * MClassDef: `redef class Foo[E]`
52 # * MProperty: `private fun foo(e: Object): Int`
53 # * MPropdef: `redef fun foo(e)`
54 fun html_declaration: Template do
55 var tpl = new Template
56 tpl.add "<span>"
57 tpl.add html_modifiers.join(" ")
58 tpl.add " "
59 tpl.add html_link
60 tpl.add "</span>"
61 return tpl
62 end
63
64 # Returns `self` namespace decorated with HTML links.
65 #
66 # * MPackage: `mpackage`
67 # * MGroup: `mpackage(::group)`
68 # * MModule: `mgroup::mmodule`
69 # * MClass: `mpackage::mclass`
70 # * MClassDef: `mmodule::mclassdef`
71 # * MProperty: `mclass::mprop`
72 # * MPropdef: `mclassdef:mpropdef`
73 fun html_namespace: Template is abstract
74
75 # Returns the synopsis and the comment of this MEntity formatted as HTML.
76 var html_documentation: nullable Writable is lazy do
77 var mdoc = mdoc_or_fallback
78 if mdoc == null then return null
79 return mdoc.html_documentation
80 end
81
82 # Returns the synopsis of this MEntity formatted as HTML.
83 var html_synopsis: nullable Writable is lazy do
84 var mdoc = mdoc_or_fallback
85 if mdoc == null then return null
86 return mdoc.html_synopsis
87 end
88
89 # Returns the the comment without the synopsis formatted as HTML.
90 var html_comment: nullable Writable is lazy do
91 var mdoc = mdoc_or_fallback
92 if mdoc == null then return null
93 return mdoc.html_comment
94 end
95
96 # Icon that will be displayed before the title
97 fun html_icon: BSIcon do
98 var icon = new BSIcon("tag")
99 icon.css_classes.add_all(css_classes)
100 return icon
101 end
102
103 # CSS classes used to decorate `self`.
104 #
105 # Mainly used for icons.
106 var css_classes = new Array[String]
107 end
108
109 redef class MPackage
110 redef fun html_raw_namespace do return html_name
111
112 redef var html_modifiers = ["package"]
113 redef fun html_namespace do return html_link
114 redef var css_classes = ["public"]
115 end
116
117 redef class MGroup
118 redef fun html_raw_namespace do
119 var parent = self.parent
120 if parent != null then
121 return "{parent.html_raw_namespace}::{html_name}"
122 end
123 return "{mpackage.html_raw_namespace}::{html_name}"
124 end
125
126 redef var html_modifiers = ["group"]
127
128 # Depends if `self` is root or not.
129 #
130 # * If root `mpackage`.
131 # * Else `mpackage::self`.
132 redef fun html_namespace do
133 var tpl = new Template
134 tpl.add mpackage.html_namespace
135 if mpackage.root != self then
136 tpl.add "::"
137 tpl.add html_link
138 end
139 return tpl
140 end
141
142 redef var css_classes = ["public"]
143 end
144
145 redef class MModule
146
147 redef var html_modifiers = ["module"]
148
149 # Depends if `self` belongs to a MGroup.
150 #
151 # * If mgroup `mgroup::self`.
152 # * Else `self`.
153 redef fun html_namespace do
154 var mgroup = self.mgroup
155 var tpl = new Template
156 if mgroup != null then
157 tpl.add mgroup.html_namespace
158 tpl.add "::"
159 end
160 tpl.add html_link
161 return tpl
162 end
163
164 redef fun html_raw_namespace do
165 var mpackage = self.mpackage
166 var mgroup = self.mgroup
167 if mgroup != null then
168 return "{mgroup.html_raw_namespace}::{html_name}"
169 else if mpackage != null then
170 return "{mpackage.html_raw_namespace}::{html_name}"
171 end
172 return html_name
173 end
174
175 redef var css_classes = ["public"]
176 end
177
178 redef class MClass
179 redef fun mdoc_or_fallback do return intro.mdoc
180
181 # Format: `Foo[E]`
182 redef var html_name is lazy do
183 var tpl = new Template
184 tpl.add name.html_escape
185 if arity > 0 then
186 tpl.add "["
187 var parameter_names = new Array[String]
188 for p in mparameters do
189 parameter_names.add(p.html_name)
190 end
191 tpl.add parameter_names.join(", ")
192 tpl.add "]"
193 end
194 return tpl.write_to_string
195 end
196
197 redef fun html_modifiers do return intro.html_modifiers
198 redef fun html_declaration do return intro.html_declaration
199
200 # Returns `mpackage::self`.
201 redef fun html_namespace do
202 var mgroup = intro_mmodule.mgroup
203 var tpl = new Template
204 if mgroup != null then
205 tpl.add mgroup.mpackage.html_namespace
206 tpl.add "::"
207 end
208 tpl.add "<span>"
209 tpl.add html_link
210 tpl.add "</span>"
211 return tpl
212 end
213
214 redef fun html_raw_namespace do return intro.html_raw_namespace
215
216 # Returns `intro.html_short_signature`.
217 fun html_short_signature: Template do return intro.html_short_signature
218
219 # Returns `intro.html_signature`.
220 fun html_signature: Template do return intro.html_signature
221
222 redef fun html_icon do return intro.html_icon
223 redef fun css_classes do return intro.css_classes
224 end
225
226 redef class MClassDef
227 redef fun html_raw_namespace do return "{mmodule.html_raw_namespace}::{html_name}"
228
229 redef fun mdoc_or_fallback do return mdoc or else mclass.mdoc_or_fallback
230
231 # Depends if `self` is an intro or not.
232 #
233 # * If intro contains the visibility and kind.
234 # * If redef contains the `redef` keyword and kind.
235 redef fun html_modifiers do
236 var res = new Array[String]
237 if not is_intro then
238 res.add "redef"
239 else
240 if mclass.visibility != public_visibility then
241 res.add mclass.visibility.to_s
242 end
243 end
244 res.add mclass.kind.to_s
245 return res
246 end
247
248 # Depends if `self` is an intro or not.
249 #
250 # For intro: `private abstract class Foo[E: Object]`
251 # For redef: `redef class Foo[E]`
252 redef fun html_declaration do
253 var tpl = new Template
254 tpl.add "<span>"
255 tpl.add html_modifiers.join(" ")
256 tpl.add " "
257 tpl.add html_link
258 if is_intro then
259 tpl.add html_signature
260 else
261 tpl.add html_short_signature
262 end
263 tpl.add "</span>"
264 return tpl
265 end
266
267 # Returns `mmodule::self`
268 redef fun html_namespace do
269 var tpl = new Template
270 tpl.add mmodule.html_namespace
271 tpl.add "::<span>"
272 tpl.add mclass.html_link
273 tpl.add "</span>"
274 return tpl
275 end
276
277 # Returns the MClassDef generic signature without static bounds.
278 fun html_short_signature: Template do
279 var tpl = new Template
280 var mparameters = mclass.mparameters
281 if not mparameters.is_empty then
282 tpl.add "["
283 for i in [0..mparameters.length[ do
284 tpl.add mparameters[i].html_name
285 if i < mparameters.length - 1 then tpl.add ", "
286 end
287 tpl.add "]"
288 end
289 return tpl
290 end
291
292 # Returns the MClassDef generic signature with static bounds.
293 fun html_signature: Template do
294 var tpl = new Template
295 var mparameters = mclass.mparameters
296 if not mparameters.is_empty then
297 tpl.add "["
298 for i in [0..mparameters.length[ do
299 tpl.add "{mparameters[i].html_name}: "
300 tpl.add bound_mtype.arguments[i].html_signature
301 if i < mparameters.length - 1 then tpl.add ", "
302 end
303 tpl.add "]"
304 end
305 return tpl
306 end
307
308 redef fun css_classes do
309 var set = new HashSet[String]
310 if is_intro then set.add "intro"
311 for m in mclass.intro.modifiers do set.add m.to_cmangle
312 for m in modifiers do set.add m.to_cmangle
313 return set.to_a
314 end
315
316
317 # List of all modifiers like redef, private etc.
318 var modifiers: Array[String] is lazy do
319 var res = new Array[String]
320 if not is_intro then
321 res.add "redef"
322 else
323 res.add mclass.visibility.to_s
324 end
325 res.add mclass.kind.to_s
326 return res
327 end
328 end
329
330 redef class MProperty
331 redef fun mdoc_or_fallback do return intro.mdoc
332 redef fun html_modifiers do return intro.html_modifiers
333 redef fun html_declaration do return intro.html_declaration
334
335 # Returns `mclass::self`.
336 redef fun html_namespace do
337 var tpl = new Template
338 tpl.add intro_mclassdef.mclass.html_namespace
339 tpl.add "::<span>"
340 tpl.add intro.html_link
341 tpl.add "</span>"
342 return tpl
343 end
344
345 redef fun html_raw_namespace do return intro.html_raw_namespace
346
347 # Returns `intro.html_short_signature`.
348 fun html_short_signature: Template do return intro.html_short_signature
349
350 # Returns `intro.html_signature`.
351 fun html_signature: Template do return intro.html_signature
352
353 redef fun css_classes do return intro.css_classes
354 end
355
356 redef class MPropDef
357 redef fun html_raw_namespace do return "{mclassdef.html_raw_namespace}::{html_name}"
358 redef fun mdoc_or_fallback do return mdoc or else mproperty.mdoc_or_fallback
359
360 # Depends if `self` is an intro or not.
361 #
362 # * If intro contains the visibility and kind.
363 # * If redef contains the `redef` keyword and kind.
364 redef fun html_modifiers do
365 var res = new Array[String]
366 if not is_intro then
367 res.add "redef"
368 else
369 if mproperty.visibility != public_visibility then
370 res.add mproperty.visibility.to_s
371 end
372 end
373 return res
374 end
375
376 # Depends if `self` is an intro or not.
377 #
378 # For intro: `private fun foo(e: Object): Bar is abstract`
379 # For redef: `redef fun foo(e) is cached`
380 redef fun html_declaration do
381 var tpl = new Template
382 tpl.add "<span>"
383 tpl.add html_modifiers.join(" ")
384 tpl.add " "
385 if is_intro then
386 tpl.add html_link
387 tpl.add html_signature
388 else
389 tpl.add mproperty.intro.html_link
390 tpl.add html_short_signature
391 end
392 tpl.add "</span>"
393 return tpl
394 end
395
396 # Returns `mclassdef::self`
397 redef fun html_namespace do
398 var tpl = new Template
399 tpl.add mclassdef.html_namespace
400 tpl.add "::"
401 tpl.add html_link
402 return tpl
403 end
404
405 # Returns the MPropdDef signature without static types.
406 fun html_short_signature: Template is abstract
407
408 # Returns the MPropDef signature with static types.
409 fun html_signature: Template is abstract
410
411 redef fun css_classes do
412 var set = new HashSet[String]
413 if is_intro then set.add "intro"
414 for m in mproperty.intro.modifiers do set.add m.to_cmangle
415 for m in modifiers do set.add m.to_cmangle
416 return set.to_a
417 end
418
419 # List of all modifiers like redef, private, abstract, intern, fun etc.
420 var modifiers: Array[String] is lazy do
421 var res = new Array[String]
422 if not is_intro then
423 res.add "redef"
424 else
425 res.add mproperty.visibility.to_s
426 end
427 var mprop = self
428 if mprop isa MVirtualTypeDef then
429 res.add "type"
430 else if mprop isa MMethodDef then
431 if mprop.is_abstract then
432 res.add "abstract"
433 else if mprop.is_intern then
434 res.add "intern"
435 end
436 if mprop.mproperty.is_init then
437 res.add "init"
438 else
439 res.add "fun"
440 end
441 end
442 return res
443 end
444 end
445
446 redef class MAttributeDef
447
448 redef fun html_modifiers do
449 var res = super
450 res.add "var"
451 return res
452 end
453
454 redef fun html_short_signature do return new Template
455
456 redef fun html_signature do
457 var static_mtype = self.static_mtype
458 var tpl = new Template
459 if static_mtype != null then
460 tpl.add ": "
461 tpl.add static_mtype.html_signature
462 end
463 return tpl
464 end
465 end
466
467 redef class MMethodDef
468
469 # FIXME annotation should be handled in their own way
470 redef fun html_modifiers do
471 if mproperty.is_init then
472 var res = new Array[String]
473 if mproperty.visibility != public_visibility then
474 res.add mproperty.visibility.to_s
475 end
476 return res
477 end
478 var res = super
479 if is_abstract then
480 res.add "abstract"
481 else if is_intern then
482 res.add "intern"
483 end
484 res.add "fun"
485 return res
486 end
487
488 redef fun html_declaration do
489 if mproperty.is_init then
490 var tpl = new Template
491 tpl.add "<span>"
492 tpl.add html_modifiers.join(" ")
493 tpl.add " "
494 tpl.add html_link
495 tpl.add html_signature
496 tpl.add "</span>"
497 return tpl
498 end
499 return super
500 end
501
502 redef fun html_short_signature do
503 return msignature.as(not null).html_short_signature
504 end
505
506 redef fun html_signature do
507 return msignature.as(not null).html_signature
508 end
509 end
510
511 redef class MVirtualTypeProp
512 redef fun html_link do return mvirtualtype.html_link
513 end
514
515 redef class MVirtualTypeDef
516
517 redef fun html_modifiers do
518 var res = super
519 res.add "type"
520 return res
521 end
522
523 redef fun html_short_signature do return new Template
524
525 redef fun html_signature do
526 var bound = self.bound
527 var tpl = new Template
528 if bound == null then return tpl
529 tpl.add ": "
530 tpl.add bound.html_signature
531 return tpl
532 end
533 end
534
535 redef class MType
536 # Returns the signature of this type whithout bounds.
537 fun html_short_signature: Template is abstract
538
539 # Returns the signature of this type.
540 fun html_signature: Template is abstract
541 end
542
543 redef class MClassType
544 redef fun html_link do return mclass.html_link
545 redef fun html_short_signature do return html_link
546 redef fun html_signature do return html_link
547 end
548
549 redef class MNullableType
550 redef fun html_short_signature do
551 var tpl = new Template
552 tpl.add "nullable "
553 tpl.add mtype.html_short_signature
554 return tpl
555 end
556
557 redef fun html_signature do
558 var tpl = new Template
559 tpl.add "nullable "
560 tpl.add mtype.html_signature
561 return tpl
562 end
563 end
564
565 redef class MGenericType
566 redef fun html_short_signature do
567 var lnk = html_link
568 var tpl = new Template
569 tpl.add new Link.with_title(lnk.href, mclass.name.html_escape, lnk.title)
570 tpl.add "["
571 for i in [0..arguments.length[ do
572 tpl.add arguments[i].html_short_signature
573 if i < arguments.length - 1 then tpl.add ", "
574 end
575 tpl.add "]"
576 return tpl
577 end
578
579 redef fun html_signature do
580 var lnk = html_link
581 var tpl = new Template
582 tpl.add new Link.with_title(lnk.href, mclass.name.html_escape, lnk.title)
583 tpl.add "["
584 for i in [0..arguments.length[ do
585 tpl.add arguments[i].html_signature
586 if i < arguments.length - 1 then tpl.add ", "
587 end
588 tpl.add "]"
589 return tpl
590 end
591 end
592
593 redef class MParameterType
594 redef fun html_short_signature do return html_link
595 redef fun html_signature do return html_link
596 redef fun html_raw_namespace do return html_name
597 end
598
599 redef class MVirtualType
600 redef fun html_signature do return html_link
601 redef fun html_raw_namespace do return html_name
602 end
603
604 redef class MSignature
605 redef fun html_short_signature do
606 var tpl = new Template
607 if not mparameters.is_empty then
608 tpl.add "("
609 for i in [0..mparameters.length[ do
610 tpl.add mparameters[i].html_short_signature
611 if i < mparameters.length - 1 then tpl.add ", "
612 end
613 tpl.add ")"
614 end
615 return tpl
616 end
617
618 redef fun html_signature do
619 var tpl = new Template
620 if not mparameters.is_empty then
621 tpl.add "("
622 for i in [0..mparameters.length[ do
623 tpl.add mparameters[i].html_signature
624 if i < mparameters.length - 1 then tpl.add ", "
625 end
626 tpl.add ")"
627 end
628 var return_mtype = self.return_mtype
629 if return_mtype != null then
630 tpl.add ": "
631 tpl.add return_mtype.html_signature
632 end
633 return tpl
634 end
635 end
636
637 redef class MParameter
638
639 # Returns `self` name and ellipsys if any.
640 fun html_short_signature: Template do
641 var tpl = new Template
642 tpl.add name
643 if is_vararg then tpl.add "..."
644 return tpl
645 end
646
647 # Returns `self` name with it's static type and ellipsys if any.
648 fun html_signature: Template do
649 var tpl = new Template
650 tpl.add "{name}: "
651 tpl.add mtype.html_signature
652 if is_vararg then tpl.add "..."
653 return tpl
654 end
655 end
656
657 redef class MEntityTree
658 # Render `self` as a hierarchical UnorderedList.
659 fun html_list: UnorderedList do
660 var lst = new_unordered_list
661 for r in roots do
662 var li = new_mentity_item(r)
663 lst.add_li li
664 build_html_list(r, li)
665 end
666 return lst
667 end
668
669 # Build the html list recursively.
670 private fun build_html_list(e: MEntity, li: ListItem) do
671 if not sub.has_key(e) then return
672 var subs = sub[e]
673 var lst = new_unordered_list
674 for e2 in subs do
675 if e2 isa MGroup and e2.is_root then
676 build_html_list(e2, li)
677 else
678 var sli = new_mentity_item(e2)
679 lst.add_li sli
680 build_html_list(e2, sli)
681 end
682 end
683 var text = new Template
684 text.add li.text
685 if not lst.is_empty then text.add lst
686 li.text = text
687 end
688
689 # HTML unordered List used to compose the tree.
690 #
691 # Redefine this method to add custom CSS classes or other html attributes.
692 protected fun new_unordered_list: UnorderedList do return new UnorderedList
693
694 # Return a li element for `mconcern` that can be displayed in a concern list
695 protected fun new_mentity_item(mentity: MEntity): ListItem do
696 var tpl = new Template
697 tpl.add mentity.html_link
698 var comment = mentity.html_synopsis
699 if comment != null then
700 tpl.add ": "
701 tpl.add comment
702 end
703 return new ListItem(tpl)
704 end
705 end