757af93ca7cf9b04c134f7c0e9e5f66af66de660
1 # This file is part of NIT ( http://www.nitlanguage.org ).
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
7 # http://www.apache.org/licenses/LICENSE-2.0
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.
15 # Highlighting of Nit AST
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")
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
32 # Prefixes used in generated IDs for line `<span>` elements.
33 # Useful if more than one highlighted code is present in the same HTML document.
35 # If set to the empty string, id for lines are disabled.
37 # Is `"L"` by default.
38 var line_id_prefix
= "L" is writable
40 # The first line to generate, null if start at the first line
41 var first_line
: nullable Int = null is writable
43 # The last line to generate, null if finish at the last line
44 var last_line
: nullable Int = null is writable
46 # When highlighting a node, show its messages (errors, warnings), if any.
49 var show_messages
= true is writable
51 # When highlighting a node, attach a full popupable infobox, if any.
53 # If `false`, only a simple `title` tooltip is used.
56 var show_infobox
= true is writable
58 # A reference to an entity used in generated `<a>` elements.
60 # It is used to refer to some specific entities when generating links.
61 # If `null` is returned, then no link are generated and `<a>` elements become `<span>`.
63 # Clients are encouraged to redefine the method in a subclass to control where entities should link to.
64 fun hrefto
(entitiy
: MEntity): nullable String
71 html
.add_class
("nitcode")
74 # When highlighting a node, also consider the loose tokens around it.
76 # Loose tokens are tokens discarded from the AST but attached before
77 # or after some non-loose tokens. See `Token::is_loose`.
79 # When this flag is set to `true`, the loose tokens that are before the
80 # first token and after the last token are also highlighted.
83 var include_loose_tokens
= false is writable
85 # When highlighting a node, the first and the last lines are fully included.
87 # If the highlighted node starts (or ends) in the middle of a line,
88 # this flags forces the whole line to be highlighted.
91 var include_whole_lines
= false is writable
93 # The entry-point of the highlighting.
94 # Will fill `html` with the generated HTML content.
95 fun enter_visit
(n
: ANode)
108 if f
== null then return
110 if l
== null then return
113 if include_loose_tokens
then
114 if f
.prev_looses
.not_empty
then f
= f
.prev_looses
.first
115 if l
.next_looses
.not_empty
then l
= l
.next_looses
.last
118 if include_whole_lines
then
119 f
= f
.first_real_token_in_line
120 l
= l
.last_real_token_in_line
126 private fun full_tag
(anode
: ANode, hv
: HighlightVisitor): nullable HTMLTag
128 var tag
= anode
.make_tag
(hv
)
129 if tag
== null then return null
130 var infobox
= anode
.infobox
(hv
)
131 if infobox
== null and anode
isa Token then
132 var pa
= anode
.parent
134 infobox
= pa
.decorate_tag
(hv
, tag
, anode
)
137 if infobox
!= null and not show_infobox
then
138 tag
.attr
("title", infobox
.title
)
139 tag
.classes
.add
"titled"
142 var messages
= anode
.location
.messages
143 if messages
!= null and show_messages
then
144 tag
.css
("border-bottom", "solid 2px red")
145 if infobox
== null then
146 infobox
= new HInfoBox(hv
, "Messages")
148 var c
= infobox
.new_dropdown
("{messages.length} message(s)", "")
150 c
.open
("li").append
(m
.text
)
153 if infobox
!= null then
154 tag
.attach_infobox
(infobox
)
159 # Highlight a full lexed source file.
161 # REQUIRE `source.first_token != null`
162 fun hightlight_source
(source
: SourceFile)
164 htmlize
(source
.first_token
.as(not null), null)
167 # Produce HTML between two tokens
168 protected fun htmlize
(first_token
: Token, last_token
: nullable Token)
170 var stack2
= new Array[HTMLTag]
171 var stack
= new Array[Prod]
173 var c
: nullable Token = first_token
174 var hv
= new HighlightVisitor
178 # Handle start of line
179 var cline
= c
.location
.line_start
180 if cline
!= line
then
181 # Handle starting block productions,
182 # Because c could be a detached token, get prods in
183 # the first AST token
184 var c0
= c
.first_token_in_line
186 if c0
!= null then starting
= c0
.starting_prods
187 if starting
!= null then for p
in starting
do
188 if not p
.is_block
then continue
189 var tag
= full_tag
(p
, hv
)
190 if tag
== null then continue
191 tag
.add_class
("foldable")
198 # Add a div for the whole line
199 var tag
= new HTMLTag("span")
200 var p
= line_id_prefix
201 if p
!= "" then tag
.attrs
["id"] = "{p}{cline}"
202 tag
.classes
.add
"line"
209 # Add the blank, verbatim
210 html
.add_raw_html c
.blank_before
212 # Handle starting span production
213 starting
= c
.starting_prods
214 if starting
!= null then for p
in starting
do
215 if not p
.is_span
then continue
216 var tag
= full_tag
(p
, hv
)
217 if tag
== null then continue
228 var tag
= full_tag
(c
, hv
)
229 if tag
!= null then html
.add tag
232 # Handle ending span productions
233 var ending
= c
.ending_prods
234 if ending
!= null then for p
in ending
do
235 if not p
.is_span
then continue
236 if stack
.is_empty
or p
!= stack
.last
then continue
241 # Handle end of line and end of file
243 if c
== last_token
then n
= null
244 if n
== null or n
.location
.line_start
!= line
then
245 # closes the line div
248 # close the block production divs
249 var c0
= c
.last_token_in_line
251 if c0
!= null then ending
= c0
.ending_prods
252 if ending
!= null then for p
in ending
do
253 if not p
.is_block
then continue
254 if stack
.is_empty
or p
!= stack
.last
then continue
262 #assert stack.is_empty
263 #assert stack2.is_empty
266 # Return a default CSS content related to CSS classes used in the `html` tree.
267 # Could be inlined in the `.html` file of saved as a specific `.css` file.
268 fun css_content
: String
271 .nitcode a { color: inherit; cursor:pointer; }
272 .nitcode .titled:hover { text-decoration: underline; } /* underline titles */
273 .nitcode .popupable:hover { text-decoration: underline; cursor:help; } /* underline titles */
274 .nitcode .foldable { display: block } /* for block productions*/
275 .nitcode .line{ display: block } /* for lines */
276 .nitcode .line:hover{ background-color: #FFFFE0; } /* current line */
277 .nitcode :target { background-color: #FFF3C2 } /* target highlight*/
278 /* lexical raw tokens. independent of usage or semantic: */
279 .nitcode .nc_c { color: gray; font-style: italic; } /* comment */
280 .nitcode .nc_d { color: #3D8127; font-style: italic; } /* documentation comments */
281 .nitcode .nc_k { font-weight: bold; } /* keyword */
282 .nitcode .nc_o {} /* operator */
283 .nitcode .nc_i {} /* standard identifier */
284 .nitcode .nc_t { color: #445588; font-weight: bold; } /* type/class identifier */
285 .nitcode .nc_a { color: #445588; font-style: italic; } /* old style attribute identifier */
286 .nitcode .nc_l { color: #009999; } /* char and number literal */
287 .nitcode .nc_s { color: #8F1546; } /* string literal */
288 /* syntactic token usage. added because of their position in the AST */
289 .nitcode .nc_ast { color: blue; } /* assert label */
290 .nitcode .nc_la { color: blue; } /* break/continue label */
291 .nitcode .nc_m { color: #445588; } /* module name */
292 /* syntactic groups */
293 .nitcode .nc_def { font-weight: bold; color: blue; } /* name used in a definition */
294 .nitcode .nc_def.nc_a { color: blue; } /* name used in a attribute definition */
295 .nitcode .nc_def.nc_t { color: blue; } /* name used in a class or vt definition */
296 .nitcode .nc_ss { color: #9E6BEB; } /* superstrings */
297 .nitcode .nc_cdef {} /* A whole class definition */
298 .nitcode .nc_pdef {} /* A whole property definition */
299 /* semantic token usage */
300 .nitcode .nc_v { font-style: italic; } /* local variable or parameter */
301 .nitcode .nc_vt { font-style: italic; } /* virtual type or formal type */
303 .nitcode .nc_error { border: 1px red solid;} /* not used */
304 .popover { max-width: 800px !important; }
308 # Additional content to inject in the <head> tag
309 # Note: does not include `css_content`; handle it yourself.
310 fun head_content
: String
312 return """<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">\n"""
315 # Additional content to inject just before the closing </body> tag
316 fun foot_content
: String
319 <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
320 <script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
321 <script>$(".popupable").popover({html:true, placement:'top'})/*initialize bootstrap popover*/</script>"""
326 # Attach the infobox to the node by using BootStrap popover
327 fun attach_infobox
(infobox
: HInfoBox)
329 classes
.add
("popupable")
330 attrs
["title"] = infobox
.title
331 var href
= infobox
.href
333 attrs
["data-title"] = """<a href="{{{href}}}">{{{infobox.title}}}</a>"""
335 attrs
["data-content"] = infobox
.content
.write_to_string
336 attrs
["data-toggle"] = "popover"
341 # A generic information container that can be used to decorate AST entities
343 # The visitor used for contextualisation, if needed
344 var visitor
: HighlightVisitor
346 # A short title for the AST element
349 # The primary link where the entity points
351 var href
: nullable String = null
353 # The content of the popuped infobox
354 var content
= new HTMLTag("div")
356 # Append a new field in the popuped infobox
357 fun new_field
(title
: String): HTMLTag
359 content
.open
("b").text
(title
)
361 var res
= content
.open
("span")
366 # Append a new dropdown in the popuped content
367 fun new_dropdown
(title
, text
: String): HTMLTag
369 content
.add_raw_html
"""<div class="dropdown"> <a data-toggle="dropdown" href="#"><b>"""
370 content
.append
(title
)
371 content
.add_raw_html
"</b> "
373 content
.add_raw_html
"""<span class="caret"></span></a>"""
374 var res
= content
.open
("ul").add_class
("dropdown-menu").attr
("role", "menu").attr
("aria-labelledby", "dLabel")
375 content
.add_raw_html
"</div>"
382 # Model entity or whatever that can produce an infobox
383 interface HInfoBoxable
384 # An new infobox documenting the entity
385 fun infobox
(v
: HighlightVisitor): HInfoBox is abstract
389 # Append an entry for the doc in the given infobox
390 fun fill_infobox
(res
: HInfoBox)
392 if content
.length
< 2 then
393 res
.new_field
("doc").text
(content
.first
)
396 var c
= res
.new_dropdown
("doc", content
.first
)
397 for x
in content
.iterator
.skip_head
(1) do
399 c
.add_raw_html
"<br>"
407 # A HTML version of `to_s` with hyper-links.
409 # By default, `linkto_text(v, to_s)` is used, c.f. see `linkto_text`.
411 # For some complex entities, like generic types, multiple `<a>` and `<span>` elements can be generated.
412 # E.g. `Array[Int]` might become `<a>Array</a>[<a>Int</a>]` with the correct `href` attributes
413 # provided by `v.hrefto`.
414 fun linkto
(v
: HighlightVisitor): HTMLTag do return linkto_text
(v
, to_s
)
416 # Link to the `self` with a specific text.
418 # The whole text is linked with a single `<a>` element.
420 # The `href` used is provided by `v.hrefto`.
421 # If `href` is null then a `<span>` element is used instead of `<a>`.
422 fun linkto_text
(v
: HighlightVisitor, text
: String): HTMLTag
424 var href
= v
.hrefto
(self)
426 return (new HTMLTag("span")).text
(text
)
428 return (new HTMLTag("a")).attr
("href", href
).text
(text
)
432 private fun href
: nullable String do return null
438 var res
= new HInfoBox(v
, "module {name}")
439 res
.href
= v
.hrefto
(self)
440 res
.new_field
("module").add
(linkto
(v
))
442 if mdoc
!= null then mdoc
.fill_infobox
(res
)
443 if in_importation
.greaters
.length
> 1 then
444 var c
= res
.new_dropdown
("imports", "{in_importation.greaters.length-1} modules")
445 for x
in in_importation
.greaters
do
446 if x
== self then continue
447 c
.open
("li").add x
.linkto
(v
)
453 # The module HTML page
454 redef fun href
: String
456 return c_name
+ ".html"
459 redef fun linkto
(v
) do return linkto_text
(v
, name
)
462 redef class MClassDef
465 var res
= new HInfoBox(v
, "class {mclass.name}")
466 res
.href
= v
.hrefto
(self)
468 res
.new_field
("class").text
(mclass
.name
)
470 res
.new_field
("redef class").text
(mclass
.name
)
471 res
.new_field
("intro").add mclass
.intro
.linkto_text
(v
, "in {mclass.intro_mmodule.to_s}")
474 if mdoc
== null then mdoc
= mclass
.intro
.mdoc
475 if mdoc
!= null then mdoc
.fill_infobox
(res
)
477 if in_hierarchy
== null then return res
479 if in_hierarchy
.greaters
.length
> 1 then
480 var c
= res
.new_dropdown
("hier", "super-classes")
481 for x
in in_hierarchy
.greaters
do
482 if x
== self then continue
483 if not x
.is_intro
then continue
484 c
.open
("li").add x
.linkto
(v
)
487 if in_hierarchy
.smallers
.length
> 1 then
488 var c
= res
.new_dropdown
("hier", "sub-classes")
489 for x
in in_hierarchy
.smallers
do
490 if x
== self then continue
491 if not x
.is_intro
then continue
492 c
.open
("li").add x
.linkto
(v
)
495 if mclass
.mclassdefs
.length
> 1 then
496 var c
= res
.new_dropdown
("redefs", "refinements")
497 for x
in mclass
.mclassdefs
do
498 if x
== self then continue
499 c
.open
("li").add x
.linkto_text
(v
, "in {x.mmodule}")
505 # The class HTML page (an anchor in the module page)
506 redef fun href
: String
508 return mmodule
.href
+ "#" + to_s
515 var res
= new HInfoBox(v
, to_s
)
516 res
.href
= v
.hrefto
(self)
517 if self isa MMethodDef then
518 if msignature
!= null then res
.new_field
("fun").append
(mproperty
.name
).add msignature
.linkto
(v
)
519 else if self isa MAttributeDef then
520 if static_mtype
!= null then res
.new_field
("fun").append
(mproperty
.name
).add static_mtype
.linkto
(v
)
521 else if self isa MVirtualTypeDef then
522 if bound
!= null then res
.new_field
("add").append
(mproperty
.name
).add bound
.linkto
(v
)
524 res
.new_field
("wat?").append
(mproperty
.name
)
529 res
.new_field
("intro").add mproperty
.intro
.linkto_text
(v
, "in {mproperty.intro.mclassdef}")
532 if mdoc
== null then mdoc
= mproperty
.intro
.mdoc
533 if mdoc
!= null then mdoc
.fill_infobox
(res
)
534 if mproperty
.mpropdefs
.length
> 1 then
535 var c
= res
.new_dropdown
("redef", "redefinitions")
536 for x
in mproperty
.mpropdefs
do
537 c
.open
("li").add x
.linkto_text
(v
, "in {x.mclassdef}")
544 # The property HTML page (an anchor in the module page)
545 redef fun href
: String
547 return self.mclassdef
.mmodule
.href
+ "#" + self.to_s
551 redef class MClassType
554 var res
= new HInfoBox(v
, to_s
)
555 res
.href
= v
.hrefto
(self)
556 res
.new_field
("class").add mclass
.intro
.linkto
(v
)
557 var mdoc
= mclass
.mdoc
558 if mdoc
== null then mdoc
= mclass
.intro
.mdoc
559 if mdoc
!= null then mdoc
.fill_infobox
(res
)
564 return mclass
.intro
.linkto
(v
)
567 redef class MVirtualType
570 var res
= new HInfoBox(v
, to_s
)
571 res
.href
= v
.hrefto
(mproperty
)
574 res
.new_field
("virtual type").add pd
.linkto
(v
)
576 if mdoc
!= null then mdoc
.fill_infobox
(res
)
581 return mproperty
.intro
.linkto
(v
)
584 redef class MParameterType
587 var res
= new HInfoBox(v
, to_s
)
588 res
.new_field
("parameter type").append
("{name} from class ").add mclass
.intro
.linkto
(v
)
593 redef class MNullableType
596 return mtype
.infobox
(v
)
600 var res
= new HTMLTag("span")
601 res
.append
("nullable ").add
(mtype
.linkto
(v
))
606 redef class MNotNullType
609 return mtype
.infobox
(v
)
613 var res
= new HTMLTag("span")
614 res
.append
("not null ").add
(mtype
.linkto
(v
))
619 redef class MNullType
622 var res
= new HInfoBox(v
, to_s
)
627 var res
= new HTMLTag("span")
633 redef class MSignature
636 var res
= new HTMLTag("span")
638 if not mparameters
.is_empty
then
640 for p
in mparameters
do
648 res
.add p
.mtype
.linkto
(v
)
652 var ret
= return_mtype
655 res
.add ret
.linkto
(v
)
664 var res
= new HInfoBox(v
, "call {mpropdef}")
665 res
.href
= v
.hrefto
(mpropdef
)
666 res
.new_field
("call").add
(mpropdef
.linkto
(v
)).add
(msignature
.linkto
(v
))
667 if mpropdef
.is_intro
then
669 res
.new_field
("intro").add mproperty
.intro
.linkto_text
(v
, "in {mproperty.intro.mclassdef}")
671 var mdoc
= mpropdef
.mdoc
672 if mdoc
== null then mdoc
= mproperty
.intro
.mdoc
673 if mdoc
!= null then mdoc
.fill_infobox
(res
)
679 return mpropdef
.linkto
(v
)
687 var declared_type
= self.declared_type
688 if declared_type
== null then
689 var res
= new HInfoBox(v
, "{name}")
690 res
.new_field
("local var").append
("{name}")
693 var res
= new HInfoBox(v
, "{name}: {declared_type}")
694 res
.new_field
("local var").append
("{name}:").add
(declared_type
.linkto
(v
))
703 # Optionally creates a tag that encapsulate the AST element on HTML rendering
704 protected fun make_tag
(v
: HighlightVisitor): nullable HTMLTag do return null
706 # Add aditionnal information on a child-token and return an additionnal HInfoBox on it
707 protected fun decorate_tag
(v
: HighlightVisitor, res
: HTMLTag, token
: Token): nullable HInfoBox
709 #debug("no decoration for {token.inspect}")
710 #res.add_class("nc_error")
714 # Return a optional infobox
715 fun infobox
(v
: HighlightVisitor): nullable HInfoBox do return null
718 redef class AQclassid
719 redef fun decorate_tag
(v
, res
, token
)
721 if token
!= n_id
then return null
722 return parent
.decorate_tag
(v
, res
, token
)
727 redef fun decorate_tag
(v
, res
, token
)
729 if token
!= n_id
then return null
730 return parent
.decorate_tag
(v
, res
, token
)
734 redef class AStdClassdef
735 redef fun make_tag
(v
)
737 var res
= new HTMLTag("span")
738 res
.add_class
("nc_cdef")
740 if md
!= null then res
.attr
("id", md
.to_s
)
743 redef fun decorate_tag
(v
, res
, token
)
745 if not token
isa TClassid then return null
746 res
.add_class
("nc_def")
749 if md
== null then return null
754 redef fun make_tag
(v
)
756 var res
= new HTMLTag("span")
757 res
.add_class
("nc_pdef")
762 res
.attr
("id", mpd
.to_s
)
764 if self isa AAttrPropdef then
766 if mpd
!= null then res
.add
(tag
(mpd
))
768 if mpd
!= null then res
.add
(tag
(mpd
))
773 private fun tag
(mpd
: MPropDef): HTMLTag
775 var a
= new HTMLTag("a")
776 a
.attr
("id", mpd
.to_s
)
782 # Produce an HTMLTag with the correct contents and CSS classes
783 # Subclasses can redefine it to decorate the tag
784 redef fun make_tag
(v
: HighlightVisitor): HTMLTag
786 var res
= new HTMLTag("span")
792 redef class TokenKeyword
793 redef fun make_tag
(v
)
796 res
.add_class
("nc_k")
800 redef class TokenOperator
801 redef fun make_tag
(v
)
804 res
.add_class
("nc_o")
809 redef class AVarFormExpr
810 redef fun decorate_tag
(v
, res
, token
)
812 if token
!= n_id
then return null
813 var variable
= self.variable
814 if variable
== null then return null
815 res
.add_class
("nc_v")
816 return variable
.infobox
(v
)
820 redef class AVardeclExpr
821 redef fun decorate_tag
(v
, res
, token
)
823 if token
!= n_id
then return null
824 var variable
= self.variable
825 if variable
== null then return null
826 res
.add_class
("nc_v")
827 return variable
.infobox
(v
)
831 redef class AForGroup
832 redef fun decorate_tag
(v
, res
, token
)
834 if not token
isa TId then return null
836 if vs
== null then return null
837 res
.add_class
("nc_v")
838 var idx
= n_ids
.index_of
(token
)
839 var variable
= vs
[idx
]
840 return variable
.infobox
(v
)
845 redef fun decorate_tag
(v
, res
, token
)
847 if token
!= n_id
then return null
849 if mp
== null then return null
850 var variable
= self.variable
851 if variable
== null then return null
852 res
.add_class
("nc_v")
853 return variable
.infobox
(v
)
857 redef class AAssertExpr
858 redef fun decorate_tag
(v
, res
, token
)
860 if not token
isa TId then return null
861 res
.add_class
("nc_ast")
867 redef fun decorate_tag
(v
, res
, token
)
869 if not token
isa TId then return null
870 res
.add_class
("nc_la")
875 redef class ASendExpr
876 redef fun decorate_tag
(v
, res
, token
)
878 if callsite
== null then return null
879 return callsite
.infobox
(v
)
884 redef fun decorate_tag
(v
, res
, token
)
886 if callsite
== null then return null
887 return callsite
.infobox
(v
)
891 redef class AAssignOp
892 redef fun decorate_tag
(v
, res
, token
)
895 assert p
isa AReassignFormExpr
897 var callsite
= p
.reassign_callsite
898 if callsite
== null then return null
899 return callsite
.infobox
(v
)
903 redef class AModuleName
904 redef fun decorate_tag
(v
, res
, token
)
906 return parent
.decorate_tag
(v
, res
, token
)
910 redef class AModuledecl
911 redef fun decorate_tag
(v
, res
, token
)
913 if not token
isa TId then return null
914 res
.add_class
("nc_def")
915 res
.add_class
("nc_m")
919 if mm
== null then return null
924 redef class AStdImport
925 redef fun decorate_tag
(v
, res
, token
)
927 if not token
isa TId then return null
928 res
.add_class
("nc_m")
930 if mm
== null then return null
934 redef class AAttrPropdef
935 redef fun decorate_tag
(v
, res
, token
)
937 if not token
isa TId then return null
938 res
.add_class
("nc_def")
939 var mpd
: nullable MPropDef
941 if mpd
== null then mpd
= mpropdef
942 if mpd
== null then return null
943 return mpd
.infobox
(v
)
948 redef fun make_tag
(v
)
951 res
.add_class
("nc_i")
956 redef fun make_tag
(v
)
958 var res
= new HTMLTag("span")
959 res
.add_class
("nc_def")
962 redef fun decorate_tag
(v
, res
, token
)
965 # nothing to decorate
970 if not p
isa AMethPropdef then return null
972 if mpd
== null then return null
973 return mpd
.infobox
(v
)
977 redef fun make_tag
(v
)
980 res
.add_class
("nc_a")
984 redef class AAttrFormExpr
985 redef fun decorate_tag
(v
, res
, token
)
987 if not token
isa TAttrid then return null
989 if p
== null then return null
990 return p
.intro
.infobox
(v
)
994 redef fun make_tag
(v
)
997 res
.add_class
("nc_t")
1002 redef fun decorate_tag
(v
, res
, token
)
1004 if not token
isa TClassid then return null
1006 if mt
== null then return null
1008 if mt
isa MFormalType then
1009 res
.add_class
("nc_vt")
1011 return mt
.infobox
(v
)
1014 redef class AFormaldef
1015 redef fun decorate_tag
(v
, res
, token
)
1017 if not token
isa TClassid then return null
1018 res
.add_class
("nc_vt")
1019 if mtype
== null then return null
1020 return mtype
.infobox
(v
)
1023 redef class ATypePropdef
1024 redef fun decorate_tag
(v
, res
, token
)
1026 if not token
isa TClassid then return null
1027 res
.add_class
("nc_def")
1029 if md
== null then return null
1030 return md
.infobox
(v
)
1033 redef class TComment
1034 redef fun make_tag
(v
)
1038 res
.add_class
("nc_c")
1044 redef fun make_tag
(v
)
1046 var res
= new HTMLTag("span")
1047 res
.add_class
("nc_d")
1051 redef class TokenLiteral
1052 redef fun make_tag
(v
)
1055 res
.add_class
("nc_l")
1059 redef class ASuperstringExpr
1060 redef fun make_tag
(v
)
1062 var res
= new HTMLTag("span")
1063 res
.add_class
("nc_ss")
1067 redef class AStringFormExpr
1068 redef fun decorate_tag
(v
, res
, token
)
1070 # Workaround to tag strings
1071 res
.classes
.remove
("nc_l")
1072 res
.add_class
("nc_s")
1077 redef fun decorate_tag
(v
, res
, token
)
1080 if t
== null then return null