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 # Fully process a content as a nit source file.
24 fun hightlightcode
(hl
: HighlightVisitor, content
: String): HLCode
26 # Prepare a stand-alone tool context
27 var tc
= new ToolContext
28 tc
.nit_dir
= tc
.locate_nit_dir
# still use the common lib to have core
29 tc
.keep_going
= true # no exit, obviously
30 tc
.opt_warn
.value
= -1 # no output, obviously
32 # Prepare an stand-alone model and model builder.
33 # Unfortunately, models are enclosing and append-only.
34 # There is no way (yet?) to have a shared module `core` with
35 # isolated and throwable user modules.
37 var mb
= new ModelBuilder(model
, tc
)
40 var source
= new SourceFile.from_string
("", content
+ "\n")
41 var lexer
= new Lexer(source
)
42 var parser
= new Parser(lexer
)
43 var tree
= parser
.parse
45 var hlcode
= new HLCode(hl
, content
, source
)
49 if eof
isa AError then
50 mb
.error
(eof
, eof
.message
)
51 hl
.hightlight_source
(source
)
54 var amodule
= tree
.n_base
.as(not null)
56 # Load the AST as a module in the model
58 mb
.load_rt_module
(null, amodule
, "")
61 # Highlight the processed module
62 hl
.enter_visit
(amodule
)
66 # A standalone highlighted piece of code
68 # The highlighter used
69 var hl
: HighlightVisitor
74 # The pseudo source-file
75 var source
: SourceFile
77 # JavaScript code to update an existing codemirror editor.
78 fun code_mirror_update
: Template
81 var res
= new Template
83 function nitmessage() {
84 editor.operation(function(){
85 for (var i = 0; i < widgets.length; ++i)
86 editor.removeLineWidget(widgets[i]);
90 for m
in source
.messages
do
92 var l = document.createElement("div");
93 l.className = "lint-error"
94 l.innerHTML = "<span class='glyphicon glyphicon-warning-sign lint-error-icon'></span> {{{m.text.html_escape}}}";
95 var w = editor.addLineWidget({{{m.location.line_start-1}}}, l);
104 # Visitor used to produce a HTML tree based on a AST on a `Source`
105 class HighlightVisitor
106 # The root of the HTML hierarchy
107 var html
= new HTMLTag("span")
109 # Is the HTML include a nested `<span class"{type_of_node}">` element for each `ANode` of the AST?
110 # Used to have a really huge and verbose HTML (mainly for debug)
111 var with_ast
= false is writable
113 # Prefixes used in generated IDs for line `<span>` elements.
114 # Useful if more than one highlighted code is present in the same HTML document.
116 # If set to the empty string, id for lines are disabled.
118 # Is `"L"` by default.
119 var line_id_prefix
= "L" is writable
121 # The first line to generate, null if start at the first line
122 var first_line
: nullable Int = null is writable
124 # The last line to generate, null if finish at the last line
125 var last_line
: nullable Int = null is writable
127 # When highlighting a node, show its messages (errors, warnings), if any.
130 var show_messages
= true is writable
132 # When highlighting a node, attach a full popupable infobox, if any.
134 # If `false`, only a simple `title` tooltip is used.
137 var show_infobox
= true is writable
139 # A reference to an entity used in generated `<a>` elements.
141 # It is used to refer to some specific entities when generating links.
142 # If `null` is returned, then no link are generated and `<a>` elements become `<span>`.
144 # By default, `null` is returned.
145 # Clients are therefore encouraged to redefine the method in a subclass to control where entities should link to.
146 fun hrefto
(entitiy
: MEntity): nullable String do return null
150 html
.add_class
("nitcode")
153 # When highlighting a node, also consider the loose tokens around it.
155 # Loose tokens are tokens discarded from the AST but attached before
156 # or after some non-loose tokens. See `Token::is_loose`.
158 # When this flag is set to `true`, the loose tokens that are before the
159 # first token and after the last token are also highlighted.
162 var include_loose_tokens
= false is writable
164 # When highlighting a node, the first and the last lines are fully included.
166 # If the highlighted node starts (or ends) in the middle of a line,
167 # this flags forces the whole line to be highlighted.
170 var include_whole_lines
= false is writable
172 # The entry-point of the highlighting.
173 # Will fill `html` with the generated HTML content.
174 fun enter_visit
(n
: ANode)
187 if f
== null then return
189 if l
== null then return
192 if include_loose_tokens
then
193 if f
.prev_looses
.not_empty
then f
= f
.prev_looses
.first
194 if l
.next_looses
.not_empty
then l
= l
.next_looses
.last
197 if include_whole_lines
then
198 f
= f
.first_real_token_in_line
199 l
= l
.last_real_token_in_line
205 private fun full_tag
(anode
: ANode, hv
: HighlightVisitor): nullable HTMLTag
207 var tag
= anode
.make_tag
(hv
)
208 if tag
== null then return null
209 var infobox
= anode
.infobox
(hv
)
210 if infobox
== null and anode
isa Token then
211 var pa
= anode
.parent
213 infobox
= pa
.decorate_tag
(hv
, tag
, anode
)
216 if infobox
!= null and not show_infobox
then
217 tag
.attr
("title", infobox
.title
)
218 tag
.classes
.add
"titled"
221 var messages
= anode
.location
.messages
222 if messages
!= null and show_messages
then
223 tag
.css
("border-bottom", "solid 2px red")
224 if infobox
== null then
225 infobox
= new HInfoBox(hv
, "Messages")
227 var c
= infobox
.new_dropdown
("{messages.length} message(s)", "")
229 c
.open
("li").append
(m
.text
)
232 if infobox
!= null then
233 tag
.attach_infobox
(infobox
)
238 # Highlight a full lexed source file.
240 # REQUIRE `source.first_token != null`
241 fun hightlight_source
(source
: SourceFile)
243 htmlize
(source
.first_token
.as(not null), null)
246 # Produce HTML between two tokens
247 protected fun htmlize
(first_token
: Token, last_token
: nullable Token)
249 var stack2
= new Array[HTMLTag]
250 var stack
= new Array[Prod]
252 var c
: nullable Token = first_token
257 # Handle start of line
258 var cline
= c
.location
.line_start
259 if cline
!= line
then
260 # Handle starting block productions,
261 # Because c could be a detached token, get prods in
262 # the first AST token
263 var c0
= c
.first_token_in_line
265 if c0
!= null then starting
= c0
.starting_prods
266 if starting
!= null then for p
in starting
do
267 if not p
.is_block
then continue
268 var tag
= full_tag
(p
, hv
)
269 if tag
== null then continue
270 tag
.add_class
("foldable")
277 # Add a div for the whole line
278 var tag
= new HTMLTag("span")
279 var p
= line_id_prefix
280 if p
!= "" then tag
.attrs
["id"] = "{p}{cline}"
281 tag
.classes
.add
"line"
288 # Add the blank, verbatim
289 html
.add_raw_html c
.blank_before
291 # Handle starting span production
292 starting
= c
.starting_prods
293 if starting
!= null then for p
in starting
do
294 if not p
.is_span
then continue
295 var tag
= full_tag
(p
, hv
)
296 if tag
== null then continue
307 var tag
= full_tag
(c
, hv
)
308 if tag
!= null then html
.add tag
311 # Handle ending span productions
312 var ending
= c
.ending_prods
313 if ending
!= null then for p
in ending
do
314 if not p
.is_span
then continue
315 if stack
.is_empty
or p
!= stack
.last
then continue
320 # Handle end of line and end of file
322 if c
== last_token
then n
= null
323 if n
== null or n
.location
.line_start
!= line
then
324 # closes the line div
327 # close the block production divs
328 var c0
= c
.last_token_in_line
330 if c0
!= null then ending
= c0
.ending_prods
331 if ending
!= null then for p
in ending
do
332 if not p
.is_block
then continue
333 if stack
.is_empty
or p
!= stack
.last
then continue
341 #assert stack.is_empty
342 #assert stack2.is_empty
345 # Return a default CSS content related to CSS classes used in the `html` tree.
346 # Could be inlined in the `.html` file of saved as a specific `.css` file.
347 fun css_content
: String
350 .nitcode a { color: inherit; cursor:pointer; }
351 .nitcode .titled:hover { text-decoration: underline; } /* underline titles */
352 .nitcode .popupable:hover { text-decoration: underline; cursor:help; } /* underline titles */
353 .nitcode .foldable { display: block } /* for block productions*/
354 .nitcode .line{ display: block } /* for lines */
355 .nitcode .line:hover{ background-color: #FFFFE0; } /* current line */
356 .nitcode :target { background-color: #FFF3C2 } /* target highlight*/
357 /* lexical raw tokens. independent of usage or semantic: */
358 .nitcode .nc_c { color: gray; font-style: italic; } /* comment */
359 .nitcode .nc_d { color: #3D8127; font-style: italic; } /* documentation comments */
360 .nitcode .nc_k { font-weight: bold; } /* keyword */
361 .nitcode .nc_o {} /* operator */
362 .nitcode .nc_i {} /* standard identifier */
363 .nitcode .nc_t { color: #445588; font-weight: bold; } /* type/class identifier */
364 .nitcode .nc_a { color: #445588; font-style: italic; } /* old style attribute identifier */
365 .nitcode .nc_l { color: #009999; } /* char and number literal */
366 .nitcode .nc_s { color: #8F1546; } /* string literal */
367 /* syntactic token usage. added because of their position in the AST */
368 .nitcode .nc_ast { color: blue; } /* assert label */
369 .nitcode .nc_la { color: blue; } /* break/continue label */
370 .nitcode .nc_m { color: #445588; } /* module name */
371 /* syntactic groups */
372 .nitcode .nc_def { font-weight: bold; color: blue; } /* name used in a definition */
373 .nitcode .nc_def.nc_a { color: blue; } /* name used in a attribute definition */
374 .nitcode .nc_def.nc_t { color: blue; } /* name used in a class or vt definition */
375 .nitcode .nc_ss { color: #9E6BEB; } /* superstrings */
376 .nitcode .nc_cdef {} /* A whole class definition */
377 .nitcode .nc_pdef {} /* A whole property definition */
378 /* semantic token usage */
379 .nitcode .nc_v { font-style: italic; } /* local variable or parameter */
380 .nitcode .nc_vt { font-style: italic; } /* virtual type or formal type */
382 .nitcode .nc_error { border: 1px red solid;} /* not used */
383 .popover { max-width: 800px !important; }
387 # Additional content to inject in the <head> tag
388 # Note: does not include `css_content`; handle it yourself.
389 fun head_content
: String
391 return """<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">\n"""
394 # Additional content to inject just before the closing </body> tag
395 fun foot_content
: String
398 <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
399 <script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
400 <script>$(".popupable").popover({html:true, placement:'top'})/*initialize bootstrap popover*/</script>"""
405 # Attach the infobox to the node by using BootStrap popover
406 fun attach_infobox
(infobox
: HInfoBox)
408 classes
.add
("popupable")
409 attrs
["title"] = infobox
.title
410 var href
= infobox
.href
412 attrs
["data-title"] = """<a href="{{{href}}}">{{{infobox.title}}}</a>"""
414 attrs
["data-content"] = infobox
.content
.write_to_string
415 attrs
["data-toggle"] = "popover"
420 # A generic information container that can be used to decorate AST entities
422 # The visitor used for contextualisation, if needed
423 var visitor
: HighlightVisitor
425 # A short title for the AST element
428 # The primary link where the entity points
430 var href
: nullable String = null
432 # The content of the popuped infobox
433 var content
= new HTMLTag("div")
435 # Append a new field in the popuped infobox
436 fun new_field
(title
: String): HTMLTag
438 content
.open
("b").text
(title
)
440 var res
= content
.open
("span")
445 # Append a new dropdown in the popuped content
446 fun new_dropdown
(title
, text
: String): HTMLTag
448 content
.add_raw_html
"""<div class="dropdown"> <a data-toggle="dropdown" href="#"><b>"""
449 content
.append
(title
)
450 content
.add_raw_html
"</b> "
452 content
.add_raw_html
"""<span class="caret"></span></a>"""
453 var res
= content
.open
("ul").add_class
("dropdown-menu").attr
("role", "menu").attr
("aria-labelledby", "dLabel")
454 content
.add_raw_html
"</div>"
461 # Model entity or whatever that can produce an infobox
462 interface HInfoBoxable
463 # An new infobox documenting the entity
464 fun infobox
(v
: HighlightVisitor): HInfoBox is abstract
468 # Append an entry for the doc in the given infobox
469 fun fill_infobox
(res
: HInfoBox)
471 if content
.length
< 2 then
472 res
.new_field
("doc").text
(content
.first
)
475 var c
= res
.new_dropdown
("doc", content
.first
)
476 for x
in content
.iterator
.skip_head
(1) do
478 c
.add_raw_html
"<br>"
486 # A HTML version of `to_s` with hyper-links.
488 # By default, `linkto_text(v, to_s)` is used, c.f. see `linkto_text`.
490 # For some complex entities, like generic types, multiple `<a>` and `<span>` elements can be generated.
491 # E.g. `Array[Int]` might become `<a>Array</a>[<a>Int</a>]` with the correct `href` attributes
492 # provided by `v.hrefto`.
493 fun linkto
(v
: HighlightVisitor): HTMLTag do return linkto_text
(v
, to_s
)
495 # Link to the `self` with a specific text.
497 # The whole text is linked with a single `<a>` element.
499 # The `href` used is provided by `v.hrefto`.
500 # If `href` is null then a `<span>` element is used instead of `<a>`.
501 fun linkto_text
(v
: HighlightVisitor, text
: String): HTMLTag
503 var href
= v
.hrefto
(self)
505 return (new HTMLTag("span")).text
(text
)
507 return (new HTMLTag("a")).attr
("href", href
).text
(text
)
510 # Append an entry for the doc in the given infobox
511 private fun add_doc_to_infobox
(res
: HInfoBox)
513 var mdoc
= mdoc_or_fallback
514 if mdoc
!= null then mdoc
.fill_infobox
(res
)
521 var res
= new HInfoBox(v
, "module {name}")
522 res
.href
= v
.hrefto
(self)
523 res
.new_field
("module").add
(linkto
(v
))
524 add_doc_to_infobox
(res
)
525 if in_importation
.greaters
.length
> 1 then
526 var c
= res
.new_dropdown
("imports", "{in_importation.greaters.length-1} modules")
527 for x
in in_importation
.greaters
do
528 if x
== self then continue
529 c
.open
("li").add x
.linkto
(v
)
535 redef fun linkto
(v
) do return linkto_text
(v
, name
)
538 redef class MClassDef
541 var res
= new HInfoBox(v
, "class {mclass.name}")
542 res
.href
= v
.hrefto
(self)
544 res
.new_field
("class").text
(mclass
.name
)
546 res
.new_field
("redef class").text
(mclass
.name
)
547 res
.new_field
("intro").add mclass
.intro
.linkto_text
(v
, "in {mclass.intro_mmodule.to_s}")
549 add_doc_to_infobox
(res
)
551 var in_hierarchy
= self.in_hierarchy
552 if in_hierarchy
== null then return res
554 if in_hierarchy
.greaters
.length
> 1 then
555 var c
= res
.new_dropdown
("hier", "super-classes")
556 for x
in in_hierarchy
.greaters
do
557 if x
== self then continue
558 if not x
.is_intro
then continue
559 c
.open
("li").add x
.linkto
(v
)
562 if in_hierarchy
.smallers
.length
> 1 then
563 var c
= res
.new_dropdown
("hier", "sub-classes")
564 for x
in in_hierarchy
.smallers
do
565 if x
== self then continue
566 if not x
.is_intro
then continue
567 c
.open
("li").add x
.linkto
(v
)
570 if mclass
.mclassdefs
.length
> 1 then
571 var c
= res
.new_dropdown
("redefs", "refinements")
572 for x
in mclass
.mclassdefs
do
573 if x
== self then continue
574 c
.open
("li").add x
.linkto_text
(v
, "in {x.mmodule}")
584 var res
= new HInfoBox(v
, to_s
)
585 res
.href
= v
.hrefto
(self)
586 if self isa MMethodDef then
587 var msignature
= self.msignature
588 if msignature
!= null then res
.new_field
("fun").append
(mproperty
.name
).add msignature
.linkto
(v
)
589 else if self isa MAttributeDef then
590 var static_mtype
= self.static_mtype
591 if static_mtype
!= null then res
.new_field
("fun").append
(mproperty
.name
).add static_mtype
.linkto
(v
)
592 else if self isa MVirtualTypeDef then
593 var bound
= self.bound
594 if bound
!= null then res
.new_field
("add").append
(mproperty
.name
).add bound
.linkto
(v
)
596 res
.new_field
("wat?").append
(mproperty
.name
)
601 res
.new_field
("intro").add mproperty
.intro
.linkto_text
(v
, "in {mproperty.intro.mclassdef}")
603 add_doc_to_infobox
(res
)
604 if mproperty
.mpropdefs
.length
> 1 then
605 var c
= res
.new_dropdown
("redef", "redefinitions")
606 for x
in mproperty
.mpropdefs
do
607 c
.open
("li").add x
.linkto_text
(v
, "in {x.mclassdef}")
615 redef class MClassType
618 var res
= new HInfoBox(v
, to_s
)
619 res
.href
= v
.hrefto
(self)
620 res
.new_field
("class").add mclass
.intro
.linkto
(v
)
621 add_doc_to_infobox
(res
)
626 return mclass
.intro
.linkto
(v
)
629 redef class MVirtualType
632 var res
= new HInfoBox(v
, to_s
)
633 res
.href
= v
.hrefto
(mproperty
)
635 add_doc_to_infobox
(res
)
636 if mdoc
!= null then mdoc
.fill_infobox
(res
)
641 return mproperty
.intro
.linkto
(v
)
644 redef class MParameterType
647 var res
= new HInfoBox(v
, to_s
)
648 res
.new_field
("parameter type").append
("{name} from class ").add mclass
.intro
.linkto
(v
)
653 redef class MNullableType
656 return mtype
.infobox
(v
)
660 var res
= new HTMLTag("span")
661 res
.append
("nullable ").add
(mtype
.linkto
(v
))
666 redef class MNotNullType
669 return mtype
.infobox
(v
)
673 var res
= new HTMLTag("span")
674 res
.append
("not null ").add
(mtype
.linkto
(v
))
679 redef class MNullType
682 var res
= new HInfoBox(v
, to_s
)
687 var res
= new HTMLTag("span")
693 redef class MSignature
696 var res
= new HTMLTag("span")
698 if not mparameters
.is_empty
then
700 for p
in mparameters
do
708 res
.add p
.mtype
.linkto
(v
)
712 var ret
= return_mtype
715 res
.add ret
.linkto
(v
)
724 var res
= new HInfoBox(v
, "call {mpropdef}")
725 res
.href
= v
.hrefto
(mpropdef
)
726 res
.new_field
("call").add
(mpropdef
.linkto
(v
)).add
(msignature
.linkto
(v
))
727 if mpropdef
.is_intro
then
729 res
.new_field
("intro").add mproperty
.intro
.linkto_text
(v
, "in {mproperty.intro.mclassdef}")
731 add_doc_to_infobox
(res
)
737 return mpropdef
.linkto
(v
)
745 var declared_type
= self.declared_type
746 if declared_type
== null then
747 var res
= new HInfoBox(v
, "{name}")
748 res
.new_field
("local var").append
("{name}")
751 var res
= new HInfoBox(v
, "{name}: {declared_type}")
752 res
.new_field
("local var").append
("{name}:").add
(declared_type
.linkto
(v
))
761 # Optionally creates a tag that encapsulate the AST element on HTML rendering
762 protected fun make_tag
(v
: HighlightVisitor): nullable HTMLTag do return null
764 # Add aditionnal information on a child-token and return an additionnal HInfoBox on it
765 protected fun decorate_tag
(v
: HighlightVisitor, res
: HTMLTag, token
: Token): nullable HInfoBox
767 #debug("no decoration for {token.inspect}")
768 #res.add_class("nc_error")
772 # Return a optional infobox
773 fun infobox
(v
: HighlightVisitor): nullable HInfoBox do return null
776 redef class AQclassid
777 redef fun decorate_tag
(v
, res
, token
)
779 if token
!= n_id
then return null
780 var parent
= self.parent
781 if parent
== null then return null
782 return parent
.decorate_tag
(v
, res
, token
)
787 redef fun decorate_tag
(v
, res
, token
)
789 if token
!= n_id
then return null
790 var parent
= self.parent
791 if parent
== null then return null
792 return parent
.decorate_tag
(v
, res
, token
)
796 redef class AStdClassdef
797 redef fun make_tag
(v
)
799 var res
= new HTMLTag("span")
800 res
.add_class
("nc_cdef")
802 if md
!= null then res
.attr
("id", md
.to_s
)
805 redef fun decorate_tag
(v
, res
, token
)
807 if not token
isa TClassid then return null
808 res
.add_class
("nc_def")
811 if md
== null then return null
816 redef fun make_tag
(v
)
818 var res
= new HTMLTag("span")
819 res
.add_class
("nc_pdef")
824 res
.attr
("id", mpd
.to_s
)
826 if self isa AAttrPropdef then
828 if mpd
!= null then res
.add
(tag
(mpd
))
830 if mpd
!= null then res
.add
(tag
(mpd
))
835 private fun tag
(mpd
: MPropDef): HTMLTag
837 var a
= new HTMLTag("a")
838 a
.attr
("id", mpd
.to_s
)
844 # Produce an HTMLTag with the correct contents and CSS classes
845 # Subclasses can redefine it to decorate the tag
846 redef fun make_tag
(v
): HTMLTag
848 var res
= new HTMLTag("span")
854 redef class TokenKeyword
855 redef fun make_tag
(v
)
858 res
.add_class
("nc_k")
862 redef class TokenOperator
863 redef fun make_tag
(v
)
866 res
.add_class
("nc_o")
871 redef class AVarFormExpr
872 redef fun decorate_tag
(v
, res
, token
)
874 if token
!= n_id
then return null
875 var variable
= self.variable
876 if variable
== null then return null
877 res
.add_class
("nc_v")
878 return variable
.infobox
(v
)
882 redef class AVardeclExpr
883 redef fun decorate_tag
(v
, res
, token
)
885 if token
!= n_id
then return null
886 var variable
= self.variable
887 if variable
== null then return null
888 res
.add_class
("nc_v")
889 return variable
.infobox
(v
)
893 redef class AForGroup
894 redef fun decorate_tag
(v
, res
, token
)
896 if not token
isa TId then return null
898 if vs
== null then return null
899 res
.add_class
("nc_v")
900 var idx
= n_ids
.index_of
(token
)
901 var variable
= vs
[idx
]
902 return variable
.infobox
(v
)
907 redef fun decorate_tag
(v
, res
, token
)
909 if token
!= n_id
then return null
911 if mp
== null then return null
912 var variable
= self.variable
913 if variable
== null then return null
914 res
.add_class
("nc_v")
915 return variable
.infobox
(v
)
919 redef class AAssertExpr
920 redef fun decorate_tag
(v
, res
, token
)
922 if not token
isa TId then return null
923 res
.add_class
("nc_ast")
929 redef fun decorate_tag
(v
, res
, token
)
931 if not token
isa TId then return null
932 res
.add_class
("nc_la")
937 redef class ASendExpr
938 redef fun decorate_tag
(v
, res
, token
)
940 var callsite
= self.callsite
941 if callsite
== null then return null
942 return callsite
.infobox
(v
)
947 redef fun decorate_tag
(v
, res
, token
)
949 var callsite
= self.callsite
950 if callsite
== null then return null
951 return callsite
.infobox
(v
)
955 redef class AAssignOp
956 redef fun decorate_tag
(v
, res
, token
)
959 assert p
isa AReassignFormExpr
961 var callsite
= p
.reassign_callsite
962 if callsite
== null then return null
963 return callsite
.infobox
(v
)
967 redef class AModuleName
968 redef fun decorate_tag
(v
, res
, token
)
971 if p
== null then return null
972 return p
.decorate_tag
(v
, res
, token
)
976 redef class AModuledecl
977 redef fun decorate_tag
(v
, res
, token
)
979 if not token
isa TId then return null
980 res
.add_class
("nc_def")
981 res
.add_class
("nc_m")
985 if mm
== null then return null
990 redef class AStdImport
991 redef fun decorate_tag
(v
, res
, token
)
993 if not token
isa TId then return null
994 res
.add_class
("nc_m")
996 if mm
== null then return null
1000 redef class AAttrPropdef
1001 redef fun decorate_tag
(v
, res
, token
)
1003 if not token
isa TId then return null
1004 res
.add_class
("nc_def")
1005 var mpd
: nullable MPropDef
1007 if mpd
== null then mpd
= mpropdef
1008 if mpd
== null then return null
1009 return mpd
.infobox
(v
)
1014 redef fun make_tag
(v
)
1017 res
.add_class
("nc_i")
1022 redef fun make_tag
(v
)
1024 var res
= new HTMLTag("span")
1025 res
.add_class
("nc_def")
1028 redef fun decorate_tag
(v
, res
, token
)
1031 # nothing to decorate
1033 redef fun infobox
(v
)
1036 if not p
isa AMethPropdef then return null
1037 var mpd
= p
.mpropdef
1038 if mpd
== null then return null
1039 return mpd
.infobox
(v
)
1043 redef fun make_tag
(v
)
1046 res
.add_class
("nc_a")
1050 redef class AAttrFormExpr
1051 redef fun decorate_tag
(v
, res
, token
)
1053 if not token
isa TAttrid then return null
1055 if p
== null then return null
1056 return p
.intro
.infobox
(v
)
1059 redef class TClassid
1060 redef fun make_tag
(v
)
1063 res
.add_class
("nc_t")
1068 redef fun decorate_tag
(v
, res
, token
)
1070 if not token
isa TClassid then return null
1072 if mt
== null then return null
1074 if mt
isa MFormalType then
1075 res
.add_class
("nc_vt")
1077 return mt
.infobox
(v
)
1080 redef class AFormaldef
1081 redef fun decorate_tag
(v
, res
, token
)
1083 if not token
isa TClassid then return null
1084 res
.add_class
("nc_vt")
1085 var mtype
= self.mtype
1086 if mtype
== null then return null
1087 return mtype
.infobox
(v
)
1090 redef class ATypePropdef
1091 redef fun decorate_tag
(v
, res
, token
)
1093 if not token
isa TClassid then return null
1094 res
.add_class
("nc_def")
1096 if md
== null then return null
1097 return md
.infobox
(v
)
1100 redef class TComment
1101 redef fun make_tag
(v
)
1105 res
.add_class
("nc_c")
1111 redef fun make_tag
(v
)
1113 var res
= new HTMLTag("span")
1114 res
.add_class
("nc_d")
1118 redef class TokenLiteral
1119 redef fun make_tag
(v
)
1122 res
.add_class
("nc_l")
1126 redef class ASuperstringExpr
1127 redef fun make_tag
(v
)
1129 var res
= new HTMLTag("span")
1130 res
.add_class
("nc_ss")
1134 redef class AStringFormExpr
1135 redef fun decorate_tag
(v
, res
, token
)
1137 # Workaround to tag strings
1138 res
.classes
.remove
("nc_l")
1139 res
.add_class
("nc_s")
1144 redef fun decorate_tag
(v
, res
, token
)
1147 if t
== null then return null