+
+ redef fun linkto(v) do return linkto_text(v, name)
+end
+
+redef class MClassDef
+ redef fun infobox(v)
+ do
+ var res = new HInfoBox(v, "class {mclass.name}")
+ res.href = v.hrefto(self)
+ if is_intro then
+ res.new_field("class").text(mclass.name)
+ else
+ res.new_field("redef class").text(mclass.name)
+ res.new_field("intro").add mclass.intro.linkto_text(v, "in {mclass.intro_mmodule.to_s}")
+ end
+ var mdoc = self.mdoc
+ if mdoc == null then mdoc = mclass.intro.mdoc
+ if mdoc != null then mdoc.fill_infobox(res)
+
+ var in_hierarchy = self.in_hierarchy
+ if in_hierarchy == null then return res
+
+ if in_hierarchy.greaters.length > 1 then
+ var c = res.new_dropdown("hier", "super-classes")
+ for x in in_hierarchy.greaters do
+ if x == self then continue
+ if not x.is_intro then continue
+ c.open("li").add x.linkto(v)
+ end
+ end
+ if in_hierarchy.smallers.length > 1 then
+ var c = res.new_dropdown("hier", "sub-classes")
+ for x in in_hierarchy.smallers do
+ if x == self then continue
+ if not x.is_intro then continue
+ c.open("li").add x.linkto(v)
+ end
+ end
+ if mclass.mclassdefs.length > 1 then
+ var c = res.new_dropdown("redefs", "refinements")
+ for x in mclass.mclassdefs do
+ if x == self then continue
+ c.open("li").add x.linkto_text(v, "in {x.mmodule}")
+ end
+ end
+ return res
+ end
+end
+
+redef class MPropDef
+ redef fun infobox(v)
+ do
+ var res = new HInfoBox(v, to_s)
+ res.href = v.hrefto(self)
+ if self isa MMethodDef then
+ var msignature = self.msignature
+ if msignature != null then res.new_field("fun").append(mproperty.name).add msignature.linkto(v)
+ else if self isa MAttributeDef then
+ var static_mtype = self.static_mtype
+ if static_mtype != null then res.new_field("fun").append(mproperty.name).add static_mtype.linkto(v)
+ else if self isa MVirtualTypeDef then
+ var bound = self.bound
+ if bound != null then res.new_field("add").append(mproperty.name).add bound.linkto(v)
+ else
+ res.new_field("wat?").append(mproperty.name)
+ end
+
+ if is_intro then
+ else
+ res.new_field("intro").add mproperty.intro.linkto_text(v, "in {mproperty.intro.mclassdef}")
+ end
+ var mdoc = self.mdoc
+ if mdoc == null then mdoc = mproperty.intro.mdoc
+ if mdoc != null then mdoc.fill_infobox(res)
+ if mproperty.mpropdefs.length > 1 then
+ var c = res.new_dropdown("redef", "redefinitions")
+ for x in mproperty.mpropdefs do
+ c.open("li").add x.linkto_text(v, "in {x.mclassdef}")
+ end
+ end
+
+ return res
+ end
+end
+
+redef class MClassType
+ redef fun infobox(v)
+ do
+ var res = new HInfoBox(v, to_s)
+ res.href = v.hrefto(self)
+ res.new_field("class").add mclass.intro.linkto(v)
+ var mdoc = mclass.mdoc
+ if mdoc == null then mdoc = mclass.intro.mdoc
+ if mdoc != null then mdoc.fill_infobox(res)
+ return res
+ end
+ redef fun linkto(v)
+ do
+ return mclass.intro.linkto(v)
+ end
+end
+redef class MVirtualType
+ redef fun infobox(v)
+ do
+ var res = new HInfoBox(v, to_s)
+ res.href = v.hrefto(mproperty)
+ var p = mproperty
+ var pd = p.intro
+ res.new_field("virtual type").add pd.linkto(v)
+ var mdoc = pd.mdoc
+ if mdoc != null then mdoc.fill_infobox(res)
+ return res
+ end
+ redef fun linkto(v)
+ do
+ return mproperty.intro.linkto(v)
+ end
+end
+redef class MParameterType
+ redef fun infobox(v)
+ do
+ var res = new HInfoBox(v, to_s)
+ res.new_field("parameter type").append("{name} from class ").add mclass.intro.linkto(v)
+ return res
+ end
+end
+
+redef class MNullableType
+ redef fun infobox(v)
+ do
+ return mtype.infobox(v)
+ end
+ redef fun linkto(v)
+ do
+ var res = new HTMLTag("span")
+ res.append("nullable ").add(mtype.linkto(v))
+ return res
+ end
+end
+
+redef class MNotNullType
+ redef fun infobox(v)
+ do
+ return mtype.infobox(v)
+ end
+ redef fun linkto(v)
+ do
+ var res = new HTMLTag("span")
+ res.append("not null ").add(mtype.linkto(v))
+ return res
+ end
+end
+
+redef class MNullType
+ redef fun infobox(v)
+ do
+ var res = new HInfoBox(v, to_s)
+ return res
+ end
+ redef fun linkto(v)
+ do
+ var res = new HTMLTag("span")
+ res.append("null")
+ return res
+ end
+end
+
+redef class MSignature
+ redef fun linkto(v)
+ do
+ var res = new HTMLTag("span")
+ var first = true
+ if not mparameters.is_empty then
+ res.append "("
+ for p in mparameters do
+ if first then
+ first = false
+ else
+ res.append ", "
+ end
+ res.append p.name
+ res.append ": "
+ res.add p.mtype.linkto(v)
+ end
+ res.append ")"
+ end
+ var ret = return_mtype
+ if ret != null then
+ res.append ": "
+ res.add ret.linkto(v)
+ end
+ return res
+ end
+end
+
+redef class CallSite
+ redef fun infobox(v)
+ do
+ var res = new HInfoBox(v, "call {mpropdef}")
+ res.href = v.hrefto(mpropdef)
+ res.new_field("call").add(mpropdef.linkto(v)).add(msignature.linkto(v))
+ if mpropdef.is_intro then
+ else
+ res.new_field("intro").add mproperty.intro.linkto_text(v, "in {mproperty.intro.mclassdef}")
+ end
+ var mdoc = mpropdef.mdoc
+ if mdoc == null then mdoc = mproperty.intro.mdoc
+ if mdoc != null then mdoc.fill_infobox(res)
+
+ return res
+ end
+ redef fun linkto(v)
+ do
+ return mpropdef.linkto(v)
+ end
+end
+
+redef class Variable
+ super HInfoBoxable
+ redef fun infobox(v)
+ do
+ var declared_type = self.declared_type
+ if declared_type == null then
+ var res = new HInfoBox(v, "{name}")
+ res.new_field("local var").append("{name}")
+ return res
+ end
+ var res = new HInfoBox(v, "{name}: {declared_type}")
+ res.new_field("local var").append("{name}:").add(declared_type.linkto(v))
+ return res
+ end
+end
+
+
+##
+
+redef class ANode
+ # Optionally creates a tag that encapsulate the AST element on HTML rendering
+ protected fun make_tag(v: HighlightVisitor): nullable HTMLTag do return null
+
+ # Add aditionnal information on a child-token and return an additionnal HInfoBox on it
+ protected fun decorate_tag(v: HighlightVisitor, res: HTMLTag, token: Token): nullable HInfoBox