scala.tools.nsc.doc.html.page.Template.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scala-compiler Show documentation
Show all versions of scala-compiler Show documentation
Compiler for the SubScript extension of the Scala Programming Language
The newest version!
/* NSC -- new Scala compiler
* Copyright 2007-2013 LAMP/EPFL
* @author David Bernard, Manohar Jonnalagedda
*/
package scala
package tools
package nsc
package doc
package html
package page
import base._
import base.comment._
import model._
import model.diagram._
import scala.xml.{Elem, NodeSeq, Text, UnprefixedAttribute}
import scala.language.postfixOps
import scala.collection.mutable. { Set, HashSet }
import model._
import model.diagram._
import diagram._
class Template(universe: doc.Universe, generator: DiagramGenerator, tpl: DocTemplateEntity) extends HtmlPage {
val path =
templateToPath(tpl)
def title = {
val s = universe.settings
tpl.name +
( if (!s.doctitle.isDefault) " - " + s.doctitle.value else "" ) +
( if (!s.docversion.isDefault) (" " + s.docversion.value) else "" ) +
" - " + tpl.qualifiedName
}
val headers =
{ if (universe.settings.docDiagrams.value) {
} else NodeSeq.Empty }
val valueMembers =
tpl.methods ++ tpl.values ++ tpl.templates.filter(x => x.isObject || x.isPackage) sorted
val (absValueMembers, nonAbsValueMembers) =
valueMembers partition (_.isAbstract)
val (deprValueMembers, nonDeprValueMembers) =
nonAbsValueMembers partition (_.deprecation.isDefined)
val (concValueMembers, shadowedImplicitMembers) =
nonDeprValueMembers partition (!_.isShadowedOrAmbiguousImplicit)
val typeMembers =
tpl.abstractTypes ++ tpl.aliasTypes ++ tpl.templates.filter(x => x.isTrait || x.isClass) sorted (implicitly[Ordering[MemberEntity]])
val constructors = (tpl match {
case cls: Class => (cls.constructors: List[MemberEntity]).sorted
case _ => Nil
})
/* for body, there is a special case for AnyRef, otherwise AnyRef appears
* like a package/object this problem should be fixed, this implementation
* is just a patch. */
val body = {
val templateName = if (tpl.isRootPackage) "root package" else tpl.name
val displayName = tpl.companion match {
case Some(companion) if (companion.visibility.isPublic && companion.inSource != None) =>
{ templateName }
case _ =>
templateName
}
val owner = {
if (tpl.isRootPackage || tpl.inTemplate.isRootPackage)
NodeSeq.Empty
else
{ templatesToHtml(tpl.inTemplate.toRoot.reverse.tail, scala.xml.Text(".")) }
}
{
tpl.companion match {
case Some(companion) if (companion.visibility.isPublic && companion.inSource != None) =>
case _ =>
}}
{ owner }
{ displayName }
{
if (tpl.isPackage) NodeSeq.Empty else {companionAndPackage(tpl)}
}{ permalink(tpl) }
{ signature(tpl, isSelf = true) }
{ memberToCommentHtml(tpl, tpl.inTemplate, isSelf = true) }
{ if (tpl.linearizationTemplates.isEmpty && tpl.conversions.isEmpty && (!universe.settings.docGroups.value || (tpl.members.map(_.group).distinct.length == 1)))
NodeSeq.Empty
else
Ordering
{
if (!universe.settings.docGroups.value || (tpl.members.map(_.group).distinct.length == 1))
NodeSeq.Empty
else
- Grouped
}
- Alphabetic
{
if (tpl.linearizationTemplates.isEmpty && tpl.conversions.isEmpty)
NodeSeq.Empty
else
- By inheritance
}
}
{ if (tpl.linearizationTemplates.isEmpty && tpl.conversions.isEmpty) NodeSeq.Empty else
{
if (!tpl.linearizationTemplates.isEmpty)
Inherited
{ (tpl :: tpl.linearizationTemplates).map(wte => - { wte.name }
) }
else NodeSeq.Empty
} ++ {
if (!tpl.conversions.isEmpty)
Implicitly
{
tpl.conversions.map { conv =>
val name = conv.conversionQualifiedName
val hide = universe.settings.hiddenImplicits(name)
- { "by " + conv.conversionShortName }
}
}
else NodeSeq.Empty
} ++
- Hide All
- Show all
Learn more about member selection
}
{
Visibility
- Public
- All
}
{ if (constructors.isEmpty) NodeSeq.Empty else
Instance Constructors
{ constructors map (memberToHtml(_, tpl)) }
}
{ if (typeMembers.isEmpty) NodeSeq.Empty else
Type Members
{ typeMembers map (memberToHtml(_, tpl)) }
}
{ if (absValueMembers.isEmpty) NodeSeq.Empty else
Abstract Value Members
{ absValueMembers map (memberToHtml(_, tpl)) }
}
{ if (concValueMembers.isEmpty) NodeSeq.Empty else
{ if (absValueMembers.isEmpty) "Value Members" else "Concrete Value Members" }
{ concValueMembers map (memberToHtml(_, tpl)) }
}
{ if (shadowedImplicitMembers.isEmpty) NodeSeq.Empty else
Shadowed Implicit Value Members
{ shadowedImplicitMembers map (memberToHtml(_, tpl)) }
}
{ if (deprValueMembers.isEmpty) NodeSeq.Empty else
Deprecated Value Members
{ deprValueMembers map (memberToHtml(_, tpl)) }
}
{
// linearization
NodeSeq fromSeq (for ((superTpl, superType) <- (tpl.linearizationTemplates zip tpl.linearizationTypes)) yield
Inherited from {
typeToHtmlWithStupidTypes(tpl, superTpl, superType)
}
)
}
{
// implicitly inherited
NodeSeq fromSeq (for (conversion <- (tpl.conversions)) yield
Inherited by implicit conversion { conversion.conversionShortName } from
{ typeToHtml(tpl.resultType, hasLinks = true) } to { typeToHtml(conversion.targetType, hasLinks = true) }
)
}
{
val allGroups = tpl.members.map(_.group).distinct
val orderedGroups = allGroups.map(group => (tpl.groupPriority(group), group)).sorted.map(_._2)
// linearization
NodeSeq fromSeq (for (group <- orderedGroups) yield
{ tpl.groupName(group) }
{
tpl.groupDescription(group) match {
case Some(body) => { bodyToHtml(body) }
case _ => NodeSeq.Empty
}
}
)
}
{
if (Set("epfl", "EPFL").contains(tpl.universe.settings.docfooter.value))
else
}
}
def memberToHtml(mbr: MemberEntity, inTpl: DocTemplateEntity): NodeSeq = {
val memberComment = memberToCommentHtml(mbr, inTpl, isSelf = false)
{ signature(mbr, isSelf = false) }
{ memberComment }
}
def memberToCommentHtml(mbr: MemberEntity, inTpl: DocTemplateEntity, isSelf: Boolean): NodeSeq = {
mbr match {
case dte: DocTemplateEntity if isSelf =>
// comment of class itself
{ memberToCommentBodyHtml(mbr, inTpl, isSelf = true) }
case _ =>
// comment of non-class member or non-documentented inner class
val commentBody = memberToCommentBodyHtml(mbr, inTpl, isSelf = false)
if (commentBody.isEmpty)
NodeSeq.Empty
else {
val shortComment = memberToShortCommentHtml(mbr, isSelf)
val longComment = memberToUseCaseCommentHtml(mbr, isSelf) ++ memberToCommentBodyHtml(mbr, inTpl, isSelf)
val includedLongComment = if (shortComment.text.trim == longComment.text.trim)
NodeSeq.Empty
else
{ longComment }
shortComment ++ includedLongComment
}
}
}
def memberToUseCaseCommentHtml(mbr: MemberEntity, isSelf: Boolean): NodeSeq = {
mbr match {
case nte: NonTemplateMemberEntity if nte.isUseCase =>
inlineToHtml(comment.Text("[use case] "))
case _ => NodeSeq.Empty
}
}
def memberToShortCommentHtml(mbr: MemberEntity, isSelf: Boolean): NodeSeq =
mbr.comment.fold(NodeSeq.Empty) { comment =>
{ memberToUseCaseCommentHtml(mbr, isSelf) }{ inlineToHtml(comment.short) }
}
def memberToInlineCommentHtml(mbr: MemberEntity, isSelf: Boolean): NodeSeq =
{ inlineToHtml(mbr.comment.get.short) }
def memberToCommentBodyHtml(mbr: MemberEntity, inTpl: DocTemplateEntity, isSelf: Boolean, isReduced: Boolean = false): NodeSeq = {
val s = universe.settings
val memberComment =
if (mbr.comment.isEmpty) NodeSeq.Empty
else { commentToHtml(mbr.comment) }
val authorComment =
if (! s.docAuthor || mbr.comment.isEmpty ||
mbr.comment.isDefined && mbr.comment.get.authors.isEmpty) NodeSeq.Empty
else
{if (mbr.comment.get.authors.size > 1) Authors:
else Author:
}
{ mbr.comment.get.authors map bodyToHtml}
val paramComments = {
val prs: List[ParameterEntity] = mbr match {
case cls: Class => cls.typeParams ::: cls.valueParams.flatten
case trt: Trait => trt.typeParams
case dfe: Def => dfe.typeParams ::: dfe.valueParams.flatten
case ctr: Constructor => ctr.valueParams.flatten
case _ => Nil
}
def paramCommentToHtml(prs: List[ParameterEntity], comment: Comment): NodeSeq = prs match {
case (tp: TypeParam) :: rest =>
val paramEntry: NodeSeq = {
{ tp.name } { bodyToHtml(comment.typeParams(tp.name)) }
}
paramEntry ++ paramCommentToHtml(rest, comment)
case (vp: ValueParam) :: rest =>
val paramEntry: NodeSeq = {
{ vp.name } { bodyToHtml(comment.valueParams(vp.name)) }
}
paramEntry ++ paramCommentToHtml(rest, comment)
case _ =>
NodeSeq.Empty
}
mbr.comment.fold(NodeSeq.Empty) { comment =>
val cmtedPrs = prs filter {
case tp: TypeParam => comment.typeParams isDefinedAt tp.name
case vp: ValueParam => comment.valueParams isDefinedAt vp.name
}
if (cmtedPrs.isEmpty && comment.result.isEmpty) NodeSeq.Empty
else {
{
paramCommentToHtml(cmtedPrs, comment) ++ (
comment.result match {
case None => NodeSeq.Empty
case Some(cmt) =>
- returns
- { bodyToHtml(cmt) }
})
}
}
}
}
val implicitInformation = mbr.byConversion match {
case Some(conv) =>
Implicit information ++
{
val targetType = typeToHtml(conv.targetType, hasLinks = true)
val conversionMethod = conv.convertorMethod match {
case Left(member) => Text(member.name)
case Right(name) => Text(name)
}
// strip off the package object endings, they make things harder to follow
val conversionOwnerQualifiedNane = conv.convertorOwner.qualifiedName.stripSuffix(".package")
val conversionOwner = templateToHtml(conv.convertorOwner, conversionOwnerQualifiedNane)
val constraintText = conv.constraints match {
case Nil =>
NodeSeq.Empty
case List(constraint) =>
scala.xml.Text("This conversion will take place only if ") ++ constraintToHtml(constraint) ++ scala.xml.Text(".")
case List(constraint1, constraint2) =>
scala.xml.Text("This conversion will take place only if ") ++ constraintToHtml(constraint1) ++
scala.xml.Text(" and at the same time ") ++ constraintToHtml(constraint2) ++ scala.xml.Text(".")
case constraints =>
++ "This conversion will take place only if all of the following constraints are met:" ++
++ {
var index = 0
constraints map { constraint => scala.xml.Text({ index += 1; index } + ". ") ++ constraintToHtml(constraint) ++
}
}
}
This member is added by an implicit conversion from { typeToHtml(inTpl.resultType, hasLinks = true) } to
{ targetType } performed by method { conversionMethod } in { conversionOwner }.
{ constraintText }
} ++ {
if (mbr.isShadowedOrAmbiguousImplicit) {
// These are the members that are shadowing or ambiguating the current implicit
// see ImplicitMemberShadowing trait for more information
val shadowingSuggestion = {
val params = mbr match {
case d: Def => d.valueParams map (_ map (_ name) mkString("(", ", ", ")")) mkString
case _ => "" // no parameters
}
++ scala.xml.Text("To access this member you can use a ") ++
type ascription ++ scala.xml.Text(":") ++
++ {"(" + Template.lowerFirstLetter(tpl.name) + ": " + conv.targetType.name + ")." + mbr.name + params }
}
val shadowingWarning: NodeSeq =
if (mbr.isShadowedImplicit)
scala.xml.Text("This implicitly inherited member is shadowed by one or more members in this " +
"class.") ++ shadowingSuggestion
else if (mbr.isAmbiguousImplicit)
scala.xml.Text("This implicitly inherited member is ambiguous. One or more implicitly " +
"inherited members have similar signatures, so calling this member may produce an ambiguous " +
"implicit conversion compiler error.") ++ shadowingSuggestion
else NodeSeq.Empty
Shadowing ++
{ shadowingWarning }
} else NodeSeq.Empty
}
case _ =>
NodeSeq.Empty
}
// --- start attributes block vals
val attributes: NodeSeq = {
val fvs: List[comment.Paragraph] = visibility(mbr).toList
if (fvs.isEmpty || isReduced) NodeSeq.Empty
else {
Attributes
{ fvs map { fv => { inlineToHtml(fv.text) ++ scala.xml.Text(" ") } } }
}
}
val definitionClasses: NodeSeq = {
val inDefTpls = mbr.inDefinitionTemplates
if ((inDefTpls.tail.isEmpty && (inDefTpls.head == inTpl)) || isReduced) NodeSeq.Empty
else {
Definition Classes
{ templatesToHtml(inDefTpls, scala.xml.Text(" → ")) }
}
}
val fullSignature: NodeSeq = {
mbr match {
case nte: NonTemplateMemberEntity if nte.isUseCase =>
Full Signature
{ signature(nte.useCaseOf.get,isSelf = true) }
case _ => NodeSeq.Empty
}
}
val selfType: NodeSeq = mbr match {
case dtpl: DocTemplateEntity if (isSelf && !dtpl.selfType.isEmpty && !isReduced) =>
Self Type
{ typeToHtml(dtpl.selfType.get, hasLinks = true) }
case _ => NodeSeq.Empty
}
val annotations: NodeSeq = {
// A list of annotations which don't show their arguments, e. g. because they are shown separately.
val annotationsWithHiddenArguments = List("deprecated", "Deprecated", "migration")
def showArguments(annotation: Annotation) =
!(annotationsWithHiddenArguments.contains(annotation.qualifiedName))
if (!mbr.annotations.isEmpty) {
Annotations
{
mbr.annotations.map { annot =>
@{ templateToHtml(annot.annotationClass) }{
if (showArguments(annot)) argumentsToHtml(annot.arguments) else NodeSeq.Empty
}
}
}
} else NodeSeq.Empty
}
val sourceLink: NodeSeq = mbr match {
case dtpl: DocTemplateEntity if (isSelf && dtpl.sourceUrl.isDefined && dtpl.inSource.isDefined && !isReduced) =>
val (absFile, _) = dtpl.inSource.get
Source
{ { Text(absFile.file.getName) } }
case _ => NodeSeq.Empty
}
val deprecation: NodeSeq =
mbr.deprecation match {
case Some(deprecation) if !isReduced =>
Deprecated
{ bodyToHtml(deprecation) }
case _ => NodeSeq.Empty
}
val migration: NodeSeq =
mbr.migration match {
case Some(migration) if !isReduced =>
Migration
{ bodyToHtml(migration) }
case _ => NodeSeq.Empty
}
val mainComment: NodeSeq = mbr.comment match {
case Some(comment) if (! isReduced) =>
def orEmpty[T](it: Iterable[T])(gen: =>NodeSeq): NodeSeq =
if (it.isEmpty) NodeSeq.Empty else gen
val example =
orEmpty(comment.example) {
Example{ if (comment.example.length > 1) "s" else ""}:
{
val exampleXml: List[NodeSeq] = for (ex <- comment.example) yield
- { bodyToHtml(ex) }
exampleXml.reduceLeft(_ ++ Text(", ") ++ _)
}
}
val version: NodeSeq =
orEmpty(comment.version) {
Version
{ for(body <- comment.version.toList) yield bodyToHtml(body) }
}
val sinceVersion: NodeSeq =
orEmpty(comment.since) {
Since
{ for(body <- comment.since.toList) yield bodyToHtml(body) }
}
val note: NodeSeq =
orEmpty(comment.note) {
Note
{
val noteXml: List[NodeSeq] = for(note <- comment.note ) yield {bodyToHtml(note)}
noteXml.reduceLeft(_ ++ Text(", ") ++ _)
}
}
val seeAlso: NodeSeq =
orEmpty(comment.see) {
See also
{
val seeXml: List[NodeSeq] = for(see <- comment.see ) yield {bodyToHtml(see)}
seeXml.reduceLeft(_ ++ _)
}
}
val exceptions: NodeSeq =
orEmpty(comment.throws) {
Exceptions thrown
{
val exceptionsXml: List[NodeSeq] =
for((name, body) <- comment.throws.toList.sortBy(_._1) ) yield
{bodyToHtml(body)}
exceptionsXml.reduceLeft(_ ++ Text("") ++ _)
}
}
val todo: NodeSeq =
orEmpty(comment.todo) {
To do
{
val todoXml: List[NodeSeq] = (for(todo <- comment.todo ) yield {bodyToHtml(todo)} )
todoXml.reduceLeft(_ ++ Text(", ") ++ _)
}
}
example ++ version ++ sinceVersion ++ exceptions ++ todo ++ note ++ seeAlso
case _ => NodeSeq.Empty
}
// end attributes block vals ---
val attributesInfo = implicitInformation ++ attributes ++ definitionClasses ++ fullSignature ++ selfType ++ annotations ++ deprecation ++ migration ++ sourceLink ++ mainComment
val attributesBlock =
if (attributesInfo.isEmpty)
NodeSeq.Empty
else
{ attributesInfo }
val linearization = mbr match {
case dtpl: DocTemplateEntity if isSelf && !isReduced && dtpl.linearizationTemplates.nonEmpty =>
Linear Supertypes
case _ => NodeSeq.Empty
}
val subclasses = mbr match {
case dtpl: DocTemplateEntity if isSelf && !isReduced =>
val subs: Set[DocTemplateEntity] = HashSet.empty
def transitive(dtpl: DocTemplateEntity) {
for (sub <- dtpl.directSubClasses if !(subs contains sub)) {
subs add sub
transitive(sub)
}
}
transitive(dtpl)
if (subs.nonEmpty)
Known Subclasses
else NodeSeq.Empty
case _ => NodeSeq.Empty
}
def createDiagram(f: DocTemplateEntity => Option[Diagram], description: String, id: String): NodeSeq =
if (s.docDiagrams.value) mbr match {
case dtpl: DocTemplateEntity if isSelf && !isReduced =>
val diagram = f(dtpl)
if (diagram.isDefined) {
val diagramSvg = generator.generate(diagram.get, tpl, this)
if (diagramSvg != NodeSeq.Empty) {
} else NodeSeq.Empty
} else NodeSeq.Empty
case _ => NodeSeq.Empty
} else NodeSeq.Empty // diagrams not generated
val typeHierarchy = createDiagram(_.inheritanceDiagram, "Type Hierarchy", "inheritance-diagram")
val contentHierarchy = createDiagram(_.contentDiagram, "Content Hierarchy", "content-diagram")
memberComment ++ authorComment ++ paramComments ++ attributesBlock ++ linearization ++ subclasses ++ typeHierarchy ++ contentHierarchy
}
def boundsToHtml(hi: Option[TypeEntity], lo: Option[TypeEntity], hasLinks: Boolean): NodeSeq = {
def bound0(bnd: Option[TypeEntity], pre: String): NodeSeq = bnd match {
case None => NodeSeq.Empty
case Some(tpe) => scala.xml.Text(pre) ++ typeToHtml(tpe, hasLinks)
}
bound0(lo, " >: ") ++ bound0(hi, " <: ")
}
def visibility(mbr: MemberEntity): Option[comment.Paragraph] = {
import comment._
import comment.{ Text => CText }
mbr.visibility match {
case PrivateInInstance() =>
Some(Paragraph(CText("private[this]")))
case PrivateInTemplate(owner) if (owner == mbr.inTemplate) =>
Some(Paragraph(CText("private")))
case PrivateInTemplate(owner) =>
Some(Paragraph(Chain(List(CText("private["), EntityLink(comment.Text(owner.qualifiedName), LinkToTpl(owner)), CText("]")))))
case ProtectedInInstance() =>
Some(Paragraph(CText("protected[this]")))
case ProtectedInTemplate(owner) if (owner == mbr.inTemplate) =>
Some(Paragraph(CText("protected")))
case ProtectedInTemplate(owner) =>
Some(Paragraph(Chain(List(CText("protected["), EntityLink(comment.Text(owner.qualifiedName), LinkToTpl(owner)), CText("]")))))
case Public() =>
None
}
}
/** name, tparams, params, result */
def signature(mbr: MemberEntity, isSelf: Boolean, isReduced: Boolean = false): NodeSeq = {
def inside(hasLinks: Boolean, nameLink: String = ""): NodeSeq =
{ mbr.flags.map(flag => inlineToHtml(flag.text) ++ scala.xml.Text(" ")) }
{ kindToString(mbr) }
{
val nameClass =
if (mbr.isImplicitlyInherited)
if (mbr.isShadowedOrAmbiguousImplicit)
"implicit shadowed"
else
"implicit"
else
"name"
val nameHtml = {
val value = if (mbr.isConstructor) tpl.name else mbr.name
val span = if (mbr.deprecation.isDefined)
{ value }
else
{ value }
val encoded = scala.reflect.NameTransformer.encode(value)
if (encoded != value) {
span % new UnprefixedAttribute("title",
"gt4s: " + encoded +
span.attribute("title").map(
node => ". " + node
).getOrElse(""),
scala.xml.Null)
} else {
span
}
}
if (!nameLink.isEmpty)
{nameHtml}
else nameHtml
}{
def tparamsToHtml(mbr: Any): NodeSeq = mbr match {
case hk: HigherKinded =>
val tpss = hk.typeParams
if (tpss.isEmpty) NodeSeq.Empty else {
def tparam0(tp: TypeParam): NodeSeq =
{ tp.variance + tp.name }{ tparamsToHtml(tp) }{ boundsToHtml(tp.hi, tp.lo, hasLinks)}
def tparams0(tpss: List[TypeParam]): NodeSeq = (tpss: @unchecked) match {
case tp :: Nil => tparam0(tp)
case tp :: tps => tparam0(tp) ++ Text(", ") ++ tparams0(tps)
}
[{ tparams0(tpss) }]
}
case _ => NodeSeq.Empty
}
tparamsToHtml(mbr)
}{
if (isReduced) NodeSeq.Empty else {
def paramsToHtml(vlsss: List[List[ValueParam]]): NodeSeq = {
def param0(vl: ValueParam): NodeSeq =
// notice the }{ in the next lines, they are necessary to avoid an undesired withspace in output
{
Text(vl.name)
}{ Text(": ") ++ typeToHtml(vl.resultType, hasLinks) }{
vl.defaultValue match {
case Some(v) => Text(" = ") ++ treeToHtml(v)
case None => NodeSeq.Empty
}
}
def params0(vlss: List[ValueParam]): NodeSeq = vlss match {
case Nil => NodeSeq.Empty
case vl :: Nil => param0(vl)
case vl :: vls => param0(vl) ++ Text(", ") ++ params0(vls)
}
def implicitCheck(vlss: List[ValueParam]): NodeSeq = vlss match {
case vl :: vls => if(vl.isImplicit) { implicit } else Text("")
case _ => Text("")
}
vlsss map { vlss => ({implicitCheck(vlss) ++ params0(vlss) }) }
}
mbr match {
case cls: Class => paramsToHtml(cls.valueParams)
case ctr: Constructor => paramsToHtml(ctr.valueParams)
case dfe: Def => paramsToHtml(dfe.valueParams)
case _ => NodeSeq.Empty
}
}
}{ if (isReduced) NodeSeq.Empty else {
mbr match {
case tme: MemberEntity if (tme.isDef || tme.isVal || tme.isLazyVal || tme.isVar) =>
: { typeToHtml(tme.resultType, hasLinks) }
case abt: MemberEntity with AbstractType =>
val b2s = boundsToHtml(abt.hi, abt.lo, hasLinks)
if (b2s != NodeSeq.Empty)
{ b2s }
else NodeSeq.Empty
case alt: MemberEntity with AliasType =>
= { typeToHtml(alt.alias, hasLinks) }
case tpl: MemberTemplateEntity if !tpl.parentTypes.isEmpty =>
extends { typeToHtml(tpl.parentTypes.map(_._2), hasLinks) }
case _ => NodeSeq.Empty
}
}}
mbr match {
case dte: DocTemplateEntity if !isSelf =>
{ inside(hasLinks = true, nameLink = relativeLinkTo(dte)) }
++ permalink(dte, isSelf)
case _ if isSelf =>
{ inside(hasLinks = true) }
case _ =>
{ inside(hasLinks = true) }
++ permalink(mbr)
}
}
/** */
def treeToHtml(tree: TreeEntity): NodeSeq = {
/** Makes text good looking in the html page : newlines and basic indentation,
* You must change this function if you want to improve pretty printing of default Values
*/
def codeStringToXml(text: String): NodeSeq = {
var goodLookingXml: NodeSeq = NodeSeq.Empty
var indent = 0
for (c <- text) c match {
case '{' => indent+=1
goodLookingXml ++= Text("{")
case '}' => indent-=1
goodLookingXml ++= Text("}")
case '\n' =>
goodLookingXml++=
++ indentation
case _ => goodLookingXml ++= Text(c.toString)
}
def indentation:NodeSeq = {
var indentXml = NodeSeq.Empty
for (x <- 1 to indent) indentXml ++= Text(" ")
indentXml
}
goodLookingXml
}
var index = 0
val str = tree.expression
val length = str.length
var myXml: NodeSeq = NodeSeq.Empty
for ((from, (member, to)) <- tree.refEntity.toSeq) {
if (index < from) {
myXml ++= codeStringToXml(str.substring(index,from))
index = from
}
if (index == from) {
member match {
case mbr: DocTemplateEntity =>
val link = relativeLinkTo(mbr)
myXml ++= {str.substring(from, to)}
case mbr: MemberEntity =>
val anchor = "#" + mbr.signature
val link = relativeLinkTo(mbr.inTemplate)
myXml ++= {str.substring(from, to)}
}
index = to
}
}
if (index <= length-1)
myXml ++= codeStringToXml(str.substring(index, length ))
if (length < 36)
{ myXml }
else
{ "..." }
}
private def argumentsToHtml(argss: List[ValueArgument]): NodeSeq = {
def argumentsToHtml0(argss: List[ValueArgument]): NodeSeq = argss match {
case Nil => NodeSeq.Empty
case arg :: Nil => argumentToHtml(arg)
case arg :: args => argumentToHtml(arg) ++ scala.xml.Text(", ") ++ argumentsToHtml0(args)
}
({ argumentsToHtml0(argss) })
}
private def argumentToHtml(arg: ValueArgument): NodeSeq = {
{
arg.parameter match {
case Some(param) => Text(param.name + " = ")
case None => NodeSeq.Empty
}
}
{ treeToHtml(arg.value) }
}
private def bodyToStr(body: comment.Body): String =
body.blocks flatMap (blockToStr(_)) mkString ""
private def blockToStr(block: comment.Block): String = block match {
case comment.Paragraph(in) => inlineToStr(in)
case _ => block.toString
}
private def inlineToStr(inl: comment.Inline): String = inl match {
case comment.Chain(items) => items flatMap (inlineToStr(_)) mkString ""
case comment.Italic(in) => inlineToStr(in)
case comment.Bold(in) => inlineToStr(in)
case comment.Underline(in) => inlineToStr(in)
case comment.Monospace(in) => inlineToStr(in)
case comment.Text(text) => text
case comment.Summary(in) => inlineToStr(in)
case _ => inl.toString
}
private def typeToHtmlWithStupidTypes(tpl: TemplateEntity, superTpl: TemplateEntity, superType: TypeEntity): NodeSeq =
if (tpl.universe.settings.useStupidTypes.value)
superTpl match {
case dtpl: DocTemplateEntity =>
val sig = signature(dtpl, isSelf = false, isReduced = true) \ "_"
sig
case tpl: TemplateEntity =>
Text(tpl.name)
}
else
typeToHtml(superType, hasLinks = true)
private def constraintToHtml(constraint: Constraint): NodeSeq = constraint match {
case ktcc: KnownTypeClassConstraint =>
scala.xml.Text(ktcc.typeExplanation(ktcc.typeParamName) + " (" + ktcc.typeParamName + ": ") ++
templateToHtml(ktcc.typeClassEntity) ++ scala.xml.Text(")")
case tcc: TypeClassConstraint =>
scala.xml.Text(tcc.typeParamName + " is ") ++
context-bounded ++ scala.xml.Text(" by " + tcc.typeClassEntity.qualifiedName + " (" + tcc.typeParamName + ": ") ++
templateToHtml(tcc.typeClassEntity) ++ scala.xml.Text(")")
case impl: ImplicitInScopeConstraint =>
scala.xml.Text("an implicit value of type ") ++ typeToHtml(impl.implicitType, hasLinks = true) ++ scala.xml.Text(" is in scope")
case eq: EqualTypeParamConstraint =>
scala.xml.Text(eq.typeParamName + " is " + eq.rhs.name + " (" + eq.typeParamName + " =:= ") ++
typeToHtml(eq.rhs, hasLinks = true) ++ scala.xml.Text(")")
case bt: BoundedTypeParamConstraint =>
scala.xml.Text(bt.typeParamName + " is a superclass of " + bt.lowerBound.name + " and a subclass of " +
bt.upperBound.name + " (" + bt.typeParamName + " >: ") ++
typeToHtml(bt.lowerBound, hasLinks = true) ++ scala.xml.Text(" <: ") ++
typeToHtml(bt.upperBound, hasLinks = true) ++ scala.xml.Text(")")
case lb: LowerBoundedTypeParamConstraint =>
scala.xml.Text(lb.typeParamName + " is a superclass of " + lb.lowerBound.name + " (" + lb.typeParamName + " >: ") ++
typeToHtml(lb.lowerBound, hasLinks = true) ++ scala.xml.Text(")")
case ub: UpperBoundedTypeParamConstraint =>
scala.xml.Text(ub.typeParamName + " is a subclass of " + ub.upperBound.name + " (" + ub.typeParamName + " <: ") ++
typeToHtml(ub.upperBound, hasLinks = true) ++ scala.xml.Text(")")
}
}
object Template {
/* Vlad: Lesson learned the hard way: don't put any stateful code that references the model here,
* it won't be garbage collected and you'll end up filling the heap with garbage */
def lowerFirstLetter(s: String) = if (s.length >= 1) s.substring(0,1).toLowerCase() + s.substring(1) else s
}