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