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
24 # Fully process a content as a nit source file.
25 fun hightlightcode
(hl
: HighlightVisitor, content
: String): HLCode
27 # Prepare a stand-alone tool context
28 var tc
= new ToolContext
29 tc
.nit_dir
= tc
.locate_nit_dir
# still use the common lib to have core
30 tc
.keep_going
= true # no exit, obviously
31 tc
.opt_warn
.value
= -1 # no output, obviously
33 # Prepare an stand-alone model and model builder.
34 # Unfortunately, models are enclosing and append-only.
35 # There is no way (yet?) to have a shared module `core` with
36 # isolated and throwable user modules.
38 var mb
= new ModelBuilder(model
, tc
)
41 var source
= new SourceFile.from_string
("", content
+ "\n")
42 var lexer
= new Lexer(source
)
43 var parser
= new Parser(lexer
)
44 var tree
= parser
.parse
46 var hlcode
= new HLCode(hl
, content
, source
)
50 if eof
isa AError then
51 mb
.error
(eof
, eof
.message
)
52 hl
.hightlight_source
(source
)
55 var amodule
= tree
.n_base
.as(not null)
57 # Load the AST as a module in the model
59 mb
.load_rt_module
(null, amodule
, "")
62 # Highlight the processed module
63 hl
.enter_visit
(amodule
)
67 # A standalone highlighted piece of code
71 # The highlighter used
72 var hl
: HighlightVisitor
77 # The pseudo source-file
78 var source
: SourceFile
80 # JavaScript code to update an existing codemirror editor.
81 fun code_mirror_update
: Template
84 var res
= new Template
86 function nitmessage() {
87 editor.operation(function(){
88 for (var i = 0; i < widgets.length; ++i)
89 editor.removeLineWidget(widgets[i]);
93 for m
in source
.messages
do
95 var l = document.createElement("div");
96 l.className = "lint-error"
97 l.innerHTML = "<span class='glyphicon glyphicon-warning-sign lint-error-icon'></span> {{{m.text.html_escape}}}";
98 var w = editor.addLineWidget({{{m.location.line_start-1}}}, l);
106 redef fun core_serialize_to
(v
)
108 v
.serialize_attribute
("code", hl
.html
.write_to_string
)
109 var msgs
= new Array[Map[String, Serializable]]
110 for m
in source
.messages
do
111 var o
= new Map[String, Serializable]
113 o
["line"] = m
.location
.line_start-1
114 o
["message"] = m
.text
116 v
.serialize_attribute
("messages", msgs
)
120 # Visitor used to produce a HTML tree based on a AST on a `Source`
121 class HighlightVisitor
122 # The root of the HTML hierarchy
123 var html
= new HTMLTag("span")
125 # Should the HTML include a nested `<span class"{type_of_node}">` element for each `ANode` of the AST?
127 # Used to have a really huge and verbose HTML (mainly for debug)
128 var with_ast
= false is writable
130 # Prefixes used in generated IDs for line `<span>` elements.
131 # Useful if more than one highlighted code is present in the same HTML document.
133 # If set to the empty string, id for lines are disabled.
135 # Is `"L"` by default.
136 var line_id_prefix
= "L" is writable
138 # The first line to generate, null if start at the first line
139 var first_line
: nullable Int = null is writable
141 # The last line to generate, null if finish at the last line
142 var last_line
: nullable Int = null is writable
144 # When highlighting a node, show its messages (errors, warnings), if any.
147 var show_messages
= true is writable
149 # When highlighting a node, attach a full popupable infobox, if any.
151 # If `false`, only a simple `title` tooltip is used.
154 var show_infobox
= true is writable
156 # A reference to an entity used in generated `<a>` elements.
158 # It is used to refer to some specific entities when generating links.
159 # If `null` is returned, then no link are generated and `<a>` elements become `<span>`.
161 # By default, `null` is returned.
162 # Clients are therefore encouraged to redefine the method in a subclass to control where entities should link to.
163 fun hrefto
(entity
: MEntity): nullable String do return null
167 html
.add_class
("nitcode")
170 # When highlighting a node, also consider the loose tokens around it.
172 # Loose tokens are tokens discarded from the AST but attached before
173 # or after some non-loose tokens. See `Token::is_loose`.
175 # When this flag is set to `true`, the loose tokens that are before the
176 # first token and after the last token are also highlighted.
179 var include_loose_tokens
= false is writable
181 # When highlighting a node, the first and the last lines are fully included.
183 # If the highlighted node starts (or ends) in the middle of a line,
184 # this flags forces the whole line to be highlighted.
187 var include_whole_lines
= false is writable
189 # The entry-point of the highlighting.
190 # Will fill `html` with the generated HTML content.
191 fun enter_visit
(n
: ANode)
204 if f
== null then return
206 if l
== null then return
209 if include_loose_tokens
then
210 if f
.prev_looses
.not_empty
then f
= f
.prev_looses
.first
211 if l
.next_looses
.not_empty
then l
= l
.next_looses
.last
214 var line
= first_line
216 while f
.location
.line_start
< line
do
218 if f
== null then return
224 while l
.location
.line_end
> line
do
226 if l
== null then return
230 if include_whole_lines
then
231 f
= f
.first_real_token_in_line
232 l
= l
.last_real_token_in_line
238 private fun full_tag
(anode
: ANode, hv
: HighlightVisitor): nullable HTMLTag
240 var tag
= anode
.make_tag
(hv
)
241 if tag
== null then return null
242 var infobox
= anode
.infobox
(hv
)
243 if infobox
== null and anode
isa Token then
244 var pa
= anode
.parent
246 infobox
= pa
.decorate_tag
(hv
, tag
, anode
)
249 if infobox
!= null and not show_infobox
then
250 tag
.attr
("title", infobox
.title
)
251 tag
.classes
.add
"titled"
254 var messages
= anode
.location
.messages
255 if messages
!= null and show_messages
then
256 tag
.css
("border-bottom", "solid 2px red")
257 if infobox
== null then
258 infobox
= new HInfoBox(hv
, "Messages")
260 var c
= infobox
.new_dropdown
("{messages.length} message(s)", "")
262 c
.open
("li").append
(m
.text
)
265 if infobox
!= null then
266 tag
.attach_infobox
(infobox
)
271 # Highlight a full lexed source file.
273 # REQUIRE `source.first_token != null`
274 fun hightlight_source
(source
: SourceFile)
276 htmlize
(source
.first_token
.as(not null), null)
279 # Produce HTML between two tokens
280 protected fun htmlize
(first_token
: Token, last_token
: nullable Token)
282 var stack2
= new Array[HTMLTag]
283 var stack
= new Array[Prod]
285 var c
: nullable Token = first_token
290 # Handle start of line
291 var cline
= c
.location
.line_start
292 if cline
!= line
then
293 # Handle starting block productions,
294 # Because c could be a detached token, get prods in
295 # the first AST token
296 var c0
= c
.first_token_in_line
298 if c0
!= null then starting
= c0
.starting_prods
299 if starting
!= null then for p
in starting
do
300 if not p
.is_block
then continue
301 var tag
= full_tag
(p
, hv
)
302 if tag
== null then continue
303 tag
.add_class
("foldable")
310 # Add a div for the whole line
311 var tag
= new HTMLTag("span")
312 var p
= line_id_prefix
313 if p
!= "" then tag
.attrs
["id"] = "{p}{cline}"
314 tag
.classes
.add
"line"
321 # Add the blank, verbatim
322 html
.add_raw_html c
.blank_before
324 # Handle starting span production
325 starting
= c
.starting_prods
326 if starting
!= null then for p
in starting
do
327 if not p
.is_span
then continue
328 var tag
= full_tag
(p
, hv
)
329 if tag
== null then continue
340 var tag
= full_tag
(c
, hv
)
341 if tag
!= null then html
.add tag
344 # Handle ending span productions
345 var ending
= c
.ending_prods
346 if ending
!= null then for p
in ending
do
347 if not p
.is_span
then continue
348 if stack
.is_empty
or p
!= stack
.last
then continue
353 # Handle end of line and end of file
355 if c
== last_token
then n
= null
356 if n
== null or n
.location
.line_start
!= line
then
357 # closes the line div
360 # close the block production divs
361 var c0
= c
.last_token_in_line
363 if c0
!= null then ending
= c0
.ending_prods
364 if ending
!= null then for p
in ending
do
365 if not p
.is_block
then continue
366 if stack
.is_empty
or p
!= stack
.last
then continue
374 if not stack2
.is_empty
then html
= stack2
.first
377 # Return a default CSS content related to CSS classes used in the `html` tree.
378 # Could be inlined in the `.html` file of saved as a specific `.css` file.
379 fun css_content
: String
382 .nitcode a { color: inherit; cursor:pointer; }
383 .nitcode .titled:hover { text-decoration: underline; } /* underline titles */
384 .nitcode .popupable:hover { text-decoration: underline; cursor:help; } /* underline titles */
385 .nitcode .foldable { display: block } /* for block productions*/
386 .nitcode .line{ display: block } /* for lines */
387 .nitcode .line:hover{ background-color: #FFFFE0; } /* current line */
388 .nitcode :target { background-color: #FFF3C2 } /* target highlight*/
389 /* lexical raw tokens. independent of usage or semantic: */
390 .nitcode .nc_c { color: gray; font-style: italic; } /* comment */
391 .nitcode .nc_d { color: #3D8127; font-style: italic; } /* documentation comments */
392 .nitcode .nc_k { font-weight: bold; } /* keyword */
393 .nitcode .nc_o {} /* operator */
394 .nitcode .nc_i {} /* standard identifier */
395 .nitcode .nc_t { color: #445588; font-weight: bold; } /* type/class identifier */
396 .nitcode .nc_a { color: #445588; font-style: italic; } /* old style attribute identifier */
397 .nitcode .nc_l { color: #009999; } /* char and number literal */
398 .nitcode .nc_s { color: #8F1546; } /* string literal */
399 /* syntactic token usage. added because of their position in the AST */
400 .nitcode .nc_ast { color: blue; } /* assert label */
401 .nitcode .nc_la { color: blue; } /* break/continue label */
402 .nitcode .nc_m { color: #445588; } /* module name */
403 /* syntactic groups */
404 .nitcode .nc_def { font-weight: bold; color: blue; } /* name used in a definition */
405 .nitcode .nc_def.nc_a { color: blue; } /* name used in a attribute definition */
406 .nitcode .nc_def.nc_t { color: blue; } /* name used in a class or vt definition */
407 .nitcode .nc_ss { color: #9E6BEB; } /* superstrings */
408 .nitcode .nc_cdef {} /* A whole class definition */
409 .nitcode .nc_pdef {} /* A whole property definition */
410 /* semantic token usage */
411 .nitcode .nc_v { font-style: italic; } /* local variable or parameter */
412 .nitcode .nc_vt { font-style: italic; } /* virtual type or formal type */
414 .nitcode .nc_error { border: 1px red solid;} /* not used */
415 .popover { max-width: 800px !important; }
419 # Additional content to inject in the <head> tag
420 # Note: does not include `css_content`; handle it yourself.
421 fun head_content
: String
423 return """<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">\n"""
426 # Additional content to inject just before the closing </body> tag
427 fun foot_content
: String
430 <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
431 <script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
432 <script>$(".popupable").popover({html:true, placement:'top'})/*initialize bootstrap popover*/</script>"""
437 # Attach the infobox to the node by using BootStrap popover
438 fun attach_infobox
(infobox
: HInfoBox)
440 classes
.add
("popupable")
441 attrs
["title"] = infobox
.title
442 var href
= infobox
.href
444 attrs
["data-title"] = """<a href="{{{href}}}">{{{infobox.title}}}</a>"""
446 attrs
["data-content"] = infobox
.content
.write_to_string
447 attrs
["data-toggle"] = "popover"
452 # A generic information container that can be used to decorate AST entities
454 # The visitor used for contextualisation, if needed
455 var visitor
: HighlightVisitor
457 # A short title for the AST element
460 # The primary link where the entity points
462 var href
: nullable String = null
464 # The content of the popuped infobox
465 var content
= new HTMLTag("div")
467 # Append a new field in the popuped infobox
468 fun new_field
(title
: String): HTMLTag
470 content
.open
("b").text
(title
)
472 var res
= content
.open
("span")
477 # Append a new dropdown in the popuped content
478 fun new_dropdown
(title
, text
: String, text_is_html
: nullable Bool): HTMLTag
480 content
.add_raw_html
"""<div class="dropdown"> <a data-toggle="dropdown" href="#"><b>"""
481 content
.append
(title
)
482 content
.add_raw_html
"</b> "
483 if text_is_html
== true then
484 content
.add_raw_html
(text
)
485 else content
.append
(text
)
486 content
.add_raw_html
"""<span class="caret"></span></a>"""
487 var res
= content
.open
("ul").add_class
("dropdown-menu").attr
("role", "menu").attr
("aria-labelledby", "dLabel")
488 content
.add_raw_html
"</div>"
495 # Model entity or whatever that can produce an infobox
496 interface HInfoBoxable
497 # An new infobox documenting the entity
498 fun infobox
(v
: HighlightVisitor): HInfoBox is abstract
502 # Append an entry for the doc in the given infobox
503 fun fill_infobox
(res
: HInfoBox)
505 if content
.length
< 2 then
506 res
.new_field
("doc").text
(content
.first
)
509 var c
= res
.new_dropdown
("doc", content
.first
)
510 for x
in content
.iterator
.skip_head
(1) do
512 c
.add_raw_html
"<br>"
520 # A HTML version of `to_s` with hyper-links.
522 # By default, `linkto_text(v, to_s)` is used, c.f. see `linkto_text`.
524 # For some complex entities, like generic types, multiple `<a>` and `<span>` elements can be generated.
525 # E.g. `Array[Int]` might become `<a>Array</a>[<a>Int</a>]` with the correct `href` attributes
526 # provided by `v.hrefto`.
527 fun linkto
(v
: HighlightVisitor): HTMLTag do return linkto_text
(v
, to_s
)
529 # Link to the `self` with a specific text.
531 # The whole text is linked with a single `<a>` element.
533 # The `href` used is provided by `v.hrefto`.
534 # If `href` is null then a `<span>` element is used instead of `<a>`.
535 fun linkto_text
(v
: HighlightVisitor, text
: String): HTMLTag
537 var href
= v
.hrefto
(self)
539 return (new HTMLTag("span")).text
(text
)
541 return (new HTMLTag("a")).attr
("href", href
).text
(text
)
544 # Append an entry for the doc in the given infobox
545 private fun add_doc_to_infobox
(res
: HInfoBox)
547 var mdoc
= mdoc_or_fallback
548 if mdoc
!= null then mdoc
.fill_infobox
(res
)
555 var res
= new HInfoBox(v
, "module {name}")
556 res
.href
= v
.hrefto
(self)
557 res
.new_field
("module").add
(linkto
(v
))
558 add_doc_to_infobox
(res
)
559 if in_importation
.greaters
.length
> 1 then
560 var c
= res
.new_dropdown
("imports", "{in_importation.greaters.length-1} modules")
561 for x
in in_importation
.greaters
do
562 if x
== self then continue
563 c
.open
("li").add x
.linkto
(v
)
569 redef fun linkto
(v
) do return linkto_text
(v
, name
)
572 redef class MClassDef
575 var res
= new HInfoBox(v
, "class {mclass.name}")
576 res
.href
= v
.hrefto
(self)
578 res
.new_field
("class").text
(mclass
.name
)
580 res
.new_field
("redef class").text
(mclass
.name
)
581 res
.new_field
("intro").add mclass
.intro
.linkto_text
(v
, "in {mclass.intro_mmodule.to_s}")
583 add_doc_to_infobox
(res
)
585 var in_hierarchy
= self.in_hierarchy
586 if in_hierarchy
== null then return res
588 if in_hierarchy
.greaters
.length
> 1 then
589 var c
= res
.new_dropdown
("hier", "super-classes")
590 for x
in in_hierarchy
.greaters
do
591 if x
== self then continue
592 if not x
.is_intro
then continue
593 c
.open
("li").add x
.linkto
(v
)
596 if in_hierarchy
.smallers
.length
> 1 then
597 var c
= res
.new_dropdown
("hier", "sub-classes")
598 for x
in in_hierarchy
.smallers
do
599 if x
== self then continue
600 if not x
.is_intro
then continue
601 c
.open
("li").add x
.linkto
(v
)
604 if mclass
.mclassdefs
.length
> 1 then
605 var c
= res
.new_dropdown
("redefs", "refinements")
606 for x
in mclass
.mclassdefs
do
607 if x
== self then continue
608 c
.open
("li").add x
.linkto_text
(v
, "in {x.mmodule}")
618 var res
= new HInfoBox(v
, to_s
)
619 res
.href
= v
.hrefto
(self)
620 if self isa MMethodDef then
621 var msignature
= self.msignature
622 if msignature
!= null then res
.new_field
("fun").append
(mproperty
.name
).add msignature
.linkto
(v
)
623 else if self isa MAttributeDef then
624 var static_mtype
= self.static_mtype
625 if static_mtype
!= null then res
.new_field
("fun").append
(mproperty
.name
).add static_mtype
.linkto
(v
)
626 else if self isa MVirtualTypeDef then
627 var bound
= self.bound
628 if bound
!= null then res
.new_field
("add").append
(mproperty
.name
).add bound
.linkto
(v
)
630 res
.new_field
("wat?").append
(mproperty
.name
)
635 res
.new_field
("intro").add mproperty
.intro
.linkto_text
(v
, "in {mproperty.intro.mclassdef}")
637 add_doc_to_infobox
(res
)
638 if mproperty
.mpropdefs
.length
> 1 then
639 var c
= res
.new_dropdown
("redef", "redefinitions")
640 for x
in mproperty
.mpropdefs
do
641 c
.open
("li").add x
.linkto_text
(v
, "in {x.mclassdef}")
649 redef class MClassType
652 var res
= new HInfoBox(v
, to_s
)
653 res
.href
= v
.hrefto
(self)
654 res
.new_field
("class").add mclass
.intro
.linkto
(v
)
655 add_doc_to_infobox
(res
)
660 return mclass
.intro
.linkto
(v
)
663 redef class MVirtualType
666 var res
= new HInfoBox(v
, to_s
)
667 res
.href
= v
.hrefto
(mproperty
)
669 res
.new_field
("virtual type").add p
.intro
.linkto
(v
)
670 add_doc_to_infobox
(res
)
675 return mproperty
.intro
.linkto
(v
)
678 redef class MParameterType
681 var res
= new HInfoBox(v
, to_s
)
682 res
.new_field
("parameter type").append
("{name} from class ").add mclass
.intro
.linkto
(v
)
687 redef class MNullableType
690 return mtype
.infobox
(v
)
694 var res
= new HTMLTag("span")
695 res
.append
("nullable ").add
(mtype
.linkto
(v
))
700 redef class MNotNullType
703 return mtype
.infobox
(v
)
707 var res
= new HTMLTag("span")
708 res
.append
("not null ").add
(mtype
.linkto
(v
))
713 redef class MNullType
716 var res
= new HInfoBox(v
, to_s
)
721 var res
= new HTMLTag("span")
727 redef class MSignature
730 var res
= new HTMLTag("span")
732 if not mparameters
.is_empty
then
734 for p
in mparameters
do
742 res
.add p
.mtype
.linkto
(v
)
746 var ret
= return_mtype
749 res
.add ret
.linkto
(v
)
758 var res
= new HInfoBox(v
, "call {mpropdef}")
759 res
.href
= v
.hrefto
(mpropdef
)
760 res
.new_field
("call").add
(mpropdef
.linkto
(v
)).add
(msignature
.linkto
(v
))
761 if mpropdef
.is_intro
then
763 res
.new_field
("intro").add mproperty
.intro
.linkto_text
(v
, "in {mproperty.intro.mclassdef}")
765 add_doc_to_infobox
(res
)
771 return mpropdef
.linkto
(v
)
779 var declared_type
= self.declared_type
780 if declared_type
== null then
781 var res
= new HInfoBox(v
, "{name}")
782 res
.new_field
("local var").append
("{name}")
785 var res
= new HInfoBox(v
, "{name}: {declared_type}")
786 res
.new_field
("local var").append
("{name}:").add
(declared_type
.linkto
(v
))
795 # Optionally creates a tag that encapsulate the AST element on HTML rendering
796 protected fun make_tag
(v
: HighlightVisitor): nullable HTMLTag do return null
798 # Add aditionnal information on a child-token and return an additionnal HInfoBox on it
799 protected fun decorate_tag
(v
: HighlightVisitor, res
: HTMLTag, token
: Token): nullable HInfoBox
801 #debug("no decoration for {token.inspect}")
802 #res.add_class("nc_error")
806 # Return a optional infobox
807 fun infobox
(v
: HighlightVisitor): nullable HInfoBox do return null
810 redef class AQclassid
811 redef fun decorate_tag
(v
, res
, token
)
813 if token
!= n_id
then return null
814 var parent
= self.parent
815 if parent
== null then return null
816 return parent
.decorate_tag
(v
, res
, token
)
821 redef fun decorate_tag
(v
, res
, token
)
823 if token
!= n_id
then return null
824 var parent
= self.parent
825 if parent
== null then return null
826 return parent
.decorate_tag
(v
, res
, token
)
830 redef class AStdClassdef
831 redef fun make_tag
(v
)
833 var res
= new HTMLTag("span")
834 res
.add_class
("nc_cdef")
836 if md
!= null then res
.attr
("id", md
.to_s
)
839 redef fun decorate_tag
(v
, res
, token
)
841 if not token
isa TClassid then return null
842 res
.add_class
("nc_def")
845 if md
== null then return null
850 redef fun make_tag
(v
)
852 var res
= new HTMLTag("span")
853 res
.add_class
("nc_pdef")
858 res
.attr
("id", mpd
.to_s
)
860 if self isa AAttrPropdef then
862 if mpd
!= null then res
.add
(tag
(mpd
))
864 if mpd
!= null then res
.add
(tag
(mpd
))
869 private fun tag
(mpd
: MPropDef): HTMLTag
871 var a
= new HTMLTag("a")
872 a
.attr
("id", mpd
.to_s
)
878 # Produce an HTMLTag with the correct contents and CSS classes
879 # Subclasses can redefine it to decorate the tag
880 redef fun make_tag
(v
): HTMLTag
882 var res
= new HTMLTag("span")
888 redef class TokenKeyword
889 redef fun make_tag
(v
)
892 res
.add_class
("nc_k")
896 redef class TokenOperator
897 redef fun make_tag
(v
)
900 res
.add_class
("nc_o")
905 redef class AVarFormExpr
906 redef fun decorate_tag
(v
, res
, token
)
908 if token
!= n_id
then return null
909 var variable
= self.variable
910 if variable
== null then return null
911 res
.add_class
("nc_v")
912 return variable
.infobox
(v
)
916 redef class AVardeclExpr
917 redef fun decorate_tag
(v
, res
, token
)
919 if token
!= n_id
then return null
920 var variable
= self.variable
921 if variable
== null then return null
922 res
.add_class
("nc_v")
923 return variable
.infobox
(v
)
927 redef class AForGroup
928 redef fun decorate_tag
(v
, res
, token
)
930 if not token
isa TId then return null
932 if vs
== null then return null
933 res
.add_class
("nc_v")
934 var idx
= n_ids
.index_of
(token
)
935 var variable
= vs
[idx
]
936 return variable
.infobox
(v
)
941 redef fun decorate_tag
(v
, res
, token
)
943 if token
!= n_id
then return null
945 if mp
== null then return null
946 var variable
= self.variable
947 if variable
== null then return null
948 res
.add_class
("nc_v")
949 return variable
.infobox
(v
)
953 redef class AAssertExpr
954 redef fun decorate_tag
(v
, res
, token
)
956 if not token
isa TId then return null
957 res
.add_class
("nc_ast")
963 redef fun decorate_tag
(v
, res
, token
)
965 if not token
isa TId then return null
966 res
.add_class
("nc_la")
971 redef class ASendExpr
972 redef fun decorate_tag
(v
, res
, token
)
974 var callsite
= self.callsite
975 if callsite
== null then return null
976 return callsite
.infobox
(v
)
981 redef fun decorate_tag
(v
, res
, token
)
983 var callsite
= self.callsite
984 if callsite
== null then return null
985 return callsite
.infobox
(v
)
989 redef class AAssignOp
990 redef fun decorate_tag
(v
, res
, token
)
993 assert p
isa AReassignFormExpr
995 var callsite
= p
.reassign_callsite
996 if callsite
== null then return null
997 return callsite
.infobox
(v
)
1001 redef class AModuleName
1002 redef fun decorate_tag
(v
, res
, token
)
1005 if p
== null then return null
1006 return p
.decorate_tag
(v
, res
, token
)
1010 redef class AModuledecl
1011 redef fun decorate_tag
(v
, res
, token
)
1013 if not token
isa TId then return null
1014 res
.add_class
("nc_def")
1015 res
.add_class
("nc_m")
1017 assert p
isa AModule
1019 if mm
== null then return null
1020 return mm
.infobox
(v
)
1024 redef class AStdImport
1025 redef fun decorate_tag
(v
, res
, token
)
1027 if not token
isa TId then return null
1028 res
.add_class
("nc_m")
1030 if mm
== null then return null
1031 return mm
.infobox
(v
)
1034 redef class AAttrPropdef
1035 redef fun decorate_tag
(v
, res
, token
)
1037 if not token
isa TId then return null
1038 res
.add_class
("nc_def")
1039 var mpd
: nullable MPropDef
1041 if mpd
== null then mpd
= mpropdef
1042 if mpd
== null then return null
1043 return mpd
.infobox
(v
)
1048 redef fun make_tag
(v
)
1051 res
.add_class
("nc_i")
1056 redef fun make_tag
(v
)
1058 var res
= new HTMLTag("span")
1059 res
.add_class
("nc_def")
1062 redef fun decorate_tag
(v
, res
, token
)
1065 # nothing to decorate
1067 redef fun infobox
(v
)
1070 if not p
isa AMethPropdef then return null
1071 var mpd
= p
.mpropdef
1072 if mpd
== null then return null
1073 return mpd
.infobox
(v
)
1077 redef fun make_tag
(v
)
1080 res
.add_class
("nc_a")
1084 redef class AAttrFormExpr
1085 redef fun decorate_tag
(v
, res
, token
)
1087 if not token
isa TAttrid then return null
1089 if p
== null then return null
1090 return p
.intro
.infobox
(v
)
1093 redef class TClassid
1094 redef fun make_tag
(v
)
1097 res
.add_class
("nc_t")
1102 redef fun decorate_tag
(v
, res
, token
)
1104 if not token
isa TClassid then return null
1106 if mt
== null then return null
1108 if mt
isa MFormalType then
1109 res
.add_class
("nc_vt")
1111 return mt
.infobox
(v
)
1114 redef class AFormaldef
1115 redef fun decorate_tag
(v
, res
, token
)
1117 if not token
isa TClassid then return null
1118 res
.add_class
("nc_vt")
1119 var mtype
= self.mtype
1120 if mtype
== null then return null
1121 return mtype
.infobox
(v
)
1124 redef class ATypePropdef
1125 redef fun decorate_tag
(v
, res
, token
)
1127 if not token
isa TClassid then return null
1128 res
.add_class
("nc_def")
1130 if md
== null then return null
1131 return md
.infobox
(v
)
1134 redef class TComment
1135 redef fun make_tag
(v
)
1139 res
.add_class
("nc_c")
1145 redef fun make_tag
(v
)
1147 var res
= new HTMLTag("span")
1148 res
.add_class
("nc_d")
1152 redef class TokenLiteral
1153 redef fun make_tag
(v
)
1156 res
.add_class
("nc_l")
1160 redef class ASuperstringExpr
1161 redef fun make_tag
(v
)
1163 var res
= new HTMLTag("span")
1164 res
.add_class
("nc_ss")
1168 redef class AStringFormExpr
1169 redef fun decorate_tag
(v
, res
, token
)
1171 # Workaround to tag strings
1172 res
.classes
.remove
("nc_l")
1173 res
.add_class
("nc_s")
1178 redef fun decorate_tag
(v
, res
, token
)
1181 if t
== null then return null