summaryrefslogblamecommitdiff
path: root/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
blob: 47f2d4abed3b5e8abe6104236480c3546fe4294f (plain) (tree)











































                                                                                                                                      







                                                                                                                     



























































































                                                                                                                                      
                                           














                                                                                   
                                                                                       


























































                                                                                                      
/* NSC -- new Scala compiler
 * Copyright 2007-2009 LAMP/EPFL
 * @author  David Bernard, Manohar Jonnalagedda
 */

package scala.tools.nsc
package doc
package html
package page

import model._

import scala.xml.{NodeSeq, Text}
import scala.collection.mutable.HashSet

class Template(tpl: DocTemplateEntity) extends HtmlPage {

  val path =
    templateToPath(tpl)

  val title = "Scaladoc for " + tpl.qualifiedName

  val headers =
    <xml:group>
		  <style type="text/css">
		    @import url({ relativeLinkTo(List("template.css", "lib")) }) screen;
		  </style>
		  <script type="text/javascript" src={ relativeLinkTo{List("template.js", "lib")} }></script>
    </xml:group>

  val valueMembers =
    (tpl.methods ::: tpl.values ::: (tpl.templates filter { tpl => tpl.isObject || tpl.isPackage })) sortWith (_.name < _.name)

  val typeMembers =
    (tpl.abstractTypes ::: tpl.aliasTypes ::: (tpl.templates filter { tpl => tpl.isTrait || tpl.isClass })) sortWith (_.name < _.name)

  val constructors = (tpl match {
    case cls: Class => cls.constructors
    case _ => Nil
  }) sortWith (_.name < _.name)

  val body =
    <body class={ if (tpl.isTrait || tpl.isClass) "type" else "value" }>

      { def ownerLinks(otl: DocTemplateEntity): NodeSeq =
          if (otl.inTemplate.isRootPackage)
            <a href={ relativeLinkTo(otl) }>{ otl.name }</a>
          else ownerLinks(otl.inTemplate) ++ <xml:group>.<a href={ relativeLinkTo(otl) }>{ otl.name }</a></xml:group>
        if (tpl.isRootPackage || tpl.inTemplate.isRootPackage)
          NodeSeq.Empty
        else
          <p id="owner">{ ownerLinks(tpl.inTemplate) }</p>
      }

      <div id="definition">
        <img src={ relativeLinkTo(List(kindToString(tpl) + "_big.png", "lib")) }/>
        <h1>{ if (tpl.isRootPackage) "root package" else tpl.name }</h1>
      </div>

      { signature(tpl, true) }

      { if (tpl.comment.isEmpty) NodeSeq.Empty else
          <div id="comment">{ commentToHtml(tpl.comment) }</div>
      }

      <div id="template">

        { if (tpl.linearization.isEmpty) NodeSeq.Empty else
            <div id="mbrsel">
              <div id="ancestors">
                <h3>Inherits</h3>
                <ol>{ tpl.linearization map { wte => <li class="in" name={ wte.qualifiedName }>{ wte.name }</li> } }</ol>
              </div>
            </div>
        }

        { if (typeMembers.isEmpty) NodeSeq.Empty else
            <div id="types" class="members">
              <h3>Type Members</h3>
              <ol>{ typeMembers map (memberToHtml(_)) }</ol>
            </div>
        }

        { if (valueMembers.isEmpty) NodeSeq.Empty else
            <div id="values" class="members">
              <h3>Value Members</h3>
              <ol>{ valueMembers map (memberToHtml(_)) }</ol>
            </div>
        }

        { if (constructors.isEmpty) NodeSeq.Empty else
            <div id="constructors" class="members">
              <h3>Instance constructors</h3>
              <ol>{ constructors map (memberToHtml(_)) }</ol>
            </div>
        }

      </div>

    </body>

  def memberToHtml(mbr: MemberEntity): NodeSeq = {
    val attributes: List[comment.Body] = Nil
    <li name={ mbr.definitionName }>
      { signature(mbr, false) }
      { val prs: List[ParameterEntity] = mbr match {
          case cls: Class if cls.isCaseClass => cls.typeParams ::: (cls.primaryConstructor map (_.valueParams.flatten)).toList.flatten
          case trt: Trait => trt.typeParams
          case dfe: Def => dfe.typeParams ::: dfe.valueParams.flatten
          case ctr: Constructor => ctr.valueParams.flatten
          case _ => Nil
        }
        def paramCommentToHtml(pr: ParameterEntity) =
          if (pr.comment.isEmpty) NodeSeq.Empty else
            <li class={ if (pr.isTypeParam) "tparam" else "param" } name={ pr.name }>{
              commentToHtml(pr.comment.get)
            }</li>
        if (prs.isEmpty) NodeSeq.Empty else
          <ol class="paramcmts">{ prs map (paramCommentToHtml(_)) }</ol>
      }
      { val fvs: List[comment.Paragraph] = mbr.visibility.toList ::: mbr.flags
        if (fvs.isEmpty) NodeSeq.Empty else
          <ol class="attributes">{ fvs map { fv => <li>{ inlineToHtml(fv.text) }</li> } }</ol>

      }
      { if (mbr.comment.isEmpty) NodeSeq.Empty else
          <div class="comment">{ commentToHtml(mbr.comment) }</div>
      }
    </li>
  }

  def kindToString(mbr: MemberEntity): String = mbr match {
    case tpl: DocTemplateEntity =>
      if (tpl.isPackage) "package" else if (tpl.isClass) "class" else if (tpl.isTrait) "trait" else "object"
    case ctor: Constructor => "new"
    case tme: MemberEntity =>
      if (tme.isDef) "def" else if (tme.isVal) "val" else if (tme.isVar) "var" else "type"
  }

  def boundsToString(hi: Option[TypeEntity], lo: Option[TypeEntity]): String = {
    def bound0(bnd: Option[TypeEntity], pre: String): String = bnd match {
      case None => ""
      case Some(tpe) => pre + typeToHtml(tpe)
    }
    bound0(hi, " <: ") + bound0(lo, " >: ")
  }

  /** name, tparams, params, result */
  def signature(mbr: MemberEntity, isSelf: Boolean): NodeSeq = {
    val inside: NodeSeq =
      <xml:group>
      <div class="kind">{ kindToString(mbr) }</div>
      <div class="symbol">
        <span class="name">{ if (mbr.isConstructor) tpl.name else mbr.name }</span>
        { def tparamsToHtml(tpss: List[TypeParam]): NodeSeq =
            if (tpss.isEmpty) NodeSeq.Empty else {
              def tparam0(tp: TypeParam): NodeSeq =
                <span name={ tp.name }>{
                  tp.variance + tp.name + boundsToString(tp.hi, tp.lo)
                }</span>
              def tparams0(tpss: List[TypeParam]): NodeSeq = (tpss: @unchecked) match {
                case tp :: Nil => tparam0(tp)
                case tp :: tps => tparam0(tp) ++ Text(",") ++ tparams0(tps)
              }
              <span class="tparams">[{ tparams0(tpss) }]</span>
            }
          mbr match {
            case trt: Trait => tparamsToHtml(trt.typeParams)
            case dfe: Def => tparamsToHtml(dfe.typeParams)
            case _ => NodeSeq.Empty
          }
        }
        { def paramsToHtml(vlsss: List[List[ValueParam]]): NodeSeq = {
            def param0(vl: ValueParam): NodeSeq =
              <span name={ vl.name }>{
                vl.name + ": " + typeToHtml(vl.resultType)
              }</span>
            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)
            }
            vlsss map { vlss => <span class="params">({ params0(vlss) })</span> }
          }
          mbr match {
            case cls: Class if cls.isCaseClass => paramsToHtml(cls.primaryConstructor.get.valueParams)
            case ctr: Constructor => paramsToHtml(ctr.valueParams)
            case dfe: Def => paramsToHtml(dfe.valueParams)
            case _ => NodeSeq.Empty
          }
        }
        { mbr match {
            case tpl: DocTemplateEntity if (!tpl.isPackage) =>
              tpl.parentType match {
                case Some(st) => <span class="result">extends<span>{ typeToHtml(st) }</span></span>
                case None =>NodeSeq.Empty
              }
            case tme: MemberEntity if (tme.isDef || tme.isVal || tme.isVar) =>
              <span class="result">:<span>{ typeToHtml(tme.resultType) }</span></span>
            case abt: AbstractType =>
              val b2s = boundsToString(abt.hi, abt.lo)
              if (b2s != "")
                <span class="result"><span>{ b2s }</span></span>
              else NodeSeq.Empty
            case alt: AliasType =>
              <span class="result">=<span>{ typeToHtml(alt.alias) }</span></span>
            case _ => NodeSeq.Empty
          }
        }
      </div>
        </xml:group>
    mbr match {
      case dte: DocTemplateEntity if !isSelf =>
        <a class="signature" href={ relativeLinkTo(dte) }>{ inside }</a>
      case _ =>
        <div class="signature">{ inside }</div>
    }
  }

}