src: update tools to new names in generic parameters
[nit.git] / src / highlight.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 # Highliting of Nit AST
16 module highlight
17
18 import frontend
19 import html
20 import pipeline
21 import astutil
22
23 # Visitor used to produce a HTML tree based on a AST on a `Source`
24 class HighlightVisitor
25 # The root of the HTML hierarchy
26 var html = new HTMLTag("span")
27
28 # Is the HTML include a nested `<span class"{type_of_node}">` element for each `ANode` of the AST?
29 # Used to have a really huge and verbose HTML (mainly for debug)
30 var with_ast = false is writable
31
32 # The first line to generate, null if start at the first line
33 var first_line: nullable Int = null is writable
34
35 # The last line to generate, null if finish at the last line
36 var last_line: nullable Int = null is writable
37
38 init
39 do
40 html.add_class("nitcode")
41 end
42
43 fun enter_visit(n: ANode)
44 do
45 n.parentize_tokens
46 var s = n.location.file
47 htmlize(s.first_token.as(not null), s.last_token.as(not null))
48 end
49
50 # Produce HTML between two tokens
51 protected fun htmlize(first_token, last_token: Token)
52 do
53 var stack2 = new Array[HTMLTag]
54 var stack = new Array[Prod]
55 var closes = new Array[Prod]
56 var line = 0
57 var c: nullable Token = first_token
58 var hv = new HighlightVisitor
59 while c != null do
60 var starting
61
62 # Handle start of line
63 var cline = c.location.line_start
64 if cline != line then
65 # Handle starting block productions,
66 # Because c could be a detached token, get prods in
67 # the first AST token
68 var c0 = c.first_token_in_line
69 starting = null
70 if c0 != null then starting = c0.starting_prods
71 if starting != null then for p in starting do
72 if not p.is_block then continue
73 var tag = p.make_tag(hv)
74 if tag == null then continue
75 tag.add_class("foldable")
76 var infobox = p.infobox(hv)
77 if infobox != null then tag.attach_infobox(infobox)
78 stack2.add(html)
79 html.add tag
80 html = tag
81 stack.add(p)
82 end
83
84 # Add a div for the whole line
85 var tag = new HTMLTag("span")
86 tag.attrs["id"] = "L{cline}"
87 tag.classes.add "line"
88 stack2.add(html)
89 html.add tag
90 html = tag
91 line = cline
92 end
93
94 # Add the blank, verbatim
95 html.add_raw_html c.blank_before
96
97 # Handle starting span production
98 starting = c.starting_prods
99 if starting != null then for p in starting do
100 if not p.is_span then continue
101 var tag = p.make_tag(hv)
102 if tag == null then continue
103 var infobox = p.infobox(hv)
104 if infobox != null then tag.attach_infobox(infobox)
105 stack2.add(html)
106 html.add tag
107 html = tag
108 stack.add(p)
109 end
110
111 # Add the token
112 if c isa TEol then
113 html.append "\n"
114 else
115 var tag = c.make_tag(hv)
116 var pa = c.parent
117 var infobox = null
118 if c isa TId or c isa TClassid or c isa TAttrid or c isa TokenLiteral or c isa TokenOperator then
119 assert c != null
120 if pa != null then infobox = pa.decorate_tag(hv, tag, c)
121 else if c isa TComment and pa isa ADoc then
122 infobox = pa.decorate_tag(hv, tag, c)
123 end
124 if infobox != null then tag.attach_infobox(infobox)
125 html.add tag
126 end
127
128 # Handle ending span productions
129 var ending = c.ending_prods
130 if ending != null then for p in ending do
131 if not p.is_span then continue
132 if stack.is_empty or p != stack.last then continue
133 stack.pop
134 html = stack2.pop
135 end
136
137 # Handle end of line and end of file
138 var n = c.next_token
139 if c == last_token then n = null
140 if n == null or n.location.line_start != line then
141 # closes the line div
142 html = stack2.pop
143
144 # close the block production divs
145 var c0 = c.last_token_in_line
146 ending = null
147 if c0 != null then ending = c0.ending_prods
148 if ending != null then for p in ending do
149 if not p.is_block then continue
150 if stack.is_empty or p != stack.last then continue
151 stack.pop
152 html = stack2.pop
153 end
154 end
155
156 c = n
157 end
158 assert stack.is_empty
159 assert stack2.is_empty
160 end
161
162 # Return a default CSS content related to CSS classes used in the `html` tree.
163 # Could be inlined in the `.html` file of saved as a specific `.css` file.
164 fun css_content: String
165 do
166 return """
167 .nitcode a { color: inherit; cursor:pointer; }
168 .nitcode .popupable:hover { text-decoration: underline; cursor:help; } /* underline titles */
169 pre.nitcode .foldable { display: block } /* for block productions*/
170 pre.nitcode .line{ display: block } /* for lines */
171 pre.nitcode .line:hover{ background-color: #FFFFE0; } /* current line */
172 .nitcode :target { background-color: #FFF3C2 } /* target highlight*/
173 /* lexical raw tokens. independent of usage or semantic: */
174 .nitcode .nc_c { color: gray; font-style: italic; } /* comment */
175 .nitcode .nc_d { color: #3D8127; font-style: italic; } /* documentation comments */
176 .nitcode .nc_k { font-weight: bold; } /* keyword */
177 .nitcode .nc_o {} /* operator */
178 .nitcode .nc_i {} /* standard identifier */
179 .nitcode .nc_t { color: #445588; font-weight: bold; } /* type/class identifier */
180 .nitcode .nc_a { color: #445588; font-style: italic; } /* old style attribute identifier */
181 .nitcode .nc_l { color: #009999; } /* char and number literal */
182 .nitcode .nc_s { color: #8F1546; } /* string literal */
183 /* syntactic token usage. added because of their position in the AST */
184 .nitcode .nc_ast { color: blue; } /* assert label */
185 .nitcode .nc_la { color: blue; } /* break/continue label */
186 .nitcode .nc_m { color: #445588; } /* module name */
187 /* syntactic groups */
188 .nitcode .nc_def { font-weight: bold; color: blue; } /* name used in a definition */
189 .nitcode .nc_def.nc_a { color: blue; } /* name used in a attribute definition */
190 .nitcode .nc_def.nc_t { color: blue; } /* name used in a class or vt definition */
191 .nitcode .nc_ss { color: #9E6BEB; } /* superstrings */
192 .nitcode .nc_cdef {} /* A whole class definition */
193 .nitcode .nc_pdef {} /* A whole property definition */
194 /* semantic token usage */
195 .nitcode .nc_v { font-style: italic; } /* local variable or parameter */
196 .nitcode .nc_vt { font-style: italic; } /* virtual type or formal type */
197
198 .nitcode .nc_error { border: 1px red solid;} /* not used */
199 .popover { max-width: 800px !important; }
200 """
201 end
202
203 # Additional content to inject in the <head> tag
204 # Note: does not include `css_content`; handle it yourself.
205 fun head_content: String
206 do
207 return """<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">\n"""
208 end
209
210 # Additional content to inject just before the closing </body> tag
211 fun foot_content: String
212 do
213 return """
214 <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
215 <script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
216 <script>$(".popupable").popover({html:true, placement:'top'})/*initialize bootstrap popover*/</script>"""
217 end
218 end
219
220 redef class HTMLTag
221 # Attach the infobox to the node by using BootStrap popover
222 fun attach_infobox(infobox: HInfoBox)
223 do
224 classes.add("popupable")
225 attrs["title"] = infobox.title
226 var href = infobox.href
227 if href != null then
228 attrs["data-title"] = """<a href="{{{href}}}">{{{infobox.title}}}</a>"""
229 end
230 attrs["data-content"] = infobox.content.write_to_string
231 attrs["data-toggle"] = "popover"
232 end
233 end
234
235
236 # A generic information container that can be used to decorate AST entities
237 class HInfoBox
238 # The visitor used for contextualisation, if needed
239 var visitor: HighlightVisitor
240
241 # A short title for the AST element
242 var title: String
243
244 # The primary link where the entity points
245 # null if no link
246 var href: nullable String = null
247
248 # The content of the popuped infobox
249 var content = new HTMLTag("div")
250
251 # Append a new field in the popuped infobox
252 fun new_field(title: String): HTMLTag
253 do
254 content.open("b").text(title)
255 content.append(" ")
256 var res = content.open("span")
257 content.open("br")
258 return res
259 end
260
261 # Append a new dropdown in the popuped content
262 fun new_dropdown(title, text: String): HTMLTag
263 do
264 content.add_raw_html """<div class="dropdown"> <a data-toggle="dropdown" href="#"><b>"""
265 content.append(title)
266 content.add_raw_html "</b> "
267 content.append(text)
268 content.add_raw_html """<span class="caret"></span></a>"""
269 var res = content.open("ul").add_class("dropdown-menu").attr("role", "menu").attr("aria-labelledby", "dLabel")
270 content.add_raw_html "</div>"
271 return res
272 end
273 end
274
275 ##
276
277 # Model entity or whatever that can produce an infobox
278 interface HInfoBoxable
279 # An new infobox documenting the entity
280 fun infobox(v: HighlightVisitor): HInfoBox is abstract
281
282 # A human-readable hyper-text for the entity
283 fun linkto: HTMLTag is abstract
284 end
285
286 redef class MDoc
287 # Append an entry for the doc in the given infobox
288 fun fill_infobox(res: HInfoBox)
289 do
290 if content.length < 2 then
291 res.new_field("doc").text(content.first)
292 return
293 end
294 var c = res.new_dropdown("doc", content.first)
295 for x in content.iterator.skip_head(1) do
296 c.append x
297 c.add_raw_html "<br>"
298 end
299 end
300 end
301
302 redef class MEntity
303 super HInfoBoxable
304 end
305
306 redef class MModule
307 redef fun infobox(v)
308 do
309 var res = new HInfoBox(v, "module {name}")
310 res.href = href
311 res.new_field("module").add(linkto)
312 var mdoc = self.mdoc
313 if mdoc != null then mdoc.fill_infobox(res)
314 if in_importation.greaters.length > 1 then
315 var c = res.new_dropdown("imports", "{in_importation.greaters.length-1} modules")
316 for x in in_importation.greaters do
317 if x == self then continue
318 c.open("li").add x.linkto
319 end
320 end
321 return res
322 end
323
324 fun href: String
325 do
326 return name + ".html"
327 end
328
329 redef fun linkto do return linkto_text(name)
330
331 # Link to the entitiy with a specific text
332 fun linkto_text(text: String): HTMLTag
333 do
334 return (new HTMLTag("a")).attr("href", href).text(text)
335 end
336 end
337
338 redef class MClassDef
339 redef fun infobox(v)
340 do
341 var res = new HInfoBox(v, "class {mclass.name}")
342 res.href = href
343 if is_intro then
344 res.new_field("class").text(mclass.name)
345 else
346 res.new_field("redef class").text(mclass.name)
347 res.new_field("intro").add mclass.intro.linkto_text("in {mclass.intro.mmodule.to_s}")
348 end
349 var mdoc = self.mdoc
350 if mdoc == null then mdoc = mclass.intro.mdoc
351 if mdoc != null then mdoc.fill_infobox(res)
352
353 if in_hierarchy.greaters.length > 1 then
354 var c = res.new_dropdown("hier", "super-classes")
355 for x in in_hierarchy.greaters do
356 if x == self then continue
357 if not x.is_intro then continue
358 c.open("li").add x.linkto
359 end
360 end
361 if in_hierarchy.smallers.length > 1 then
362 var c = res.new_dropdown("hier", "sub-classes")
363 for x in in_hierarchy.smallers do
364 if x == self then continue
365 if not x.is_intro then continue
366 c.open("li").add x.linkto
367 end
368 end
369 if mclass.mclassdefs.length > 1 then
370 var c = res.new_dropdown("redefs", "refinements")
371 for x in mclass.mclassdefs do
372 if x == self then continue
373 c.open("li").add x.linkto_text("in {x.mmodule}")
374 end
375 end
376 return res
377 end
378
379 fun href: String
380 do
381 return mmodule.href + "#" + to_s
382 end
383
384 redef fun linkto do return linkto_text(mclass.name)
385
386 # Link to the entitiy with a specific text
387 fun linkto_text(text: String): HTMLTag
388 do
389 return (new HTMLTag("a")).attr("href", href).text(text)
390 end
391 end
392
393 redef class MPropDef
394 redef fun infobox(v)
395 do
396 var res = new HInfoBox(v, to_s)
397 res.href = href
398 if self isa MMethodDef then
399 res.new_field("fun").append(mproperty.name).add msignature.linkto
400 else if self isa MAttributeDef then
401 res.new_field("fun").append(mproperty.name).add static_mtype.linkto
402 else if self isa MVirtualTypeDef then
403 res.new_field("add").append(mproperty.name).add bound.linkto
404 else
405 res.new_field("wat?").append(mproperty.name)
406 end
407
408 if is_intro then
409 else
410 res.new_field("intro").add mproperty.intro.linkto_text("in {mproperty.intro.mclassdef}")
411 end
412 var mdoc = self.mdoc
413 if mdoc == null then mdoc = mproperty.intro.mdoc
414 if mdoc != null then mdoc.fill_infobox(res)
415 if mproperty.mpropdefs.length > 1 then
416 var c = res.new_dropdown("redef", "redefinitions")
417 for x in mproperty.mpropdefs do
418 c.open("li").add x.linkto_text("in {x.mclassdef}")
419 end
420 end
421
422 return res
423 end
424
425 fun href: String
426 do
427 return self.mclassdef.mmodule.href + "#" + self.to_s
428 end
429
430 redef fun linkto do return linkto_text(mproperty.name)
431
432 # Link to the entitiy with a specific text
433 fun linkto_text(text: String): HTMLTag
434 do
435 return (new HTMLTag("a")).attr("href", href).text(text)
436 end
437 end
438
439 redef class MClassType
440 redef fun infobox(v)
441 do
442 var res = new HInfoBox(v, to_s)
443 res.href = mclass.intro.href
444 res.new_field("class").add mclass.intro.linkto
445 var mdoc = mclass.mdoc
446 if mdoc == null then mdoc = mclass.intro.mdoc
447 if mdoc != null then mdoc.fill_infobox(res)
448 return res
449 end
450 redef fun linkto
451 do
452 return mclass.intro.linkto
453 end
454 end
455 redef class MVirtualType
456 redef fun infobox(v)
457 do
458 var res = new HInfoBox(v, to_s)
459 res.href = mproperty.intro.href
460 var p = mproperty
461 var pd = p.intro
462 res.new_field("virtual type").add pd.linkto
463 var mdoc = pd.mdoc
464 if mdoc != null then mdoc.fill_infobox(res)
465 return res
466 end
467 redef fun linkto
468 do
469 return mproperty.intro.linkto
470 end
471 end
472 redef class MParameterType
473 redef fun infobox(v)
474 do
475 var res = new HInfoBox(v, to_s)
476 res.new_field("parameter type").append("{name} from class ").add mclass.intro.linkto
477 return res
478 end
479 redef fun linkto
480 do
481 return (new HTMLTag("span")).text(name)
482 end
483 end
484
485 redef class MNullableType
486 redef fun infobox(v)
487 do
488 return mtype.infobox(v)
489 end
490 redef fun linkto
491 do
492 var res = new HTMLTag("span")
493 res.append("nullable ").add(mtype.linkto)
494 return res
495 end
496 end
497
498 redef class MSignature
499 redef fun linkto
500 do
501 var res = new HTMLTag("span")
502 var first = true
503 if not mparameters.is_empty then
504 res.append "("
505 for p in mparameters do
506 if first then
507 first = false
508 else
509 res.append ", "
510 end
511 res.append p.name
512 res.append ": "
513 res.add p.mtype.linkto
514 end
515 res.append ")"
516 end
517 var ret = return_mtype
518 if ret != null then
519 res.append ": "
520 res.add ret.linkto
521 end
522 return res
523 end
524 end
525
526 redef class CallSite
527 super HInfoBoxable
528 redef fun infobox(v)
529 do
530 var res = new HInfoBox(v, "call {mpropdef}")
531 res.href = mpropdef.href
532 res.new_field("call").add(mpropdef.linkto).add(msignature.linkto)
533 if mpropdef.is_intro then
534 else
535 res.new_field("intro").add mproperty.intro.linkto_text("in {mproperty.intro.mclassdef}")
536 end
537 var mdoc = mpropdef.mdoc
538 if mdoc == null then mdoc = mproperty.intro.mdoc
539 if mdoc != null then mdoc.fill_infobox(res)
540
541 return res
542 end
543 redef fun linkto
544 do
545 return mpropdef.linkto
546 end
547 end
548
549 redef class Variable
550 super HInfoBoxable
551 redef fun infobox(v)
552 do
553 var declared_type = self.declared_type
554 if declared_type == null then
555 var res = new HInfoBox(v, "{name}")
556 res.new_field("local var").append("{name}")
557 return res
558 end
559 var res = new HInfoBox(v, "{name}: {declared_type}")
560 res.new_field("local var").append("{name}:").add(declared_type.linkto)
561 return res
562 end
563 redef fun linkto
564 do
565 return (new HTMLTag("span")).text(name)
566 end
567 end
568
569
570 ##
571
572 redef class ANode
573 # Optionally creates a tag that encapsulate the AST element on HTML rendering
574 protected fun make_tag(v: HighlightVisitor): nullable HTMLTag do return null
575
576 # Add aditionnal information on a child-token and return an additionnal HInfoBox on it
577 protected fun decorate_tag(v: HighlightVisitor, res: HTMLTag, token: Token): nullable HInfoBox
578 do
579 #debug("no decoration for {token.inspect}")
580 #res.add_class("nc_error")
581 return null
582 end
583
584 # Return a optional infobox
585 fun infobox(v: HighlightVisitor): nullable HInfoBox do return null
586 end
587
588 redef class AStdClassdef
589 redef fun make_tag(v)
590 do
591 var res = new HTMLTag("span")
592 res.add_class("nc_cdef")
593 var md = mclassdef
594 if md != null then res.attr("id", md.to_s)
595 return res
596 end
597 redef fun decorate_tag(v, res, token)
598 do
599 res.add_class("nc_def")
600
601 var md = mclassdef
602 if md == null then return null
603 return md.infobox(v)
604 end
605 end
606 redef class APropdef
607 redef fun make_tag(v)
608 do
609 var res = new HTMLTag("span")
610 res.add_class("nc_pdef")
611 var mpd
612 mpd = mpropdef
613 if mpd != null then
614 #res.add(tag(mpd))
615 res.attr("id", mpd.to_s)
616 end
617 if self isa AAttrPropdef then
618 mpd = mreadpropdef
619 if mpd != null then res.add(tag(mpd))
620 mpd = mwritepropdef
621 if mpd != null then res.add(tag(mpd))
622 end
623 return res
624 end
625
626 private fun tag(mpd: MPropDef): HTMLTag
627 do
628 var a = new HTMLTag("a")
629 a.attr("id", mpd.to_s)
630 return a
631 end
632 end
633
634 redef class Token
635 # Produce an HTMLTag with the correct contents and CSS classes
636 # Subclasses can redefine it to decorate the tag
637 redef fun make_tag(v: HighlightVisitor): HTMLTag
638 do
639 var res = new HTMLTag("span")
640 res.text(text)
641 return res
642 end
643 end
644
645 redef class TokenKeyword
646 redef fun make_tag(v)
647 do
648 var res = super
649 res.add_class("nc_k")
650 return res
651 end
652 end
653 redef class TokenOperator
654 redef fun make_tag(v)
655 do
656 var res = super
657 var p = parent
658 if p != null then p.decorate_tag(v, res, self)
659 res.add_class("nc_o")
660 return res
661 end
662 end
663
664 redef class AVarFormExpr
665 redef fun decorate_tag(v, res, token)
666 do
667 var variable = self.variable
668 if variable == null then return null
669 res.add_class("nc_v")
670 return variable.infobox(v)
671 end
672 end
673
674 redef class AVardeclExpr
675 redef fun decorate_tag(v, res, token)
676 do
677 var variable = self.variable
678 if variable == null then return null
679 res.add_class("nc_v")
680 return variable.infobox(v)
681 end
682 end
683
684 redef class AForExpr
685 redef fun decorate_tag(v, res, token)
686 do
687 if not token isa TId then return null
688 var vs = variables
689 if vs == null then return null
690 res.add_class("nc_v")
691 var idx = n_ids.index_of(token)
692 var variable = vs[idx]
693 return variable.infobox(v)
694 end
695 end
696
697 redef class AParam
698 redef fun decorate_tag(v, res, token)
699 do
700 var mp = mparameter
701 if mp == null then return null
702 var variable = self.variable
703 if variable == null then return null
704 res.add_class("nc_v")
705 return variable.infobox(v)
706 end
707 end
708
709 redef class AAssertExpr
710 redef fun decorate_tag(v, res, token)
711 do
712 res.add_class("nc_ast")
713 return null
714 end
715 end
716
717 redef class ALabel
718 redef fun decorate_tag(v, res, token)
719 do
720 res.add_class("nc_la")
721 return null
722 end
723 end
724
725 redef class ASendExpr
726 redef fun decorate_tag(v, res, token)
727 do
728 if callsite == null then return null
729 return callsite.infobox(v)
730 end
731 end
732
733 redef class ANewExpr
734 redef fun decorate_tag(v, res, token)
735 do
736 if callsite == null then return null
737 return callsite.infobox(v)
738 end
739 end
740
741 redef class AAssignOp
742 redef fun decorate_tag(v, res, token)
743 do
744 var p = parent
745 assert p isa AReassignFormExpr
746
747 var callsite = p.reassign_callsite
748 if callsite == null then return null
749 return callsite.infobox(v)
750 end
751 end
752
753 redef class AModuleName
754 redef fun decorate_tag(v, res, token)
755 do
756 return parent.decorate_tag(v, res, token)
757 end
758 end
759
760 redef class AModuledecl
761 redef fun decorate_tag(v, res, token)
762 do
763 res.add_class("nc_def")
764 res.add_class("nc_m")
765 var p = parent
766 assert p isa AModule
767 var mm = p.mmodule
768 if mm == null then return null
769 return mm.infobox(v)
770 end
771 end
772
773 redef class AStdImport
774 redef fun decorate_tag(v, res, token)
775 do
776 res.add_class("nc_m")
777 var mm = mmodule
778 if mm == null then return null
779 return mm.infobox(v)
780 end
781 end
782 redef class AAttrPropdef
783 redef fun decorate_tag(v, res, token)
784 do
785 res.add_class("nc_def")
786 var mpd: nullable MPropDef
787 mpd = mreadpropdef
788 if mpd == null then mpd = mpropdef
789 if mpd == null then return null
790 return mpd.infobox(v)
791 end
792 end
793
794 redef class TId
795 redef fun make_tag(v)
796 do
797 var res = super
798 var p = parent
799 if p != null then p.decorate_tag(v, res, self)
800 res.add_class("nc_i")
801 return res
802 end
803 end
804 redef class AMethid
805 redef fun make_tag(v)
806 do
807 var res = new HTMLTag("span")
808 res.add_class("nc_def")
809 return res
810 end
811 redef fun decorate_tag(v, res, token)
812 do
813 return null
814 # nothing to decorate
815 end
816 redef fun infobox(v)
817 do
818 var p = parent
819 if not p isa AMethPropdef then return null
820 var mpd = p.mpropdef
821 if mpd == null then return null
822 return mpd.infobox(v)
823 end
824 end
825 redef class TAttrid
826 redef fun make_tag(v)
827 do
828 var res = super
829 var p = parent
830 if p != null then p.decorate_tag(v, res, self)
831 res.add_class("nc_a")
832 return res
833 end
834 end
835 redef class AAttrFormExpr
836 redef fun decorate_tag(v, res, token)
837 do
838 var p = mproperty
839 if p == null then return null
840 return p.intro.infobox(v)
841 end
842 end
843 redef class TClassid
844 redef fun make_tag(v)
845 do
846 var res = super
847 var p = parent
848 if p != null then p.decorate_tag(v, res, self)
849 res.add_class("nc_t")
850 return res
851 end
852 end
853 redef class AType
854 redef fun decorate_tag(v, res, token)
855 do
856 var mt = mtype
857 if mt == null then return null
858 mt = mt.as_notnullable
859 if mt isa MVirtualType or mt isa MParameterType then
860 res.add_class("nc_vt")
861 end
862 return mt.infobox(v)
863 end
864 end
865 redef class AFormaldef
866 redef fun decorate_tag(v, res, token)
867 do
868 res.add_class("nc_vt")
869 if mtype == null then return null
870 return mtype.infobox(v)
871 end
872 end
873 redef class ATypePropdef
874 redef fun decorate_tag(v, res, token)
875 do
876 res.add_class("nc_def")
877 var md = mpropdef
878 if md == null then return null
879 return md.infobox(v)
880 end
881 end
882 redef class TComment
883 redef fun make_tag(v)
884 do
885 var res = super
886 if not parent isa ADoc then
887 res.add_class("nc_c")
888 end
889 return res
890 end
891 end
892 redef class ADoc
893 redef fun make_tag(v)
894 do
895 var res = new HTMLTag("span")
896 res.add_class("nc_d")
897 return res
898 end
899 end
900 redef class TokenLiteral
901 redef fun make_tag(v)
902 do
903 var res = super
904 res.add_class("nc_l")
905 var p = parent
906 if p != null then p.decorate_tag(v, res, self)
907 return res
908 end
909 end
910 redef class ASuperstringExpr
911 redef fun make_tag(v)
912 do
913 var res = new HTMLTag("span")
914 res.add_class("nc_ss")
915 return res
916 end
917 end
918 redef class AStringFormExpr
919 redef fun decorate_tag(v, res, token)
920 do
921 # Workaround to tag strings
922 res.classes.remove("nc_l")
923 res.add_class("nc_s")
924 return null
925 end
926 end
927 redef class AExpr
928 redef fun decorate_tag(v, res, token)
929 do
930 var t = mtype
931 if t == null then return null
932 return t.infobox(v)
933 end
934 end
935