summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGilles Dubochet <gilles.dubochet@epfl.ch>2009-12-09 14:12:50 +0000
committerGilles Dubochet <gilles.dubochet@epfl.ch>2009-12-09 14:12:50 +0000
commita17785f8be385cb795f903ff3c9dbebd856c94a9 (patch)
treebb367b7a41ea55ca03a9d0ed51f1000cabd061b3 /src
parent25d82e13f13684077de44bcfd6cf2433be9d40ae (diff)
downloadscala-a17785f8be385cb795f903ff3c9dbebd856c94a9.tar.gz
scala-a17785f8be385cb795f903ff3c9dbebd856c94a9.tar.bz2
scala-a17785f8be385cb795f903ff3c9dbebd856c94a9.zip
[scaladoc] Display of comments is improved.
Diffstat (limited to 'src')
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/DocComments.scala4
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala15
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/Template.scala94
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js18
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/template.css103
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/lib/template.js46
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/resource/template.html78
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/Entity.scala4
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala28
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala2
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala19
11 files changed, 310 insertions, 101 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/DocComments.scala b/src/compiler/scala/tools/nsc/ast/DocComments.scala
index 9baefe43b8..c89924ecb3 100755
--- a/src/compiler/scala/tools/nsc/ast/DocComments.scala
+++ b/src/compiler/scala/tools/nsc/ast/DocComments.scala
@@ -182,7 +182,7 @@ trait DocComments { self: SymbolTable =>
out append replacement
start = idx
case None =>
- println("no replacement for "+vname) // !!!
+ //println("no replacement for "+vname) // !!!
}
} else {
idx += 1
@@ -289,7 +289,7 @@ trait DocComments { self: SymbolTable =>
if (idx < str.length && (str charAt idx) == ' ') idx += 1
defs(sym) += vble -> str.substring(idx)
}
- if (defs(sym).nonEmpty) println("vars of "+sym+" = "+defs(sym)) // !!!
+ //if (defs(sym).nonEmpty) println("vars of "+sym+" = "+defs(sym)) // !!!
}
}
diff --git a/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala b/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala
index 90952c49d6..271f888bc5 100644
--- a/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala
@@ -14,7 +14,8 @@ import xml.{Unparsed, XML, NodeSeq}
import xml.dtd.{DocType, PublicID}
import scala.collection._
import scala.util.NameTransformer
-import java.io.File
+import java.nio.channels.Channels
+import java.io.{FileOutputStream, File}
/** An html page that is part of a Scaladoc site.
* @author David Bernard
@@ -54,7 +55,15 @@ abstract class HtmlPage { thisPage =>
</head>
{ body }
</html>
- XML.save(pageFile.getPath, html, site.encoding, xmlDecl = false, doctype = doctype)
+ val fos = new FileOutputStream(pageFile.getPath)
+ val w = Channels.newWriter(fos.getChannel, site.encoding)
+ try {
+ w.write("<?xml version='1.0' encoding='" + site.encoding + "'?>\n")
+ w.write( doctype.toString + "\n")
+ w.write(xml.Xhtml.toXhtml(html))
+ }
+ finally { w.close() ; fos.close() }
+ //XML.save(pageFile.getPath, html, site.encoding, xmlDecl = false, doctype = doctype)
}
def templateToPath(tpl: TemplateEntity): List[String] = {
@@ -121,7 +130,7 @@ abstract class HtmlPage { thisPage =>
case Title(in, 3) => <h3>{ inlineToHtml(in) }</h3>
case Title(in, _) => <h4>{ inlineToHtml(in) }</h4>
case Paragraph(in) => <p>{ inlineToHtml(in) }</p>
- case Code(data) => <p><code>{ Unparsed(data) }</code></p>
+ case Code(data) => <pre>{ Unparsed(data) }</pre>
case UnorderedList(items) =>
<ul>{items map { i => <li>{ blockToHtml(i) }</li>}}</ul>
case OrderedList(items) =>
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 b11db3bcff..d39b0a9698 100644
--- a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
@@ -58,10 +58,7 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
</div>
{ signature(tpl, true) }
-
- { if (tpl.comment.isEmpty) NodeSeq.Empty else
- <div id="comment">{ commentToHtml(tpl.comment) }</div>
- }
+ { memberToCommentHtml(tpl, true) }
<div id="template">
@@ -103,31 +100,88 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
val attributes: List[comment.Body] = Nil
<li name={ mbr.definitionName }>
{ signature(mbr, false) }
+ { memberToCommentHtml(mbr, false) }
+ </li>
+ }
+
+ def memberToCommentHtml(mbr: MemberEntity, isSelf: Boolean): NodeSeq = mbr match {
+ case dte: DocTemplateEntity if isSelf && mbr.comment.isDefined =>
+ <div id="comment" class="fullcomment">{ memberToFullCommentHtml(mbr, isSelf) }</div>
+ case dte: DocTemplateEntity if !isSelf && mbr.comment.isDefined =>
+ <p class="comment cmt">{ inlineToHtml(mbr.comment.get.short) }</p>
+ case _ if mbr.comment.isDefined =>
+ <p class="shortcomment cmt">{ inlineToHtml(mbr.comment.get.short) }</p>
+ <div class="fullcomment">{ memberToFullCommentHtml(mbr, isSelf) }</div>
+ case _ => NodeSeq.Empty
+ }
+
+ def memberToFullCommentHtml(mbr: MemberEntity, isSelf: Boolean): NodeSeq =
+ <xml:group>
+ { if (mbr.comment.isEmpty) NodeSeq.Empty else
+ <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 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>
+ def mbrCmt = mbr.comment.get
+ def paramCommentToHtml(prs: List[ParameterEntity]): NodeSeq = prs match {
+ case Nil =>
+ NodeSeq.Empty
+ case (tp: TypeParam) :: rest =>
+ val paramEntry: NodeSeq = {
+ <dt class="tparam">{ tp.name }</dt><dd class="cmt">{ bodyToHtml(mbrCmt.typeParams(tp.name)) }</dd>
+ }
+ paramEntry ++ paramCommentToHtml(rest)
+ case (vp: ValueParam) :: rest =>
+ val paramEntry: NodeSeq = {
+ <dt class="param">{ vp.name }</dt><dd class="cmt">{ bodyToHtml(mbrCmt.valueParams(vp.name)) }</dd>
+ }
+ paramEntry ++ paramCommentToHtml(rest)
+ }
+ if (mbr.comment.isEmpty) NodeSeq.Empty else {
+ val cmtedPrs = prs filter {
+ case tp: TypeParam => mbrCmt.typeParams isDefinedAt tp.name
+ case vp: ValueParam => mbrCmt.valueParams isDefinedAt vp.name
+ }
+ if (cmtedPrs.isEmpty) NodeSeq.Empty else
+ <dl class="paramcmts block">{
+ paramCommentToHtml(cmtedPrs) ++ (
+ mbrCmt.result match {
+ case None => NodeSeq.Empty
+ case Some(cmt) =>
+ <dt>returns</dt><dd class="cmt">{ bodyToHtml(cmt) }</dd>
+ })
+ }</dl>
+ }
}
{ 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>
-
+ <div class="block">{ fvs map { fv => { inlineToHtml(fv.text) ++ xml.Text(" ") } } }</div>
}
- { if (mbr.comment.isEmpty) NodeSeq.Empty else
- <div class="comment">{ commentToHtml(mbr.comment) }</div>
+ { def inheritanceElem(tpl: TemplateEntity): NodeSeq = tpl match {
+ case (dTpl: DocTemplateEntity) =>
+ <a href={ relativeLinkTo(dTpl) }>{ dTpl.name }</a>
+ case (ndTpl: NoDocTemplate) =>
+ xml.Text(ndTpl.name)
+ }
+ def inheritanceChain(tplss: List[TemplateEntity]): NodeSeq = (tplss: @unchecked) match {
+ case tpl :: Nil => inheritanceElem(tpl)
+ case tpl :: tpls =>
+ inheritanceElem(tpl) ++ xml.Text(" ⇐ ") ++ inheritanceChain(tpls)
+ }
+ val inDefTpls = mbr.inDefinitionTemplates
+ if (inDefTpls.tail.isEmpty && (inDefTpls.head == mbr.inTemplate)) NodeSeq.Empty else {
+ <div class="block">
+ definition classes: { inheritanceChain(inDefTpls) }
+ </div>
+ }
}
- </li>
- }
+ </xml:group>
def kindToString(mbr: MemberEntity): String = mbr match {
case tpl: DocTemplateEntity =>
@@ -207,9 +261,9 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
</xml:group>
mbr match {
case dte: DocTemplateEntity if !isSelf =>
- <a class="signature" href={ relativeLinkTo(dte) }>{ inside(hasLinks = false) }</a>
+ <h4 class="signature"><a href={ relativeLinkTo(dte) }>{ inside(hasLinks = false) }</a></h4>
case _ =>
- <div class="signature">{ inside(hasLinks = true) }</div>
+ <h4 class="signature">{ inside(hasLinks = true) }</h4>
}
}
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js b/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js
index 8f9b366ea9..ad8a53529b 100644
--- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/index.js
@@ -1,3 +1,6 @@
+// 2009 EPFL/LAMP
+// written by Gilles Dubochet with contributions by Johannes Rudolph and "spiros"
+
$(document).ready(function(){
cleanPackage($("#tpl"));
$("#tpl ol > li span:contains('(class)')").replaceWith("<img class='icon' src='lib/class.png'/>");
@@ -11,7 +14,7 @@ $(document).ready(function(){
$("#quickflt").focus(function(event) {
$("#quickflt").select();
});
- $("#quickflt").bind("keyup", function(event) {
+ function search() {
var query = $("#quickflt").attr("value");
// Regexp that matches CamelCase subbits: "BiSe" is
// "[a-z]*Bi[a-z]*Se" and matches "BitSet", "ABitSet", ...
@@ -28,7 +31,18 @@ $(document).ready(function(){
};
});
cleanPackage($("#tpl"));
- });
+ pendingTimeout = undefined;
+ };
+ var pendingTimeout = undefined;
+ $("#quickflt").bind("keyup", function(event) {
+ if (event.keyCode == 27) { // escape
+ $("#quickflt").attr("value", "");
+ }
+ if (pendingTimeout != undefined) {
+ clearTimeout(pendingTimeout);
+ }
+ pendingTimeout = setTimeout(search, 200); //delay 0.2 sec
+ });
$("#tpl .packages > li").prepend("<a class='packhide'>hide</a>");
$("#tpl .packages > li > a.packhide").click(function(event){
var action = $(this).text();
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.css b/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.css
index 00d95138e7..517c767241 100644
--- a/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.css
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/lib/template.css
@@ -3,6 +3,7 @@
text-decoration: none;
font-family: inherit;
font-size: inherit;
+ font-weight: normal;
border-width: 0px;
padding: 0px;
margin: 0px;
@@ -87,6 +88,18 @@ a:hover {
background-color: #000000;
}
+/* Member cells */
+
+div.members > ol {
+ background-color: white;
+}
+
+div.members > ol > li {
+ display: block;
+}
+
+/* Member signatures */
+
.signature {
padding: 1px;
font-family: monospace;
@@ -120,52 +133,96 @@ a:hover {
color: #561414;
}
-#template > div.members > ol {
- background-color: white;
+/* Comments text formating */
+
+.cmt {}
+
+.cmt p {
+ margin: 2px 0 2px 0;
}
-.members > ol > li {
+.cmt code {
+ font-family: monospace;
+ font-size: small;
+}
+
+.cmt pre {
+ display: block;
+ font-family: monospace;
+ font-size: small;
+ margin: 2px 0 2px 0;
+}
+
+/* Comments structured layout */
+
+p.comment {
display: block;
+ margin-left: 80px;
}
-.members .paramcmts {
+p.shortcomment {
+ display: block;
margin-left: 80px;
+ cursor: help;
}
-.members .paramcmts > li.tparam {
- background-color: #ffcc66;
- display: none;
+div.fullcomment {
+ display: block;
+ margin: 10px 0 10px 0;
}
-.members .paramcmts > li.param {
- background-color: #cc99ff;
- display: none;
+#template div.fullcomment {
+ margin: 6px 0 6px 80px;
}
-.members .attributes {
- border-bottom-color: black;
- border-bottom-style: solid;
- border-bottom-width: 1px;
- margin-left: 80px;
+div.fullcomment .block {
+ padding: 2px 0 2px 0;
+ border-top: 1px solid black;
+ border-bottom: 1px solid black;
}
-.members .attributes > li {
- padding: 2px;
- font-size: 10pt;
+div.fullcomment .block + .block {
+ border-top: none;
+}
+
+div.fullcomment .block > h5 {
+ font-style: italic;
+ font-weight: normal;
display: inline-block;
}
-.members .comment {
+div.fullcomment .comment {
+ margin: 6px 0 6px 0;
+}
+
+div.fullcomment dl.paramcmts > dt {
display: block;
- margin-left: 80px;
+ float: left;
+ font-weight: bold;
+ margin: 2px 4px 2px 0;
}
-.comment > p {
- margin-bottom: 4px;
- margin-top: 4px;
+div.fullcomment dl.paramcmts > dd {
display: block;
+ padding-left: 80px;
+ border-top: 1px dashed black;
+ border-bottom: 1px dashed black;
}
+div.fullcomment dl.paramcmts > dt:first-child + dd {
+ border-top: none;
+}
+
+div.fullcomment dl.paramcmts > dd:last-child {
+ border-bottom: none;
+}
+
+div.fullcomment dl.paramcmts > dd + dt + dd {
+ border-top: none;
+}
+
+/* Members filter tool */
+
#mbrsel {
padding: 4px;
background-color: #cccccc;
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 f1b864137d..2f5efb1ede 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
@@ -6,7 +6,7 @@ $(document).ready(function(){
prefilters.removeClass("in");
prefilters.addClass("out");
filterInherit();
- $("#ancestors > ol > li").click(function(event){
+ $("#ancestors > ol > li").click(function(){
if ($(this).hasClass("in")) {
$(this).removeClass("in");
$(this).addClass("out");
@@ -18,19 +18,59 @@ $(document).ready(function(){
filterInherit();
});
$(".signature .symbol .extype").hover(
- function(event){
+ function(){
var full = $(this).attr("name");
var short = $(this).text();
$(this).attr("name", short);
$(this).text(full);
},
- function(event){
+ function(){
var short = $(this).attr("name");
var full = $(this).text();
$(this).attr("name", full);
$(this).text(short);
}
);
+ $("#template div.fullcomment").hide();
+ var docAllSigs = $("#template .signature");
+ function commentShowFct(fullComment){
+ var vis = $(":visible", fullComment);
+ if (vis.length > 0) {
+ fullComment.slideUp(100);
+ }
+ else {
+ fullComment.slideDown(100);
+ }
+ };
+ var docShowSigs = docAllSigs.filter(function(){
+ return $("+ div.fullcomment", $(this)).length > 0;
+ });
+ docShowSigs.css("cursor", "help");
+ docShowSigs.click(function(){
+ commentShowFct($("+ div.fullcomment", $(this)));
+ });
+ function commentToggleFct(shortComment){
+ var vis = $("~ div.fullcomment:visible", shortComment);
+ if (vis.length > 0) {
+ shortComment.slideDown(100);
+ vis.slideUp(100);
+ }
+ else {
+ var hid = $("~ div.fullcomment:hidden", shortComment);
+ hid.slideDown(100);
+ shortComment.slideUp(100);
+ }
+ };
+ var docToggleSigs = docAllSigs.filter(function(){
+ return $("+ p.shortcomment", $(this)).length > 0;
+ });
+ docToggleSigs.css("cursor", "help");
+ docToggleSigs.click(function(){
+ commentToggleFct($("+ p.shortcomment", $(this)));
+ });
+ $("p.shortcomment").click(function(){
+ commentToggleFct($(this));
+ });
});
function filterInherit() {
diff --git a/src/compiler/scala/tools/nsc/doc/html/resource/template.html b/src/compiler/scala/tools/nsc/doc/html/resource/template.html
index 6bf91d96ee..68370bb264 100644
--- a/src/compiler/scala/tools/nsc/doc/html/resource/template.html
+++ b/src/compiler/scala/tools/nsc/doc/html/resource/template.html
@@ -23,15 +23,15 @@
<span class="result">extends<span>A[X]</span> with <span>C[Y]</span> with <span>B</span></span>
</div>
</div>
- <div id="comment" class="comment">
+ <div id="comment" class="comment cmt">
<p>This class can be used as an adaptor to create mutable maps from immutable map implementations. Only method empty has to be redefined if the immutable map on which this mutable map is originally based is not empty. empty is supposed to return the representation of an empty map.</p>
<p>A subtrait of collection.IndexedSeq which represents sequences that can be mutated.</p>
<p>The canonical builder for collections that are addable, i.e. that support an efficient + method which adds an element to the collection. Collections are <code>built</code> from their empty element using this + method.</p>
- <code class="block">
- Once upon a time<br/>
- In a land far far away<br/>
- There was a man
- </code>
+ <pre>
+Once upon a time
+In a land far far away
+There was a man
+ </pre>
</div>
<div id="template">
<div id="mbrsel">
@@ -54,33 +54,51 @@
<h3>Value Members</h3>
<ol>
<li name="toto.FlawedImpl#transform">
- <div class="signature">
+ <h4 class="signature">
<div class="kind">def</div>
<div class="symbol">
<span class="name">transform</span>
<span class="tparams">[<span name="T">T</span>, <span name="U">U ⊲ Int</span>]</span>
- <span class="params">(<span name="f">f: (A, B) => B</span>, <span name="b">b: <span class="extype" name="scala.Double">Double</span></span>)</span>
+ <span class="params">(<span name="f">f: (<a href="">A</a>, B) => B</span>, <span name="b">b: <span class="extype" name="scala.Double">Double</span></span>)</span>
<span class="result">:<span>ImmutableMapAdaptor[A, B]</span></span>
</div>
- </div>
- <ol class="paramcmts">
- <li class="tparam" name="T">
- <p>T an empty map.</p>
- </li>
- <li class="tparam" name="U">
- <p>U can be used as an adaptor to create mutable maps.</p>
- </li>
- <li class="param" name="f">
- <p>f can be used as an adaptor to create mutable maps from immutable map implementations. Only method empty has to be redefined.</p>
- </li>
- <li class="param" name="b">
- <p>b the immutable map on which this mutable map is originally based is not empty. empty is supposed to return the representation of an empty map.</p>
- </li>
- </ol>
- <ol class="attributes"><li>override</li><li>protected</li><li>@inline</li></ol>
- <div class="comment">
- <p>A subtrait of collection.IndexedSeq which represents sequences that can be mutated.</p>
- <p>The canonical builder for collections that are addable, i.e. that support an efficient + method which adds an element to the collection. Collections are built from their empty element using this + method.</p>
+ </h4>
+ <p class="shortcomment">
+ A subtrait of collection.IndexedSeq which represents sequences that can be mutated.
+ </p>
+ <div class="fullcomment">
+ <div class="block">
+ override protected <a>@inline</a>
+ </div>
+ <div class="comment cmt">
+ <p>A subtrait of collection.IndexedSeq which represents sequences that can be mutated.</p>
+ <p>The canonical builder for collections that are addable, i.e. that support an efficient + method which adds an element to the collection. Collections are built from their empty element using this + method.</p>
+ </div>
+ <dl class="paramcmts block">
+ <dt class="tparam">T</dt>
+ <dd class="cmt">
+ <p>an empty map.</p>
+ </dd>
+ <dt class="tparam">U</dt>
+ <dd class="cmt">
+ <p>can be used as an adaptor to create mutable maps.</p>
+ </dd>
+ <dt class="param">f</dt>
+ <dd class="cmt">
+ <p>can be used as an adaptor to create mutable maps from immutable map implementations. Only method empty has to be redefined.</p>
+ </dd>
+ <dt class="param">archeolugenialerwunshpunsh</dt>
+ <dd class="cmt">
+ <p>the immutable map on which this mutable map is originally based is not empty. empty is supposed to return the representation of an empty map.</p>
+ </dd>
+ <dt>returns</dt>
+ <dd class="cmt">
+ <p>some immutable map thinggy of no practical use.</p>
+ </dd>
+ </dl>
+ <div class="block">
+ <h5>Inheritance:</h5> this ⇐ <a>ASuper</a> ⇐ <a>SomeMore</a>
+ </div>
</div>
</li>
<li name="Map#curry">
@@ -99,7 +117,7 @@
<span class="name">randomize</span><span class="result">: <span>ImmutableMapAdaptor[A, B]</span></span>
</div>
</div>
- <div class="comment">
+ <div class="fullcomment">
<p>A subtrait of collection.IndexedSeq which represents sequences that can be mutated.</p>
<p>The canonical builder for collections that are addable, i.e. that support an efficient + method which adds an element to the collection. Collections are built from their empty element using this + method.</p>
</div>
@@ -149,9 +167,7 @@
<span class="tparams">[<span name="T">T</span>,<span name="U">U ⊲ Int</span>]</span>
</div>
</a>
- <div class="comment">
- <p>Some inner class</p>
- </div>
+ <p class="comment cmt">Some inner class</p>
</li>
<li>
<div class="signature">
diff --git a/src/compiler/scala/tools/nsc/doc/model/Entity.scala b/src/compiler/scala/tools/nsc/doc/model/Entity.scala
index 3130e906a8..ac28ff2219 100644
--- a/src/compiler/scala/tools/nsc/doc/model/Entity.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/Entity.scala
@@ -16,7 +16,6 @@ trait Entity {
def inTemplate: TemplateEntity
def toRoot: List[Entity]
def qualifiedName: String
- def comment: Option[Comment]
override def toString = qualifiedName
}
@@ -37,9 +36,10 @@ trait NoDocTemplate extends TemplateEntity
/** A member of a class, trait, object or package. */
trait MemberEntity extends Entity {
+ def comment: Option[Comment]
def inTemplate: DocTemplateEntity
def toRoot: List[MemberEntity]
- def inDefinitionTemplate: TemplateEntity
+ def inDefinitionTemplates: List[TemplateEntity]
def definitionName: String
def visibility: Option[Paragraph]
def flags: List[Paragraph]
diff --git a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
index 0a71ea63eb..02fb60065a 100644
--- a/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/ModelFactory.scala
@@ -40,17 +40,6 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { extractor =
def inTemplate = inTpl
def toRoot: List[EntityImpl] = this :: inTpl.toRoot
def qualifiedName = name
- val comment = {
- val whichSym =
- if (docComments isDefinedAt sym) Some(sym) else sym.allOverriddenSymbols find (docComments isDefinedAt _)
- whichSym map { s =>
- commentCache.getOrElse(s, {
- val c = commentFactory.parse(expandedDocComment(s), s.pos) // !!! which one should it be?
- commentCache += s -> c
- c
- })
- }
- }
}
/** Provides a default implementation for instances of the `WeakTemplateEntity` type. It must be instantiated as a
@@ -73,9 +62,19 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { extractor =
/** Provides a default implementation for instances of the `MemberEntity` type. It must be instantiated as a
* `SymbolicEntity` to access the compiler symbol that underlies the entity. */
abstract class MemberImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends EntityImpl(sym, inTpl) with MemberEntity {
+ val comment =
+ if (inTpl == null) None else {
+ val rawComment = expandedDocComment(sym, inTpl.sym)
+ if (rawComment == "") None else {
+ val c = commentFactory.parse(rawComment, docCommentPos(sym))
+ commentCache += sym -> c
+ Some(c)
+ }
+ }
override def inTemplate = inTpl
override def toRoot: List[MemberImpl] = this :: inTpl.toRoot
- lazy val inDefinitionTemplate = if (sym.owner == inTpl.sym) inTpl else makeTemplate(sym.owner)
+ def inDefinitionTemplates =
+ (if (sym.owner == inTpl.sym) inTpl else makeTemplate(sym.owner)) :: (sym.allOverriddenSymbols map { inhSym => makeTemplate(inhSym.owner) })
val visibility = {
def qual = {
val qq =
@@ -94,7 +93,6 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { extractor =
val fgs = mutable.ListBuffer.empty[Paragraph]
if (sym hasFlag Flags.IMPLICIT) fgs += Paragraph(Text("implicit"))
if (sym hasFlag Flags.SEALED) fgs += Paragraph(Text("sealed"))
- if (sym hasFlag Flags.OVERRIDE) fgs += Paragraph(Text("override"))
if (!sym.isTrait && (sym hasFlag Flags.ABSTRACT)) fgs += Paragraph(Text("abstract"))
if (!sym.isTrait && (sym hasFlag Flags.DEFERRED)) fgs += Paragraph(Text("abstract"))
if (!sym.isModule && (sym hasFlag Flags.FINAL)) fgs += Paragraph(Text("final"))
@@ -125,7 +123,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { extractor =
abstract class DocTemplateImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends MemberImpl(sym, inTpl) with TemplateImpl with DocTemplateEntity {
//if (inTpl != null) println("mbr " + sym + " in " + (inTpl.toRoot map (_.sym)).mkString(" > "))
templatesCache += ((sym, inTpl) -> this)
- override def definitionName = inDefinitionTemplate.qualifiedName + "." + name
+ override def definitionName = inDefinitionTemplates.head.qualifiedName + "." + name
val inSource = if (sym.sourceFile != null) Some(sym.sourceFile, sym.pos.line) else None
val typeParams = if (sym.isClass) sym.typeParams map (makeTypeParam(_, this)) else Nil
val parentType =
@@ -157,7 +155,7 @@ class ModelFactory(val global: Global, val settings: doc.Settings) { extractor =
abstract class NonTemplateMemberImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends MemberImpl(sym, inTpl) with NonTemplateMemberEntity {
override def qualifiedName = inTemplate.qualifiedName + "#" + name
- override def definitionName = inDefinitionTemplate.qualifiedName + "#" + name
+ override def definitionName = inDefinitionTemplates.head.qualifiedName + "#" + name
}
abstract class ParameterImpl(sym: Symbol, inTpl: => DocTemplateImpl) extends EntityImpl(sym, inTpl) with ParameterEntity {
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 1476af7de8..97ee9abdf0 100644
--- a/src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala
@@ -19,6 +19,8 @@ abstract class Comment {
def body: Body
/* author|deprecated|param|return|see|since|throws|version|todo|tparam */
+ def short: Inline
+
/** */
def authors: List[Body]
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 58526b6bc0..d51573364f 100644
--- a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
@@ -28,6 +28,12 @@ final class CommentFactory(val reporter: Reporter) { parser =>
protected def oops(msg: String): Nothing =
throw FatalError("program logic: " + msg)
+ protected val CleanHtml =
+ new Regex("""</?(p|h\d|pre|dl|dt|dd|ol|ul|li|blockquote|div|hr|br|br)\s*/?>""")
+
+ protected val ShortLineEnd =
+ new Regex("""\.|</(p|h\d|pre|dd|li|div|blockquote)>|<(hr|table)\s*/?>""")
+
/** The body of a comment, dropping start and end markers. */
protected val CleanComment =
new Regex("""(?s)\s*/\*\*((?:[^\*]\*)*)\*/\s*""")
@@ -157,6 +163,19 @@ final class CommentFactory(val reporter: Reporter) { parser =>
val since = oneTag(SimpleTagKey("since"))
val todo = allTags(SimpleTagKey("todo"))
val deprecated = oneTag(SimpleTagKey("deprecated"))
+ val short = {
+ val shortText = ShortLineEnd.findFirstMatchIn(docBody) match {
+ case None => docBody
+ case Some(m) => docBody.take(m.start)
+ }
+ val safeText = CleanHtml.replaceAllIn(shortText, "") // get rid of all layout-busting html tags
+ parseWiki(safeText, pos) match {
+ case Body(Paragraph(inl) :: _) => inl
+ case _ =>
+ reporter.warning(pos, "Comment must start with a sentence")
+ Text("")
+ }
+ }
}
for ((key, _) <- bodyTags)