summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorchrisJames <chrisJames@epfl.ch>2010-08-04 12:32:01 +0000
committerchrisJames <chrisJames@epfl.ch>2010-08-04 12:32:01 +0000
commitbf44cd12b16c701cc4ac94c86357128d44afc147 (patch)
treea18a2dcb863060f0dc0436f64079131b2cb2a319 /src
parentdb99926628a2b636a548049c1204fee78c77b9bb (diff)
downloadscala-bf44cd12b16c701cc4ac94c86357128d44afc147.tar.gz
scala-bf44cd12b16c701cc4ac94c86357128d44afc147.tar.bz2
scala-bf44cd12b16c701cc4ac94c86357128d44afc147.zip
[Scaladoc]
Prints default Values, considers anyRef as a class. closes #3105. Review by prokopec.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/doc/DocFactory.scala4
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/Template.scala74
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js7
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/Entity.scala2
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala5
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/TreeEntity.scala16
-rwxr-xr-xsrc/compiler/scala/tools/nsc/doc/model/TreeFactory.scala86
7 files changed, 187 insertions, 7 deletions
diff --git a/src/compiler/scala/tools/nsc/doc/DocFactory.scala b/src/compiler/scala/tools/nsc/doc/DocFactory.scala
index 066f800f79..d303d1e65a 100644
--- a/src/compiler/scala/tools/nsc/doc/DocFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/DocFactory.scala
@@ -26,7 +26,7 @@ import reporters.Reporter
class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor =>
/** The unique compiler instance used by this processor and constructed from its `settings`. */
- object compiler extends Global(settings, reporter) {
+ object compiler extends Global(settings, reporter) with interactive.RangePositions{
override protected def computeInternalPhases() {
phasesSet += syntaxAnalyzer
phasesSet += analyzer.namerFactory
@@ -51,7 +51,7 @@ class DocFactory(val reporter: Reporter, val settings: doc.Settings) { processor
compiler.addSourceless
assert(settings.docformat.value == "html")
if (!reporter.hasErrors) {
- val modelFactory = (new model.ModelFactory(compiler, settings) with model.comment.CommentFactory)
+ val modelFactory = (new model.ModelFactory(compiler, settings) with model.comment.CommentFactory with model.TreeFactory)
val docModel = modelFactory.makeModel
println("model contains " + modelFactory.templatesCount + " documentable templates")
(new html.HtmlFactory(docModel)).generate
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 dd7633a9a8..324b04a54f 100644
--- a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
@@ -39,8 +39,11 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
case _ => Nil
}) sortBy (_.name)
+ /* 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 =
- <body class={ if (tpl.isTrait || tpl.isClass) "type" else "value" } onload="windowTitle();">
+ <body class={ if (tpl.isTrait || tpl.isClass || tpl.qualifiedName == "scala.AnyRef") "type" else "value" } onload="windowTitle();">
{ if (tpl.isRootPackage || tpl.inTemplate.isRootPackage)
NodeSeq.Empty
@@ -406,7 +409,7 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
// 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) {
- Text(" = ") ++ <span class="default">{vl.defaultValue.get}</span>
+ defaultValueToHtml(vl.defaultValue.get);
}
else NodeSeq.Empty
}</span>
@@ -460,4 +463,71 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
}
}
+ /** */
+ def defaultValueToHtml(defVal:TreeEntity):NodeSeq = {
+ var index = 0
+ val str = defVal.expression
+ val length = str.length
+ var myXml: NodeSeq = NodeSeq.Empty
+ for( x <- defVal.refs) {
+ val from = x._1
+ val to = x._2._2
+ if (index < from) {
+ myXml ++= stringToXml(str.substring(index,from))
+ index = from
+ }
+
+ if (index == from) {
+ val member:Entity = x._2._1
+ member match {
+ case mbr: DocTemplateEntity =>
+ val link = relativeLinkTo(mbr)
+ myXml ++= <span class="name"><a href={link}>{str.substring(from, to)}</a></span>
+ case mbr: MemberEntity =>
+ 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
+ }
+ }
+ // function used in the MemberEntity case above
+ def defParamsString(mbr: Entity):String = mbr match {
+ case d:MemberEntity with Def => defParamsToString(d)
+ case _ => ""
+ }
+
+ if (index <= length-1) myXml ++= stringToXml(str.substring(index, length ))
+
+ Text(" =") ++
+ {
+ if(length< 7) <span class="symbol">{ myXml }</span>
+ else <span class="defval" name={ myXml }>{ " ..." }</span>
+ }
+ }
+
+ /** 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 stringToXml(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++= <br/> ++ indentation
+ case _ => goodLookingXml ++= Text(c.toString)
+ }
+ def indentation:NodeSeq = {
+ var indentXml = NodeSeq.Empty
+ for (x<- 1 to indent) indentXml ++= Text("&nbsp;&nbsp;")
+ indentXml
+ }
+ goodLookingXml
+ }
+
}
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js b/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js
index 6aacfb1390..c327e0f13e 100644
--- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js
@@ -102,6 +102,13 @@ $(document).ready(function(){
$(this.getTip()).text(this.getTrigger().attr("name"));
}
});
+ $(".defval").tooltip({
+ tip: "#tooltip",
+ position:"top center",
+ onBeforeShow: function(ev) {
+ $(this.getTip()).html(this.getTrigger().attr("name"))
+ }
+ });
var docAllSigs = $("#template .signature");
function commentShowFct(fullComment){
var vis = $(":visible", fullComment);
diff --git a/src/compiler/scala/tools/nsc/doc/model/Entity.scala b/src/compiler/scala/tools/nsc/doc/model/Entity.scala
index fc84ed8f6c..395ff66f33 100644
--- a/src/compiler/scala/tools/nsc/doc/model/Entity.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/Entity.scala
@@ -170,7 +170,7 @@ trait TypeParam extends ParameterEntity with HigherKinded {
/** A value parameter to a constructor or to a method. */
trait ValueParam extends ParameterEntity {
def resultType: TypeEntity
- def defaultValue: Option[String]
+ def defaultValue: Option[TreeEntity]
def isImplicit: Boolean
}
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
index fca26e69ce..f430b31c05 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
@@ -14,7 +14,7 @@ import symtab.Flags
import model.{ RootPackage => RootPackageEntity }
/** This trait extracts all required information for documentation from compilation units */
-class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory: ModelFactory with CommentFactory =>
+class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory: ModelFactory with CommentFactory with TreeFactory =>
import global._
import definitions.{ ObjectClass, ScalaObjectClass, RootPackage, EmptyPackage, NothingClass, AnyClass, AnyRefClass }
@@ -453,7 +453,8 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { thisFactory
(currentRun.units filter (_.source.file == aSym.sourceFile)).toList match {
case List(unit) =>
(unit.body find (_.symbol == aSym)) match {
- case Some(ValDef(_,_,_,rhs)) => Some(rhs.toString)
+ case Some(ValDef(_,_,_,rhs)) =>
+ Some(makeTree(rhs))
case _ => None
}
case _ => None
diff --git a/src/compiler/scala/tools/nsc/doc/model/TreeEntity.scala b/src/compiler/scala/tools/nsc/doc/model/TreeEntity.scala
new file mode 100644
index 0000000000..7a0c8c7961
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/doc/model/TreeEntity.scala
@@ -0,0 +1,16 @@
+
+
+
+/** we create a TreeEntity to store some text and some hyperLinks to make on entities in it */
+
+package scala.tools.nsc
+package doc
+package model
+
+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
diff --git a/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala b/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala
new file mode 100755
index 0000000000..6d71e93ae4
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/doc/model/TreeFactory.scala
@@ -0,0 +1,86 @@
+package scala.tools.nsc
+package doc
+package model
+
+/** The goal of this trait is , using makeDefaultValue,
+ * to browse the tree of default values to
+ * 1- have the String of the DefaultValue (tree.expression)
+ * 2- fill references to create hyperLinks later in html.pageTemplate
+ *
+ * It is applied in ModelFactory => makeValueParam
+ *
+ */
+
+trait TreeFactory {
+ thisTreeFactory: ModelFactory with TreeFactory =>
+ val global:Global
+
+ import global._
+
+ def makeTree(rhs:Tree):TreeEntity = {
+ val printSteps:Boolean = false
+ val tree = new TreeEntity
+ val firstIndex = rhs.pos.startOrPoint
+
+ /** Gets the full string of the right hand side of a parameter, without links */
+ def makeExpression(rhs:Tree){
+ val start = rhs.pos.startOrPoint
+ val end = rhs.pos.endOrPoint
+ var expr = ""
+ for (i <- start until end) expr += rhs.pos.source.content.apply(i)
+ rhs match {
+ case Block(r,s) => expr += "}"
+ case _ =>
+ }
+ tree.expression += expr
+ }
+
+ val traverser = new Traverser{
+ /** Finds the Entity on which we will later create a link on,
+ * stores it in tree.refs with its position
+ */
+ def makeLink(rhs:Tree){
+ var start = rhs.pos.point - firstIndex
+ val end = rhs.pos.endOrPoint - firstIndex
+ if(start != end) {
+ var asym = rhs.symbol
+ if (asym.isClass) makeTemplate(asym) match{
+ case docTmpl: DocTemplateImpl =>
+ tree.refs += ((start,(docTmpl,end)))
+ case _ =>
+ }
+ else if (asym.isTerm && asym.owner.isClass){
+ if (asym.isSetter) asym = asym.getter(asym.owner)
+ makeTemplate(asym.owner) match {
+ case docTmpl:DocTemplateImpl =>
+ val mbrs:List[MemberImpl] = makeMember(asym,docTmpl)
+ mbrs foreach {mbr =>
+ tree.refs += ((start,(mbr,end)))
+ }
+ case _ =>
+ }
+ }
+ }
+ }
+ /** Goes through the tree of the rhs and makes links when a Select occurs,
+ * The cas of New(_) is ignored because the object we want to create a link on
+ * will be reached with recursivity and we don't want a link on the "new" string
+ */
+ override def traverse(tree:Tree) = tree match {
+ case Select(qualifier, name) =>
+ qualifier match {
+ case New(_) =>
+ case _ => makeLink(tree)
+ }
+ traverse(qualifier)
+ case _ =>
+ super.traverse(tree)
+ }
+ }
+
+ makeExpression(rhs)
+ traverser.traverse(rhs)
+ return tree
+ }
+
+}