From 4659d81554c1eb5bda6730d48e0dfed747679862 Mon Sep 17 00:00:00 2001 From: Gilles Dubochet Date: Fri, 5 Nov 2010 15:32:14 +0000 Subject: [scaladoc] Annotations are modeled and printed. --- .../scala/tools/nsc/doc/html/page/Template.scala | 80 ++++++++++++++-------- .../scala/tools/nsc/doc/model/Entity.scala | 13 ++++ .../scala/tools/nsc/doc/model/ModelFactory.scala | 40 +++++++++-- .../scala/tools/nsc/doc/model/TreeEntity.scala | 2 +- 4 files changed, 103 insertions(+), 32 deletions(-) diff --git a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala index 622d2cdc22..9132d8754d 100644 --- a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala +++ b/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 =

{ inlineToHtml(mbr.comment.get.short) }

- 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
{ commentToHtml(mbr.comment) }
@@ -310,6 +310,30 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage { case _ => NodeSeq.Empty } } ++ + { if (!mbr.annotations.isEmpty) { +
+ annotations: { + mbr.annotations.map { annot => + + @{ templateToHtml(annot.annotationClass) }{ + def paramsToHtml(vls: List[ValueArgument]): NodeSeq = + vls map { vl => + { + vl.parameter match { + case Some(p) => Text(p.name + " = ") + case None => NodeSeq.Empty + } + }{ treeToHtml(vl.value) } + } + ({ paramsToHtml(annot.arguments) }) + } + + } + } +
+ } + 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 - { Text(vl.name + ": ") }{ typeToHtml(vl.resultType, hasLinks) }{ - if(!vl.defaultValue.isEmpty) { - defaultValueToHtml(vl.defaultValue.get); - } - else 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 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 + { Text(vl.name + ": ") }{ typeToHtml(vl.resultType, hasLinks) }{ + if(!vl.defaultValue.isEmpty) { + treeToHtml(vl.defaultValue.get); + } + else 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) }) } } - def implicitCheck(vlss: List[ValueParam]): NodeSeq = vlss match { - case vl :: vls => if(vl.isImplicit) { implicit } 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 => ({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 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 ++= {str.substring(from, to)} - case _ => assert(false, "unexpected case in defaultValueToHtml") } index = to } diff --git a/src/compiler/scala/tools/nsc/doc/model/Entity.scala b/src/compiler/scala/tools/nsc/doc/model/Entity.scala index 6d81b8271e..a042cf636a 100644 --- a/src/compiler/scala/tools/nsc/doc/model/Entity.scala +++ b/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 diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala index 080af68d27..449fdca7b9 100644 --- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala +++ b/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 = { @@ -375,6 +376,37 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory throw new Error("'" + bSym + "' that isn't a class, trait or object cannot be built as a documentable template") } + /** */ + 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] = { @@ -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) diff --git a/src/compiler/scala/tools/nsc/doc/model/TreeEntity.scala b/src/compiler/scala/tools/nsc/doc/model/TreeEntity.scala index 7a0c8c7961..425a735a3a 100644 --- a/src/compiler/scala/tools/nsc/doc/model/TreeEntity.scala +++ b/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) -} \ No newline at end of file +} -- cgit v1.2.3