From a17785f8be385cb795f903ff3c9dbebd856c94a9 Mon Sep 17 00:00:00 2001 From: Gilles Dubochet Date: Wed, 9 Dec 2009 14:12:50 +0000 Subject: [scaladoc] Display of comments is improved. --- src/compiler/scala/tools/nsc/ast/DocComments.scala | 4 +- .../scala/tools/nsc/doc/html/HtmlPage.scala | 15 ++- .../scala/tools/nsc/doc/html/page/Template.scala | 94 +++++++++++++++---- .../scala/tools/nsc/doc/html/resource/lib/index.js | 18 +++- .../tools/nsc/doc/html/resource/lib/template.css | 103 ++++++++++++++++----- .../tools/nsc/doc/html/resource/lib/template.js | 46 ++++++++- .../tools/nsc/doc/html/resource/template.html | 78 +++++++++------- .../scala/tools/nsc/doc/model/Entity.scala | 4 +- .../scala/tools/nsc/doc/model/ModelFactory.scala | 28 +++--- .../tools/nsc/doc/model/comment/Comment.scala | 2 + .../nsc/doc/model/comment/CommentFactory.scala | 19 ++++ 11 files changed, 310 insertions(+), 101 deletions(-) (limited to 'src') 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 => { body } - 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("\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) =>

{ inlineToHtml(in) }

case Title(in, _) =>

{ inlineToHtml(in) }

case Paragraph(in) =>

{ inlineToHtml(in) }

- case Code(data) =>

{ Unparsed(data) }

+ case Code(data) =>
{ Unparsed(data) }
case UnorderedList(items) => 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 { { signature(tpl, true) } - - { if (tpl.comment.isEmpty) NodeSeq.Empty else -
{ commentToHtml(tpl.comment) }
- } + { memberToCommentHtml(tpl, true) }
@@ -103,31 +100,88 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage { val attributes: List[comment.Body] = Nil
  • { signature(mbr, false) } + { memberToCommentHtml(mbr, false) } +
  • + } + + def memberToCommentHtml(mbr: MemberEntity, isSelf: Boolean): NodeSeq = mbr match { + case dte: DocTemplateEntity if isSelf && mbr.comment.isDefined => +
    { memberToFullCommentHtml(mbr, isSelf) }
    + case dte: DocTemplateEntity if !isSelf && mbr.comment.isDefined => +

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

    + case _ if mbr.comment.isDefined => +

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

    +
    { memberToFullCommentHtml(mbr, isSelf) }
    + case _ => NodeSeq.Empty + } + + def memberToFullCommentHtml(mbr: MemberEntity, isSelf: Boolean): NodeSeq = + + { if (mbr.comment.isEmpty) NodeSeq.Empty else +
    { commentToHtml(mbr.comment) }
    + } { 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 -
  • { - commentToHtml(pr.comment.get) - }
  • - if (prs.isEmpty) NodeSeq.Empty else -
      { prs map (paramCommentToHtml(_)) }
    + def mbrCmt = mbr.comment.get + def paramCommentToHtml(prs: List[ParameterEntity]): NodeSeq = prs match { + case Nil => + NodeSeq.Empty + case (tp: TypeParam) :: rest => + val paramEntry: NodeSeq = { +
    { tp.name }
    { bodyToHtml(mbrCmt.typeParams(tp.name)) }
    + } + paramEntry ++ paramCommentToHtml(rest) + case (vp: ValueParam) :: rest => + val paramEntry: NodeSeq = { +
    { vp.name }
    { bodyToHtml(mbrCmt.valueParams(vp.name)) }
    + } + 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 +
    { + paramCommentToHtml(cmtedPrs) ++ ( + mbrCmt.result match { + case None => NodeSeq.Empty + case Some(cmt) => +
    returns
    { bodyToHtml(cmt) }
    + }) + }
    + } } { val fvs: List[comment.Paragraph] = mbr.visibility.toList ::: mbr.flags if (fvs.isEmpty) NodeSeq.Empty else -
      { fvs map { fv =>
    1. { inlineToHtml(fv.text) }
    2. } }
    - +
    { fvs map { fv => { inlineToHtml(fv.text) ++ xml.Text(" ") } } }
    } - { if (mbr.comment.isEmpty) NodeSeq.Empty else -
    { commentToHtml(mbr.comment) }
    + { def inheritanceElem(tpl: TemplateEntity): NodeSeq = tpl match { + case (dTpl: DocTemplateEntity) => + { dTpl.name } + 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 { +
    + definition classes: { inheritanceChain(inDefTpls) } +
    + } } - - } +
    def kindToString(mbr: MemberEntity): String = mbr match { case tpl: DocTemplateEntity => @@ -207,9 +261,9 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage { mbr match { case dte: DocTemplateEntity if !isSelf => - { inside(hasLinks = false) } +

    { inside(hasLinks = false) }

    case _ => -
    { inside(hasLinks = true) }
    +

    { inside(hasLinks = true) }

    } } 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(""); @@ -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("hide"); $("#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 @@ extendsA[X] with C[Y] with B
    -
    +

    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.

    A subtrait of collection.IndexedSeq which represents sequences that can be mutated.

    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.

    - - Once upon a time
    - In a land far far away
    - There was a man -
    +
    +Once upon a time
    +In a land far far away
    +There was a man
    +			
    @@ -54,33 +54,51 @@

    Value Members

    1. -
      +

      def
      transform [T, U ⊲ Int] - (f: (A, B) => B, b: Double) + (f: (A, B) => B, b: Double) :ImmutableMapAdaptor[A, B]
      -

      -
        -
      1. -

        T an empty map.

        -
      2. -
      3. -

        U can be used as an adaptor to create mutable maps.

        -
      4. -
      5. -

        f can be used as an adaptor to create mutable maps from immutable map implementations. Only method empty has to be redefined.

        -
      6. -
      7. -

        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.

        -
      8. -
      -
      1. override
      2. protected
      3. @inline
      -
      -

      A subtrait of collection.IndexedSeq which represents sequences that can be mutated.

      -

      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.

      + +

      + A subtrait of collection.IndexedSeq which represents sequences that can be mutated. +

      +
      +
      + override protected @inline +
      +
      +

      A subtrait of collection.IndexedSeq which represents sequences that can be mutated.

      +

      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.

      +
      +
      +
      T
      +
      +

      an empty map.

      +
      +
      U
      +
      +

      can be used as an adaptor to create mutable maps.

      +
      +
      f
      +
      +

      can be used as an adaptor to create mutable maps from immutable map implementations. Only method empty has to be redefined.

      +
      +
      archeolugenialerwunshpunsh
      +
      +

      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.

      +
      +
      returns
      +
      +

      some immutable map thinggy of no practical use.

      +
      +
      +
      +
      Inheritance:
      this ⇐ ASuperSomeMore +
    2. @@ -99,7 +117,7 @@ randomize: ImmutableMapAdaptor[A, B]
    -
    +

    A subtrait of collection.IndexedSeq which represents sequences that can be mutated.

    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.

    @@ -149,9 +167,7 @@ [T,U ⊲ Int]
    -
    -

    Some inner class

    -
    +

    Some inner class

  • 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("""""") + + protected val ShortLineEnd = + new Regex("""\.||<(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) -- cgit v1.2.3