summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorGilles Dubochet <gilles.dubochet@epfl.ch>2010-04-12 17:05:04 +0000
committerGilles Dubochet <gilles.dubochet@epfl.ch>2010-04-12 17:05:04 +0000
commitb3f909df2e71ab14661e2a8f099b871a165bd38a (patch)
tree740ea05a36ed2662072f28d16b441cb0dc25af55 /src/compiler
parentc315a6fe9ce88384ef2b59bb3530e068c874b1d0 (diff)
downloadscala-b3f909df2e71ab14661e2a8f099b871a165bd38a.tar.gz
scala-b3f909df2e71ab14661e2a8f099b871a165bd38a.tar.bz2
scala-b3f909df2e71ab14661e2a8f099b871a165bd38a.zip
[scaladoc] Comment summary (first sentence) is ...
[scaladoc] Comment summary (first sentence) is extracted by comment parser, which is a lot more robust and correct. No review.
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala1
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/comment/Body.scala42
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala106
3 files changed, 91 insertions, 58 deletions
diff --git a/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala b/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala
index 74ec740204..ae98ecf1f6 100644
--- a/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/HtmlPage.scala
@@ -167,6 +167,7 @@ abstract class HtmlPage { thisPage =>
case EntityLink(entity) => templateToHtml(entity)
case Monospace(text) => <code>{ Unparsed(text) }</code>
case Text(text) => Unparsed(text)
+ case Summary(in) => inlineToHtml(in)
}
def typeToHtml(tpe: model.TypeEntity, hasLinks: Boolean): NodeSeq = {
diff --git a/src/compiler/scala/tools/nsc/doc/model/comment/Body.scala b/src/compiler/scala/tools/nsc/doc/model/comment/Body.scala
index 7d2aee2d98..29e47fa578 100644
--- a/src/compiler/scala/tools/nsc/doc/model/comment/Body.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/comment/Body.scala
@@ -9,10 +9,41 @@ import scala.collection._
import java.net.URL
-/** */
-final case class Body(blocks: Seq[Block])
+/** A body of text. A comment has a single body, which is composed of at least one block. Inside every body is exactly
+ * one summary (see [[scala.tools.nsc.doc.model.comment.Summary]]). */
+final case class Body(blocks: Seq[Block]) {
-/** */
+ /** The summary text of the comment body. */
+ lazy val summary: Option[Inline] = {
+ def summaryInBlock(block: Block): Seq[Inline] = block match {
+ case Title(text, _) => summaryInInline(text)
+ case Paragraph(text) => summaryInInline(text)
+ case UnorderedList(items) => items flatMap { summaryInBlock(_) }
+ case OrderedList(items, _) => items flatMap { summaryInBlock(_) }
+ case DefinitionList(items) => items.values.toSeq flatMap { summaryInBlock(_) }
+ case _ => Nil
+ }
+ def summaryInInline(text: Inline): Seq[Inline] = text match {
+ case Summary(text) => List(text)
+ case Chain(items) => items flatMap { summaryInInline(_) }
+ case Italic(text) => summaryInInline(text)
+ case Bold(text) => summaryInInline(text)
+ case Underline(text) => summaryInInline(text)
+ case Superscript(text) => summaryInInline(text)
+ case Subscript(text) => summaryInInline(text)
+ case Link(_, title) => summaryInInline(title)
+ case _ => Nil
+ }
+ (blocks flatMap { summaryInBlock(_) }).toList match {
+ case Nil => None
+ case inline :: Nil => Some(inline)
+ case inlines => Some(Chain(inlines))
+ }
+ }
+
+}
+
+/** A block-level element of text, such as a paragraph or code block. */
sealed abstract class Block
final case class Title(text: Inline, level: Int) extends Block
@@ -23,7 +54,7 @@ final case class OrderedList(items: Seq[Block], style: String) extends Block
final case class DefinitionList(items: SortedMap[Inline, Block]) extends Block
final case class HorizontalRule() extends Block
-/** */
+/** An section of text inside a block, possibly with formatting. */
sealed abstract class Inline
final case class Chain(items: Seq[Inline]) extends Inline
@@ -36,3 +67,6 @@ final case class Link(target: String, title: Inline) extends Inline
final case class EntityLink(target: TemplateEntity) extends Inline
final case class Monospace(text: String) extends Inline
final case class Text(text: String) extends Inline
+
+/** The summary of a comment, usually its first sentence. There must be exactly one summary per body. */
+final case class Summary(text: Inline) extends Inline
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 dba538046a..f067555cc3 100644
--- a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
@@ -102,17 +102,15 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
* @param comment The raw comment string (including start and end markers) to be parsed.
* @param pos The position of the comment in source. */
protected def parse(comment: String, pos: Position): Comment = {
+
/** The cleaned raw comment as a list of lines. Cleaning removes comment start and end markers, line start markers
* and unnecessary whitespace. */
val cleaned: List[String] = {
def cleanLine(line: String): String = {
//replaceAll removes trailing whitespaces
line.replaceAll("""\s+$""", "") match {
- case "" => "" // Empty lines are require to keep paragraphs
case CleanCommentLine(ctl) => ctl
- case tl =>
- reporter.warning(pos, "Please re-check this line of the comment")
- tl
+ case tl => tl
}
}
val strippedComment = comment.trim.stripPrefix("/*").stripSuffix("*/")
@@ -221,20 +219,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
val deprecated = oneTag(SimpleTagKey("deprecated"))
val note = allTags(SimpleTagKey("note"))
val example = allTags(SimpleTagKey("example"))
- val short = {
- def findShort(blocks: Iterable[Block]): Inline =
- if (blocks.isEmpty) Text("")
- else blocks.head match {
- case Title(text, _) => text
- case Paragraph(text) => text
- case Code(data) => Monospace(data.lines.next)
- case UnorderedList(items) => findShort(items)
- case OrderedList(items, _) => findShort(items)
- case DefinitionList(items) => findShort(items.values)
- case HorizontalRule() => findShort(blocks.tail)
- }
- findShort(body.blocks)
- }
+ val short = body.summary getOrElse Text("no summary matey")
}
for ((key, _) <- bodyTags)
@@ -264,6 +249,8 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
* @author Gilles Dubochet */
protected final class WikiParser(val buffer: Array[Char], pos: Position) extends CharReader(buffer) { wiki =>
+ var summaryParsed = false
+
/** listStyle ::= '-' spc | '1.' spc | 'I.' spc | 'i.' spc | 'A.' spc | 'a.' spc
* Characters used to build lists and their constructors */
protected val listStyles = Map[String, (Seq[Block] => Block)]( // TODO Should this be defined at some list companion?
@@ -380,7 +367,16 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
/** {{{ para ::= inline '\n' }}} */
def para(): Block = {
- val p = Paragraph(inline(checkParaEnded()))
+ val p =
+ if (summaryParsed)
+ Paragraph(inline(false))
+ else {
+ val s = summary()
+ val r =
+ if (checkParaEnded) List(s) else List(s, inline(false))
+ summaryParsed = true
+ Paragraph(Chain(r))
+ }
while (char == endOfLine && char != endOfText)
nextChar()
p
@@ -388,34 +384,26 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
/* INLINES */
- def inline(isBlockEnd: => Boolean): Inline =
- inline(isBlockEnd, isBlockEnd)
+ def inline(isInlineEnd: => Boolean): Inline = {
- def inline(isInlineEnd: => Boolean, isBlockEnd: => Boolean): Inline = {
def inline0(): Inline = {
- if (check("'''"))
- bold(isInlineEnd, isBlockEnd)
- else if (check("''"))
- italic(isInlineEnd, isBlockEnd)
- else if (check("`"))
- monospace(isInlineEnd, isBlockEnd)
- else if (check("__"))
- underline(isInlineEnd, isBlockEnd)
- else if (check("^"))
- superscript(isInlineEnd, isBlockEnd)
- else if (check(",,"))
- subscript(isInlineEnd, isBlockEnd)
- else if (check("[["))
- link(isInlineEnd, isBlockEnd)
+ if (check("'''")) bold()
+ else if (check("''")) italic()
+ else if (check("`")) monospace()
+ else if (check("__")) underline()
+ else if (check("^")) superscript()
+ else if (check(",,")) subscript()
+ else if (check("[[")) link()
else {
- readUntil { check("''") || char == '`' || check("__") || char == '^' || check(",,") || check("[[") || isInlineEnd || isBlockEnd || char == endOfLine }
+ readUntil { check("''") || char == '`' || check("__") || char == '^' || check(",,") || check("[[") || isInlineEnd || checkParaEnded || char == endOfLine }
Text(getRead())
}
}
+
val inlines: List[Inline] = {
val iss = mutable.ListBuffer.empty[Inline]
iss += inline0()
- while(!isInlineEnd && !isBlockEnd && !checkParaEnded) {
+ while(!isInlineEnd && !checkParaEnded) {
if (char == endOfLine) nextChar()
val current = inline0()
(iss.last, current) match {
@@ -426,57 +414,66 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
}
iss.toList
}
+
inlines match {
case Nil => Text("")
case i :: Nil => i
- case i :: is => Chain(i :: is)
+ case is => Chain(is)
}
+
}
- def bold(isInlineEnd: => Boolean, isBlockEnd: => Boolean): Inline = {
+ def bold(): Inline = {
jump("'''")
- val i = inline(check("'''"), isBlockEnd)
+ val i = inline(check("'''"))
jump("'''")
Bold(i)
}
- def italic(isInlineEnd: => Boolean, isBlockEnd: => Boolean): Inline = {
+ def italic(): Inline = {
jump("''")
- val i = inline(check("''"), isBlockEnd)
+ val i = inline(check("''"))
jump("''")
Italic(i)
}
- def monospace(isInlineEnd: => Boolean, isBlockEnd: => Boolean): Inline = {
+ def monospace(): Inline = {
jump("`")
readUntil { char == '`' }
jump("`")
Monospace(getRead())
}
- def underline(isInlineEnd: => Boolean, isBlockEnd: => Boolean): Inline = {
+ def underline(): Inline = {
jump("__")
- val i = inline(check("__"), isBlockEnd)
+ val i = inline(check("__"))
jump("__")
Underline(i)
}
- def superscript(isInlineEnd: => Boolean, isBlockEnd: => Boolean): Inline = {
+ def superscript(): Inline = {
jump("^")
- val i = inline(check("^"), isBlockEnd)
+ val i = inline(check("^"))
jump("^")
Superscript(i)
}
- def subscript(isInlineEnd: => Boolean, isBlockEnd: => Boolean): Inline = {
+ def subscript(): Inline = {
jump(",,")
- val i = inline(check(",,"), isBlockEnd)
+ val i = inline(check(",,"))
jump(",,")
Subscript(i)
}
- protected val SchemeUri =
- new Regex("""([^:]+:.*)""")
+ def summary(): Inline = {
+ val i = inline(check("."))
+ Summary(
+ if (jump("."))
+ Chain(List(i, Text(".")))
+ else
+ i
+ )
+ }
def entityLink(query: String): Inline = findTemplate(query) match {
case Some(tpl) =>
@@ -485,14 +482,15 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
Text(query)
}
- def link(isInlineEnd: => Boolean, isBlockEnd: => Boolean): Inline = {
+ def link(): Inline = {
+ val SchemeUri = new Regex("""([^:]+:.*)""")
jump("[[")
readUntil { check("]]") || check(" ") }
val target = getRead()
val title =
if (!check("]]")) Some({
jump(" ")
- inline(check("]]"), isBlockEnd)
+ inline(check("]]"))
})
else None
jump("]]")