summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorchrisJames <chrisJames@epfl.ch>2010-08-12 11:58:52 +0000
committerchrisJames <chrisJames@epfl.ch>2010-08-12 11:58:52 +0000
commit596ef0e94b3b4ea1b43b5eba49c5af014067798d (patch)
treeab94857ad03cc8786f03fea24c20123ac6943481 /src/compiler
parentb781e25afea36e2839d207125d3b91b35571d8ec (diff)
downloadscala-596ef0e94b3b4ea1b43b5eba49c5af014067798d.tar.gz
scala-596ef0e94b3b4ea1b43b5eba49c5af014067798d.tar.bz2
scala-596ef0e94b3b4ea1b43b5eba49c5af014067798d.zip
[Scaladoc] Improve the documentation of primary...
[Scaladoc] Improve the documentation of primary constructor. Adds a @constructor for commenting the primary constructor. It also adds some comments for the primary constructor (@params, @deprecated) which are initialised in the class comment. Members that come from primary constructor parameters (val parameters or parameters of a case class) are listed as members with the comment given using the @param tag (closes #254, closes #577). Case class signature now begins by 'case class' instead of 'class'. Review by dubochet
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala9
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/Template.scala8
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/Entity.scala22
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala11
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala5
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala114
6 files changed, 119 insertions, 50 deletions
diff --git a/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala b/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala
index 014dee3b20..47d7503534 100644
--- a/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala
@@ -223,8 +223,17 @@ abstract class HtmlPage { thisPage =>
def docEntityKindToString(ety: DocTemplateEntity) =
if (ety.isTrait) "trait"
+ else if (ety.isCaseClass) "case class"
else if (ety.isClass) "class"
else if (ety.isObject) "object"
else if (ety.isPackage) "package"
else "class" // FIXME: an entity *should* fall into one of the above categories, but AnyRef is somehow not
+
+ /** Returns the _big image name corresponding to the DocTemplate Entity (upper left icon) */
+ def docEntityKindToBigImage(ety: DocTemplateEntity) =
+ if (ety.isTrait) "trait_big.png"
+ else if (ety.isClass) "class_big.png"
+ else if (ety.isObject) "object_big.png"
+ else if (ety.isPackage) "package_big.png"
+ else "class_big.png" // FIXME: an entity *should* fall into one of the above categories, but AnyRef is somehow not
}
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 324b04a54f..a4c100884b 100644
--- a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
@@ -52,7 +52,7 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
}
<div id="definition">
- <img src={ relativeLinkTo(List(kindToString(tpl) + "_big.png", "lib")) }/>
+ <img src={ relativeLinkTo(List(docEntityKindToBigImage(tpl), "lib")) }/>
<h1>{ if (tpl.isRootPackage) "root package" else tpl.name }</h1>
</div>
@@ -210,8 +210,7 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
<div class="comment cmt">{ commentToHtml(mbr.comment) }</div>
} ++
{ val prs: List[ParameterEntity] = mbr match {
- case cls: Class if cls.isCaseClass =>
- cls.typeParams ::: (cls.primaryConstructor map (_.valueParams.flatten)).toList.flatten
+ 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
@@ -425,8 +424,7 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
vlsss map { vlss => <span class="params">({implicitCheck(vlss) ++ params0(vlss) })</span> }
}
mbr match {
- case cls: Class if cls.isCaseClass && cls.primaryConstructor.isDefined =>
- paramsToHtml(cls.primaryConstructor.get.valueParams)
+ case cls: Class => paramsToHtml(cls.valueParams)
case ctr: Constructor => paramsToHtml(ctr.valueParams)
case dfe: Def => paramsToHtml(dfe.valueParams)
case _ => NodeSeq.Empty
diff --git a/src/compiler/scala/tools/nsc/doc/model/Entity.scala b/src/compiler/scala/tools/nsc/doc/model/Entity.scala
index 395ff66f33..6d81b8271e 100644
--- a/src/compiler/scala/tools/nsc/doc/model/Entity.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/Entity.scala
@@ -33,6 +33,7 @@ trait TemplateEntity extends Entity {
def isClass: Boolean
def isObject: Boolean
def isDocTemplate: Boolean
+ def isCaseClass: Boolean
def selfType : Option[TypeEntity]
}
trait NoDocTemplate extends TemplateEntity
@@ -83,33 +84,16 @@ trait DocTemplateEntity extends TemplateEntity with MemberEntity {
def abstractTypes: List[AbstractType]
def aliasTypes: List[AliasType]
def companion: Option[DocTemplateEntity]
- // temporary implementation: to be removed
- def findMember(str: String): Option[DocTemplateEntity] = {
- val root = toRoot.last
- val path = if (str.length > 0) str.split("\\.") else Array[String]()
- var i = 0;
- var found: DocTemplateEntity = root
- while(i < path.length && found != null) {
- found = found.members.find(_.name == path(i)) match {
- case Some(doc:DocTemplateEntity) => doc
- case _ => null
- }
- i += 1
- }
- Option(found)
- }
}
/** A ''documentable'' trait. */
-trait Trait extends DocTemplateEntity with HigherKinded {
- def valueParams : List[List[ValueParam]]
-}
+trait Trait extends DocTemplateEntity with HigherKinded
/** A ''documentable'' class. */
trait Class extends Trait with HigherKinded {
def primaryConstructor: Option[Constructor]
def constructors: List[Constructor]
- def isCaseClass: Boolean
+ def valueParams: List[List[ValueParam]]
}
/** A ''documentable'' object. */
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
index f430b31c05..e36df22435 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
@@ -70,6 +70,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
def isTrait = sym.isTrait
def isClass = sym.isClass && !sym.isTrait
def isObject = sym.isModule && !sym.isPackage
+ def isCaseClass = sym.isClass && sym.hasFlag(Flags.CASE)
def isRootPackage = false
def selfType = if (sym.thisSym eq sym) None else Some(makeType(sym.thisSym.typeOfThis, this))
}
@@ -354,18 +355,16 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
else if (bSym.isModule || (bSym.isAliasType && bSym.tpe.typeSymbol.isModule))
new DocTemplateImpl(bSym, minimumInTpl) with Object
else if (bSym.isTrait || (bSym.isAliasType && bSym.tpe.typeSymbol.isTrait))
- new DocTemplateImpl(bSym, minimumInTpl) with Trait {
- def valueParams =
- List(sym.constrParamAccessors map (makeValueParam(_, this)))
- }
+ new DocTemplateImpl(bSym, minimumInTpl) with Trait
else if (bSym.isClass || (bSym.isAliasType && bSym.tpe.typeSymbol.isClass))
new DocTemplateImpl(bSym, minimumInTpl) with Class {
def valueParams =
- List(sym.constrParamAccessors map (makeValueParam(_, this)))
+ // we don't want params on a class (non case class) signature
+ if (isCaseClass) List(sym.constrParamAccessors map (makeValueParam(_, this)))
+ else List.empty
val constructors =
members collect { case d: Constructor => d }
def primaryConstructor = constructors find { _.isPrimary }
- def isCaseClass = sym.isClass && sym.hasFlag(Flags.CASE)
}
else
throw new Error("'" + bSym + "' that isn't a class, trait or object cannot be built as a documentable template")
diff --git a/src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala b/src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala
index 2a463959e5..fceb93b7c6 100644
--- a/src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala
@@ -19,7 +19,7 @@ abstract class Comment {
def body: Body
/** A shorter version of the body. Usually, this is the first sentence of the body. */
- def short: Inline
+ def short: Inline = body.summary getOrElse Text("")
/** A list of authors. The empty list is used when no author is defined. */
def authors: List[Body]
@@ -62,6 +62,9 @@ abstract class Comment {
/** A usage example related to the entity. */
def example: List[Body]
+ /** A description for the primary constructor */
+ def constructor: Option[Body]
+
override def toString =
body.toString + "\n" +
(authors map ("@author " + _.toString)).mkString("\n") +
diff --git a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
index 6fe1fe06a4..94406ad2f8 100644
--- a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
@@ -36,13 +36,89 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
if (commentCache isDefinedAt key)
Some(commentCache(key))
else { // not reached for use-case comments
+ val c = defineComment(sym, inTpl)
+ if (c isDefined) commentCache += (sym, inTpl) -> c.get
+ c
+ }
+ }
+
+ /* A comment is usualy created by the parser, however for some special cases we have to give
+ * some inTpl comments (parent class for example) to the comment of the symbol
+ * This function manages some of those cases : Param accessor and Primary constructor
+ */
+ def defineComment(sym: global.Symbol, inTpl: => DocTemplateImpl):Option[Comment] =
+ //param accessor case
+ // We just need the @param argument, we put it into the body
+ if( sym.isParamAccessor &&
+ inTpl.comment.isDefined &&
+ inTpl.comment.get.valueParams.isDefinedAt(sym.encodedName)) {
+ val comContent = Some(inTpl.comment.get.valueParams(sym.encodedName))
+ Some(createComment(body0=comContent))
+ }
+
+ // Primary constructor case
+ // We need some content of the class definition : @constructor for the body,
+ // @param and @deprecated, we can add some more if necessary
+ else if (sym.isPrimaryConstructor && inTpl.comment.isDefined ) {
+ val tplComment = inTpl.comment.get
+ // If there is nothing to put into the comment there is no need to create it
+ if(tplComment.constructor.isDefined ||
+ tplComment.throws != Map.empty ||
+ tplComment.valueParams != Map.empty ||
+ tplComment.typeParams != Map.empty ||
+ tplComment.deprecated.isDefined
+ )
+ Some(createComment( body0 = tplComment.constructor,
+ throws0 = tplComment.throws,
+ valueParams0 = tplComment.valueParams,
+ typeParams0 = tplComment.typeParams,
+ deprecated0 = tplComment.deprecated
+ ))
+ else None
+ }
+ //other comment cases
+ // parse function will make the comment
+ else {
val rawComment = global.expandedDocComment(sym, inTpl.sym).trim
- if (rawComment == "") None else {
+ if (rawComment != "") {
val c = parse(rawComment, global.docCommentPos(sym))
- commentCache += (sym, inTpl) -> c
Some(c)
}
- }
+ else None
+ }
+
+ /* Creates comments with necessary arguments */
+ def createComment(body0: Option[Body] = None,
+ authors0: List[Body] = List.empty,
+ see0: List[Body] = List.empty,
+ result0: Option[Body] = None,
+ throws0: Map[String,Body] = Map.empty,
+ valueParams0: Map[String,Body] = Map.empty,
+ typeParams0: Map[String,Body] = Map.empty,
+ version0: Option[Body] = None,
+ since0: Option[Body] = None,
+ todo0: List[Body] = List.empty,
+ deprecated0: Option[Body] = None,
+ note0: List[Body] = List.empty,
+ example0: List[Body] = List.empty,
+ constructor0: Option[Body] = None
+ ):Comment =
+ new Comment{
+ val body = if(body0 isDefined) body0.get else Body(Seq.empty)
+ val authors = authors0
+ val see = see0
+ val result = result0
+ val throws = throws0
+ val valueParams = valueParams0
+ val typeParams = typeParams0
+ val version = version0
+ val since = since0
+ val todo = todo0
+ val deprecated = deprecated0
+ val note = note0
+ val example = example0
+ val constructor = constructor0
+
}
protected val endOfText = '\u0003'
@@ -235,22 +311,22 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
Map.empty[String, Body] ++ pairs
}
- val com = new Comment {
- val body = parseWiki(docBody, pos)
- val authors = allTags(SimpleTagKey("author"))
- val see = allTags(SimpleTagKey("see"))
- val result = oneTag(SimpleTagKey("return"))
- val throws = allSymsOneTag(SimpleTagKey("throws"))
- val valueParams = allSymsOneTag(SimpleTagKey("param"))
- val typeParams = allSymsOneTag(SimpleTagKey("tparam"))
- val version = oneTag(SimpleTagKey("version"))
- val since = oneTag(SimpleTagKey("since"))
- val todo = allTags(SimpleTagKey("todo"))
- val deprecated = oneTag(SimpleTagKey("deprecated"))
- val note = allTags(SimpleTagKey("note"))
- val example = allTags(SimpleTagKey("example"))
- val short = body.summary getOrElse Text("no summary matey")
- }
+ val com = createComment (
+ body0 = Some(parseWiki(docBody, pos)),
+ authors0 = allTags(SimpleTagKey("author")),
+ see0 = allTags(SimpleTagKey("see")),
+ result0 = oneTag(SimpleTagKey("return")),
+ throws0 = allSymsOneTag(SimpleTagKey("throws")),
+ valueParams0 = allSymsOneTag(SimpleTagKey("param")),
+ typeParams0 = allSymsOneTag(SimpleTagKey("tparam")),
+ version0 = oneTag(SimpleTagKey("version")),
+ since0 = oneTag(SimpleTagKey("since")),
+ todo0 = allTags(SimpleTagKey("todo")),
+ deprecated0 = oneTag(SimpleTagKey("deprecated")),
+ note0 = allTags(SimpleTagKey("note")),
+ example0 = allTags(SimpleTagKey("example")),
+ constructor0 = oneTag(SimpleTagKey("constructor"))
+ )
for ((key, _) <- bodyTags)
reporter.warning(pos, "Tag '@" + key.name + "' is not recognised")