Permalink
Browse files

[scaladoc] Annotations are modeled and printed.

  • Loading branch information...
1 parent e3b2ebc commit 4659d81554c1eb5bda6730d48e0dfed747679862 Gilles Dubochet committed Nov 5, 2010
View
80 src/compiler/scala/tools/nsc/doc/html/page/Template.scala
@@ -219,7 +219,7 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
def memberToInlineCommentHtml(mbr: MemberEntity, isSelf: Boolean): NodeSeq =
<p class="comment cmt">{ inlineToHtml(mbr.comment.get.short) }</p>
- def memberToCommentBodyHtml(mbr: MemberEntity, isSelf: Boolean, isReduced: Boolean = false): NodeSeq =
+ def memberToCommentBodyHtml(mbr: MemberEntity, isSelf: Boolean, isReduced: Boolean = false): NodeSeq = {
NodeSeq.Empty ++
{ if (mbr.comment.isEmpty) NodeSeq.Empty else
<div class="comment cmt">{ commentToHtml(mbr.comment) }</div>
@@ -310,6 +310,30 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
case _ => NodeSeq.Empty
}
} ++
+ { if (!mbr.annotations.isEmpty) {
+ <div class="block">
+ annotations: {
+ mbr.annotations.map { annot =>
+ <xml:group>
+ <span class="name">@{ templateToHtml(annot.annotationClass) }</span>{
+ def paramsToHtml(vls: List[ValueArgument]): NodeSeq =
+ vls map { vl =>
+ <span>{
+ vl.parameter match {
+ case Some(p) => Text(p.name + " = ")
+ case None => NodeSeq.Empty
+ }
+ }{ treeToHtml(vl.value) }</span>
+ }
+ <span class="params">({ paramsToHtml(annot.arguments) })</span>
+ }
+ </xml:group>
+ }
+ }
+ </div>
+ }
+ else NodeSeq.Empty
+ } ++
{ mbr match {
case dtpl: DocTemplateEntity if (isSelf && dtpl.sourceUrl.isDefined && dtpl.inSource.isDefined && !isReduced) =>
val (absFile, line) = dtpl.inSource.get
@@ -351,6 +375,7 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
case None => NodeSeq.Empty
}
}
+ }
def kindToString(mbr: MemberEntity): String = mbr match {
case tpl: DocTemplateEntity => docEntityKindToString(tpl)
@@ -418,33 +443,35 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
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 a undesired withspace in output
- <span name={ vl.name }>{ Text(vl.name + ": ") }{ typeToHtml(vl.resultType, hasLinks) }{
- if(!vl.defaultValue.isEmpty) {
- defaultValueToHtml(vl.defaultValue.get);
- }
- else NodeSeq.Empty
- }</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)
+ def paramsToHtml(vlsss: List[List[ValueParam]]): NodeSeq = {
+ def param0(vl: ValueParam): NodeSeq =
+ // notice the }{ in the next lines, they are necessary to avoid a undesired withspace in output
+ <span name={ vl.name }>{ Text(vl.name + ": ") }{ typeToHtml(vl.resultType, hasLinks) }{
+ if(!vl.defaultValue.isEmpty) {
+ treeToHtml(vl.defaultValue.get);
+ }
+ else NodeSeq.Empty
+ }</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)
+ }
+ def implicitCheck(vlss: List[ValueParam]): NodeSeq = vlss match {
+ case vl :: vls => if(vl.isImplicit) { <span class="implicit">implicit </span> } else Text("")
+ case _ => Text("")
+ }
+ vlsss map { vlss => <span class="params">({implicitCheck(vlss) ++ params0(vlss) })</span> }
}
- def implicitCheck(vlss: List[ValueParam]): NodeSeq = vlss match {
- case vl :: vls => if(vl.isImplicit) { <span class="implicit">implicit </span> } else Text("")
- case _ => Text("")
+ mbr match {
+ case cls: Class => paramsToHtml(cls.valueParams)
+ case ctr: Constructor => paramsToHtml(ctr.valueParams)
+ case dfe: Def => paramsToHtml(dfe.valueParams)
+ case _ => NodeSeq.Empty
}
- vlsss map { vlss => <span class="params">({implicitCheck(vlss) ++ params0(vlss) })</span> }
}
- 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 tpl: DocTemplateEntity if (!tpl.isPackage) =>
@@ -477,7 +504,7 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
}
/** */
- def defaultValueToHtml(defVal:TreeEntity):NodeSeq = {
+ def treeToHtml(defVal:TreeEntity):NodeSeq = {
var index = 0
val str = defVal.expression
val length = str.length
@@ -500,7 +527,6 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
val anchor = "#" + mbr.name + defParamsString(mbr) + ":" + mbr.resultType.name
val link = relativeLinkTo(mbr.inTemplate)
myXml ++= <span class="name"><a href={link ++ anchor}>{str.substring(from, to)}</a></span>
- case _ => assert(false, "unexpected case in defaultValueToHtml")
}
index = to
}
View
13 src/compiler/scala/tools/nsc/doc/model/Entity.scala
@@ -18,6 +18,7 @@ trait Entity {
def qualifiedName: String
override def toString = qualifiedName
def universe: Universe
+ def annotations: List[Annotation]
}
/** A class, trait, object or package. A package is represented as an instance
@@ -158,6 +159,18 @@ trait ValueParam extends ParameterEntity {
def isImplicit: Boolean
}
+/** An annotation, defined by its class and its constructor arguments. */
+trait Annotation extends Entity {
+ def annotationClass: TemplateEntity
+ def arguments: List[ValueArgument]
+}
+
+/** A value that is passed as an argument to a value paramater. */
+trait ValueArgument {
+ def parameter: Option[ValueParam]
+ def value: TreeEntity
+}
+
/** An type that represents visibility of members. */
sealed trait Visibility {
def isProtected: Boolean = false
View
40 src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
@@ -59,6 +59,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
def toRoot: List[EntityImpl] = this :: inTpl.toRoot
def qualifiedName = name
val universe = thisFactory.universe
+ def annotations = sym.annotations.map(makeAnnotation)
}
/** Provides a default implementation for instances of the `WeakTemplateEntity` type. It must be instantiated as a
@@ -162,7 +163,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
templatesCache += (sym -> this)
lazy val definitionName = optimize(inDefinitionTemplates.head.qualifiedName + "." + name)
override def toRoot: List[DocTemplateImpl] = this :: inTpl.toRoot
- def inSource = if (sym.sourceFile != null) Some(sym.sourceFile, sym.pos.line) else None
+ def inSource = if (sym.sourceFile != null) Some((sym.sourceFile, sym.pos.line)) else None
def sourceUrl = {
def fixPath(s: String) = s.replaceAll("\\" + java.io.File.separator, "/")
val assumedSourceRoot: String = {
@@ -376,6 +377,37 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
}
/** */
+ def makeAnnotation(annot: AnnotationInfo): Annotation = {
+ val aSym = annot.atp.typeSymbol
+ new EntityImpl(aSym, makeTemplate(aSym.owner)) with Annotation {
+ def annotationClass =
+ makeTemplate(annot.atp.typeSymbol)
+ def arguments =
+ annotationClass match {
+ case aClass: Class =>
+ aClass.valueParams match {
+ case Nil => Nil
+ case vp :: vps =>
+ (vp zip annot.args) map { case (param, arg) =>
+ new ValueArgument {
+ def parameter = Some(param)
+ def value = makeTree(arg)
+ }
+ }
+ }
+ case _ =>
+ annot.args map { arg =>
+ new ValueArgument {
+ def parameter = None
+ def value = makeTree(arg)
+ }
+ }
+ }
+
+ }
+ }
+
+ /** */
def makeMember(aSym: Symbol, inTpl: => DocTemplateImpl): List[MemberImpl] = {
def makeMember0(bSym: Symbol): Option[MemberImpl] = {
@@ -457,17 +489,17 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
def isTypeParam = false
def isValueParam = true
def defaultValue =
- if (aSym.hasDefault)
+ if (aSym.hasDefault) {
// units.filter should return only one element
(currentRun.units filter (_.source.file == aSym.sourceFile)).toList match {
case List(unit) =>
(unit.body find (_.symbol == aSym)) match {
- case Some(ValDef(_,_,_,rhs)) =>
- Some(makeTree(rhs))
+ case Some(ValDef(_,_,_,rhs)) => Some(makeTree(rhs))
case _ => None
}
case _ => None
}
+ }
else None
def resultType =
makeType(sym.tpe, inTpl, sym)
View
2 src/compiler/scala/tools/nsc/doc/model/TreeEntity.scala
@@ -13,4 +13,4 @@ import scala.collection.immutable.TreeMap
class TreeEntity {
var expression:String = ""
var refs = new TreeMap[Int, (Entity, Int)] // start, (Entity to be linked to , end)
-}
+}

0 comments on commit 4659d81

Please sign in to comment.