diff options
author | Kato Kazuyoshi <kato.kazuyoshi@gmail.com> | 2011-03-22 14:10:25 +0000 |
---|---|---|
committer | Kato Kazuyoshi <kato.kazuyoshi@gmail.com> | 2011-03-22 14:10:25 +0000 |
commit | fed7729dbb708ea2e1d138e79e20b9ec9bdbe3fd (patch) | |
tree | 12f3750d096bd48a3cb6c2c3f97befd659731edb | |
parent | 063e8a9dfee3d2c889f9e2e28cda2e8a28aa61cc (diff) | |
download | scala-fed7729dbb708ea2e1d138e79e20b9ec9bdbe3fd.tar.gz scala-fed7729dbb708ea2e1d138e79e20b9ec9bdbe3fd.tar.bz2 scala-fed7729dbb708ea2e1d138e79e20b9ec9bdbe3fd.zip |
[scaladoc] Closes #4366. Review by pedrofurla.
6 files changed, 111 insertions, 3 deletions
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 dd2093a88e..52ef154325 100644 --- a/src/compiler/scala/tools/nsc/doc/model/comment/Body.scala +++ b/src/compiler/scala/tools/nsc/doc/model/comment/Body.scala @@ -67,7 +67,18 @@ 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 -final case class HtmlTag(data: String) extends Inline +final case class HtmlTag(data: String) extends Inline { + def canClose(open: HtmlTag) = { + open.data.stripPrefix("<") == data.stripPrefix("</") + } + + def close = { + if (data.indexOf("</") == -1) + Some(HtmlTag("</" + data.stripPrefix("<"))) + else + None + } +} /** 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/Comment.scala b/src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala index e39907ac55..b3033188e9 100644 --- a/src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala +++ b/src/compiler/scala/tools/nsc/doc/model/comment/Comment.scala @@ -18,8 +18,41 @@ abstract class Comment { /** The main body of the comment that describes what the entity does and is. */ def body: Body + private def closeHtmlTags(inline: Inline) = { + val stack = mutable.ListBuffer.empty[HtmlTag] + def scan(i: Inline): Unit = { + i match { + case Chain(list) => + list.foreach(scan) + case tag: HtmlTag => { + if (stack.length > 0 && tag.canClose(stack.last)) { + stack.remove(stack.length-1) + } else { + tag.close match { + case Some(t) => + stack += t + case None => + ; + } + } + } + case _ => + ; + } + } + scan(inline) + Chain(List(inline) ++ stack.reverse) + } + /** A shorter version of the body. Usually, this is the first sentence of the body. */ - def short: Inline = body.summary getOrElse Text("") + def short: Inline = { + body.summary match { + case Some(s) => + closeHtmlTags(s) + case _ => + Text("") + } + } /** A list of authors. The empty list is used when no author is defined. */ 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 d82d5bfa5a..7485533641 100644 --- a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala +++ b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala @@ -172,7 +172,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory => /** Safe HTML tags that can be kept. */ protected val SafeTags = - new Regex("""((&\w+;)|(&#\d+;)|(<code( [^>]*)?>.*</code>)|(</?(abbr|acronym|address|area|a|bdo|big|blockquote|br|button|b|caption|cite|col|colgroup|dd|del|dfn|em|fieldset|form|hr|img|input|ins|i|kbd|label|legend|link|map|object|optgroup|option|param|pre|q|samp|select|small|span|strong|sub|sup|table|tbody|td|textarea|tfoot|th|thead|tr|tt|var)( [^>]*)?/?>))""") + new Regex("""((&\w+;)|(&#\d+;)|(<code( [^>]*)?>.*?</code>)|(</?(abbr|acronym|address|area|a|bdo|big|blockquote|br|button|b|caption|cite|col|colgroup|dd|del|dfn|em|fieldset|form|hr|img|input|ins|i|kbd|label|legend|link|map|object|optgroup|option|param|pre|q|samp|select|small|span|strong|sub|sup|table|tbody|td|textarea|tfoot|th|thead|tr|tt|var)( [^>]*)?/?>))""") protected val safeTagMarker = '\u000E' diff --git a/test/scaladoc/resources/Trac4366.scala b/test/scaladoc/resources/Trac4366.scala new file mode 100644 index 0000000000..d117ffa903 --- /dev/null +++ b/test/scaladoc/resources/Trac4366.scala @@ -0,0 +1,8 @@ +class Trac4366 { + /** + * <strong><code>foo</code> has been deprecated and will be removed in a future version of + * ScalaTest. Please call <code>bar</code> instead.</strong> + */ + @deprecated // deprecated in 1.0, remove in 1.4 + val foo: Option[String] = None +} diff --git a/test/scaladoc/scala/html/HtmlFactoryTest.scala b/test/scaladoc/scala/html/HtmlFactoryTest.scala index f0f1cd7e49..ecdbb3cf46 100644 --- a/test/scaladoc/scala/html/HtmlFactoryTest.scala +++ b/test/scaladoc/scala/html/HtmlFactoryTest.scala @@ -98,4 +98,30 @@ object Test extends Properties("HtmlFactory") { val files = createTemplates("Trac4306.scala") files("com/example/trac4306/foo/package$$Bar.html") != None } + + property("Trac #4366") = { + val files = createTemplates("Trac4366.scala") + files("Trac4366.html") match { + case node: scala.xml.Node => { + val comments = XMLUtil.stripGroup(node).descendant.flatMap { + case e: scala.xml.Elem => { + if (e.attribute("class").toString.contains("shortcomment")) { + Some(e) + } else { + None + } + } + case _ => None + } + + comments.exists { + (e) => { + val s = e.toString + s.contains("<code>foo</code>") && s.contains("</strong>") + } + } + } + case _ => false + } + } } diff --git a/test/scaladoc/scala/model/CommentFactoryTest.scala b/test/scaladoc/scala/model/CommentFactoryTest.scala index afe27dace0..25a91b1fa2 100644 --- a/test/scaladoc/scala/model/CommentFactoryTest.scala +++ b/test/scaladoc/scala/model/CommentFactoryTest.scala @@ -18,6 +18,9 @@ class Factory(val g: Global, val s: doc.Settings) def parseComment(s: String): Option[Inline] = strip(parse(s, "", scala.tools.nsc.util.NoPosition)) + + def createBody(s: String) = + parse(s, "", scala.tools.nsc.util.NoPosition).body } object Test extends Properties("CommentFactory") { @@ -95,4 +98,31 @@ object Test extends Properties("CommentFactory") { Text("\n"), HtmlTag("</pre>"))))))) ) + + property("Trac #4366 - body") = { + val body = factory.createBody( + """ + /** + * <strong><code>foo</code> has been deprecated and will be removed in a future version. Please call <code>bar</code> instead.</strong> + */ + """ + ) + + body == Body(List(Paragraph(Chain(List( + Summary(Chain(List(Chain(List(HtmlTag("<strong>"), HtmlTag("<code>foo</code>"), Text(" has been deprecated and will be removed in a future version"))), Text(".")))), + Chain(List(Text(" Please call "), HtmlTag("<code>bar</code>"), Text(" instead."), HtmlTag("</strong>"), Text("\n"), Text(""))) + ))))) + } + + property("Trac #4366 - summary") = { + val body = factory.createBody( + """ + /** + * <strong><code>foo</code> has been deprecated and will be removed in a future version. Please call <code>bar</code> instead.</strong> + */ + """ + ) + + body.summary == Some(Chain(List(Chain(List(HtmlTag("<strong>"), HtmlTag("<code>foo</code>"), Text(" has been deprecated and will be removed in a future version"))), Text(".")))) + } } |