summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/DocComments.scala122
-rw-r--r--src/compiler/scala/tools/nsc/doc/html/page/Template.scala4
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala2
-rwxr-xr-xsrc/compiler/scala/tools/nsc/util/DocStrings.scala87
-rw-r--r--test/scaladoc/resources/explicit-inheritance-override.scala48
-rw-r--r--test/scaladoc/resources/explicit-inheritance-usecase.scala47
-rw-r--r--test/scaladoc/resources/implicit-inheritance-override.scala8
-rw-r--r--test/scaladoc/resources/inheritdoc-corner-cases.scala78
-rw-r--r--test/scaladoc/scala/html/HtmlFactoryTest.scala196
9 files changed, 503 insertions, 89 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/DocComments.scala b/src/compiler/scala/tools/nsc/ast/DocComments.scala
index 6a6379cca2..678f7b3028 100755
--- a/src/compiler/scala/tools/nsc/ast/DocComments.scala
+++ b/src/compiler/scala/tools/nsc/ast/DocComments.scala
@@ -19,6 +19,8 @@ import scala.collection.mutable
*/
trait DocComments { self: Global =>
+ var cookedDocComments = Map[Symbol, String]()
+
def reporter: Reporter
/** The raw doc comment map */
@@ -50,21 +52,29 @@ trait DocComments { self: Global =>
else sym.owner.ancestors map (sym overriddenSymbol _) filter (_ != NoSymbol)
}
- /** The raw doc comment of symbol `sym`, minus @usecase and @define sections, augmented by
+ /** The raw doc comment of symbol `sym`, minus usecase and define sections, augmented by
* missing sections of an inherited doc comment.
* If a symbol does not have a doc comment but some overridden version of it does,
* the doc comment of the overridden version is copied instead.
*/
- def cookedDocComment(sym: Symbol, docStr: String = ""): String = {
- val ownComment = if (docStr.length == 0) docComments get sym map (_.template) getOrElse ""
- else DocComment(docStr).template
- superComment(sym) match {
- case None =>
- ownComment
- case Some(sc) =>
- if (ownComment == "") sc
- else merge(sc, ownComment, sym)
- }
+ def cookedDocComment(sym: Symbol, docStr: String = ""): String = cookedDocComments.get(sym) match {
+ case Some(comment) =>
+ comment
+ case None =>
+ val ownComment = if (docStr.length == 0) docComments get sym map (_.template) getOrElse ""
+ else DocComment(docStr).template
+ val comment = superComment(sym) match {
+ case None =>
+ if (ownComment.indexOf("@inheritdoc") != -1)
+ reporter.warning(sym.pos, "The comment for " + sym +
+ " contains @inheritdoc, but no parent comment is available to inherit from.")
+ ownComment.replaceAllLiterally("@inheritdoc", "<invalid inheritdoc annotation>")
+ case Some(sc) =>
+ if (ownComment == "") sc
+ else expandInheritdoc(sc, merge(sc, ownComment, sym), sym)
+ }
+ cookedDocComments += (sym -> comment)
+ comment
}
/** The cooked doc comment of symbol `sym` after variable expansion, or "" if missing.
@@ -99,10 +109,18 @@ trait DocComments { self: Global =>
*/
def useCases(sym: Symbol, site: Symbol): List[(Symbol, String, Position)] = {
def getUseCases(dc: DocComment) = {
- for (uc <- dc.useCases; defn <- uc.expandedDefs(sym, site)) yield
- (defn,
- expandVariables(merge(cookedDocComment(sym), uc.comment.raw, defn), sym, site),
- uc.pos)
+ val fullSigComment = cookedDocComment(sym)
+ for (uc <- dc.useCases; defn <- uc.expandedDefs(sym, site)) yield {
+ // use cases comments go through a series of transformations:
+ // 1 - filling in missing sections from the full signature
+ // 2 - expanding explicit inheritance @inheritdoc tags
+ // 3 - expanding variables like $COLL
+ val useCaseCommentRaw = uc.comment.raw
+ val useCaseCommentMerged = merge(fullSigComment, useCaseCommentRaw, defn)
+ val useCaseCommentInheritdoc = expandInheritdoc(fullSigComment, useCaseCommentMerged, sym)
+ val useCaseCommentVariables = expandVariables(useCaseCommentInheritdoc, sym, site)
+ (defn, useCaseCommentVariables, uc.pos)
+ }
}
getDocComment(sym) map getUseCases getOrElse List()
}
@@ -201,6 +219,80 @@ trait DocComments { self: Global =>
}
}
+ /**
+ * Expand inheritdoc tags
+ * - for the main comment we transform the inheritdoc into the super variable,
+ * and the variable expansion can expand it further
+ * - for the param, tparam and throws sections we must replace comments on the spot
+ *
+ * This is done separately, for two reasons:
+ * 1. It takes longer to run compared to merge
+ * 2. The inheritdoc annotation should not be used very often, as building the comment from pieces severely
+ * impacts performance
+ */
+ def expandInheritdoc(src: String, dst: String, sym: Symbol): String =
+ if (dst.indexOf("@inheritdoc") == -1)
+ dst
+ else {
+ val srcSections = tagIndex(src)
+ val dstSections = tagIndex(dst)
+ val srcTagMap = sectionTagMap(src, srcSections)
+ val srcNamedParams = Map() +
+ ("@param" -> paramDocs(src, "@param", srcSections)) +
+ ("@tparam" -> paramDocs(src, "@tparam", srcSections)) +
+ ("@throws" -> paramDocs(src, "@throws", srcSections))
+
+ val out = new StringBuilder
+
+ def replaceInheritdoc(src: String, dst: String) =
+ if (dst.indexOf("@inheritdoc") == -1)
+ dst
+ else
+ dst.replaceAllLiterally("@inheritdoc", src)
+
+ def getSourceSection(section: (Int, Int)): String = {
+
+ def getSectionHeader = extractSectionTag(dst, section) match {
+ case param@("@param"|"@tparam"|"@throws") => param + " " + extractSectionParam(dst, section)
+ case other => other
+ }
+
+ def sectionString(param: String, paramMap: Map[String, (Int, Int)]): String =
+ paramMap.get(param) match {
+ case Some(section) =>
+ // Cleanup the section tag and parameter
+ val sectionTextBounds = extractSectionText(src, section)
+ cleanupSectionText(src.substring(sectionTextBounds._1, sectionTextBounds._2))
+ case None =>
+ reporter.info(sym.pos, "The \"" + getSectionHeader + "\" annotation of the " + sym +
+ " comment contains @inheritdoc, but the corresponding section in the parent is not defined.", true)
+ "<invalid inheritdoc annotation>"
+ }
+
+ dst.substring(section._1, section._1 + 7) match {
+ case param@("@param "|"@tparam"|"@throws") => sectionString(extractSectionParam(dst, section), srcNamedParams(param.trim))
+ case _ => sectionString(extractSectionTag(dst, section), srcTagMap)
+ }
+ }
+
+ def mainComment(str: String, sections: List[(Int, Int)]): String =
+ if (str.trim.length > 3)
+ str.trim.substring(3, startTag(str, sections))
+ else
+ ""
+
+ // Append main comment
+ out.append("/**")
+ out.append(replaceInheritdoc(mainComment(src, srcSections), mainComment(dst, dstSections)))
+
+ // Append sections
+ for (section <- dstSections)
+ out.append(replaceInheritdoc(getSourceSection(section), dst.substring(section._1, section._2)))
+
+ out.append("*/")
+ out.toString
+ }
+
/** Maps symbols to the variable -> replacement maps that are defined
* in their doc comments
*/
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 5e5320ca9a..e35286b281 100644
--- a/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
+++ b/src/compiler/scala/tools/nsc/doc/html/page/Template.scala
@@ -438,7 +438,9 @@ class Template(tpl: DocTemplateEntity) extends HtmlPage {
if(!comment.throws.isEmpty) {
<dt>Exceptions thrown</dt>
<dd>{
- val exceptionsXml: Iterable[scala.xml.NodeSeq] = (for(exception <- comment.throws ) yield <span class="cmt">{Text(exception._1) ++ bodyToHtml(exception._2)}</span> )
+ val exceptionsXml: Iterable[scala.xml.NodeSeq] =
+ for(exception <- comment.throws.toList.sortBy(_._1) ) yield
+ <span class="cmt">{Text(exception._1) ++ bodyToHtml(exception._2)}</span>
exceptionsXml.reduceLeft(_ ++ Text("") ++ _)
}</dd>
} else NodeSeq.Empty
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 efa524503c..b088c643cb 100644
--- a/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/comment/CommentFactory.scala
@@ -38,7 +38,7 @@ trait CommentFactory { thisFactory: ModelFactory with CommentFactory =>
val key = (sym, inTpl)
if (commentCache isDefinedAt key)
Some(commentCache(key))
- else { // not reached for use-case comments
+ else {
val c = defineComment(sym, inTpl)
if (c isDefined) commentCache += (sym, inTpl) -> c.get
c
diff --git a/src/compiler/scala/tools/nsc/util/DocStrings.scala b/src/compiler/scala/tools/nsc/util/DocStrings.scala
index fbe92e5d84..f4ce6d6ef1 100755
--- a/src/compiler/scala/tools/nsc/util/DocStrings.scala
+++ b/src/compiler/scala/tools/nsc/util/DocStrings.scala
@@ -26,6 +26,14 @@ object DocStrings {
if (start < str.length && isIdentifierPart(str charAt start)) skipIdent(str, start + 1)
else start
+ /** Returns index of string `str` following `start` skipping
+ * sequence of identifier characters.
+ */
+ def skipTag(str: String, start: Int): Int =
+ if (start < str.length && (str charAt start) == '@') skipIdent(str, start + 1)
+ else start
+
+
/** Returns index of string `str` after `start` skipping longest
* sequence of space and tab characters, possibly also containing
* a single `*` character or the `/``**` sequence.
@@ -68,38 +76,46 @@ object DocStrings {
/** Produces a string index, which is a list of ``sections'', i.e
* pairs of start/end positions of all tagged sections in the string.
- * Every section starts with a `@` and extends to the next `@`, or
- * to the end of the comment string, but excluding the final two
+ * Every section starts with an at sign and extends to the next at sign,
+ * or to the end of the comment string, but excluding the final two
* characters which terminate the comment.
*
* Also take usecases into account - they need to expand until the next
* usecase or the end of the string, as they might include other sections
* of their own
*/
- def tagIndex(str: String, p: Int => Boolean = (idx => true)): List[(Int, Int)] =
- findAll(str, 0) (idx => str(idx) == '@' && p(idx)) match {
+ def tagIndex(str: String, p: Int => Boolean = (idx => true)): List[(Int, Int)] = {
+ var indices = findAll(str, 0) (idx => str(idx) == '@' && p(idx))
+ indices = mergeUsecaseSections(str, indices)
+ indices = mergeInheritdocSections(str, indices)
+
+ indices match {
case List() => List()
- case idxs => {
- val idxs2 = mergeUsecaseSections(str, idxs)
- idxs2 zip (idxs2.tail ::: List(str.length - 2))
- }
+ case idxs => idxs zip (idxs.tail ::: List(str.length - 2))
}
+ }
/**
* Merge sections following an usecase into the usecase comment, so they
* can override the parent symbol's sections
*/
def mergeUsecaseSections(str: String, idxs: List[Int]): List[Int] = {
- idxs.find(str.substring(_).startsWith("@usecase")) match {
- case Some(firstUC) =>
- val commentSections = idxs.take(idxs.indexOf(firstUC))
- val usecaseSections = idxs.drop(idxs.indexOf(firstUC)).filter(str.substring(_).startsWith("@usecase"))
+ idxs.indexWhere(str.substring(_).startsWith("@usecase")) match {
+ case firstUCIndex if firstUCIndex != -1 =>
+ val commentSections = idxs.take(firstUCIndex)
+ val usecaseSections = idxs.drop(firstUCIndex).filter(str.substring(_).startsWith("@usecase"))
commentSections ::: usecaseSections
- case None =>
+ case _ =>
idxs
}
}
+ /**
+ * Merge the inheritdoc sections, as they never make sense on their own
+ */
+ def mergeInheritdocSections(str: String, idxs: List[Int]): List[Int] =
+ idxs.filterNot(str.substring(_).startsWith("@inheritdoc"))
+
/** Does interval `iv` start with given `tag`?
*/
def startsWithTag(str: String, section: (Int, Int), tag: String): Boolean =
@@ -108,12 +124,11 @@ object DocStrings {
def startsWithTag(str: String, start: Int, tag: String): Boolean =
str.startsWith(tag, start) && !isIdentifierPart(str charAt (start + tag.length))
-
/** The first start tag of a list of tag intervals,
* or the end of the whole comment string - 2 if list is empty
*/
def startTag(str: String, sections: List[(Int, Int)]) = sections match {
- case List() => str.length - 2
+ case Nil => str.length - 2
case (start, _) :: _ => start
}
@@ -155,4 +170,46 @@ object DocStrings {
idx
}
}
+
+ /** A map from the section tag to section parameters */
+ def sectionTagMap(str: String, sections: List[(Int, Int)]): Map[String, (Int, Int)] =
+ Map() ++ {
+ for (section <- sections) yield
+ extractSectionTag(str, section) -> section
+ }
+
+ /** Extract the section tag, treating the section tag as an indentifier */
+ def extractSectionTag(str: String, section: (Int, Int)): String =
+ str.substring(section._1, skipTag(str, section._1))
+
+ /** Extract the section parameter */
+ def extractSectionParam(str: String, section: (Int, Int)): String = {
+ assert(str.substring(section._1).startsWith("@param") ||
+ str.substring(section._1).startsWith("@tparam") ||
+ str.substring(section._1).startsWith("@throws"))
+
+ val start = skipWhitespace(str, skipTag(str, section._1))
+ val finish = skipIdent(str, start)
+
+ str.substring(start, finish)
+ }
+
+ /** Extract the section text, except for the tag and comment newlines */
+ def extractSectionText(str: String, section: (Int, Int)): (Int, Int) = {
+ if (str.substring(section._1).startsWith("@param") ||
+ str.substring(section._1).startsWith("@tparam") ||
+ str.substring(section._1).startsWith("@throws"))
+ (skipWhitespace(str, skipIdent(str, skipWhitespace(str, skipTag(str, section._1)))), section._2)
+ else
+ (skipWhitespace(str, skipTag(str, section._1)), section._2)
+ }
+
+ /** Cleanup section text */
+ def cleanupSectionText(str: String) = {
+ var result = str.trim.replaceAll("\n\\s+\\*\\s+", " \n")
+ while (result.endsWith("\n"))
+ result = result.substring(0, str.length - 1)
+ result
+ }
+
}
diff --git a/test/scaladoc/resources/explicit-inheritance-override.scala b/test/scaladoc/resources/explicit-inheritance-override.scala
new file mode 100644
index 0000000000..62ce653aea
--- /dev/null
+++ b/test/scaladoc/resources/explicit-inheritance-override.scala
@@ -0,0 +1,48 @@
+// This tests the implicit comment inheritance capabilities of scaladoc for class inheritance (no $super, no @inheritdoc)
+class InheritDocBase {
+ /**
+ * The base comment. And another sentence...
+ *
+ * @param arg1 The T term comment
+ * @param arg2 The string comment
+ * @tparam T the type of the first argument
+ * @throws SomeException if the function is not called with correct parameters
+ * @return The return comment
+ * @see The Manual
+ * @note Be careful!
+ * @example function[Int](3, "something")
+ * @author a Scala developer
+ * @version 0.0.2
+ * @since 0.0.1
+ * @todo Call mom.
+ */
+ def function[T](arg1: T, arg2: String): Double = 0.0d
+}
+
+class InheritDocDerived extends InheritDocBase {
+ /**
+ * Starting line
+ *
+ * @inheritdoc
+ * @inheritdoc
+ *
+ * Ending line
+ *
+ * @param arg1 Start1 @inheritdoc End1
+ * @param arg2 Start2 @inheritdoc End2
+ * @param arg3 Start3 ShouldWarn @inheritdoc End3
+ * @tparam T StartT @inheritdoc EndT
+ * @tparam ShouldWarn StartSW @inheritdoc EndSW
+ * @throws SomeException StartEx @inheritdoc EndEx
+ * @throws SomeOtherException StartSOE Should Warn @inheritdoc EndSOE
+ * @return StartRet @inheritdoc EndRet
+ * @see StartSee @inheritdoc EndSee
+ * @note StartNote @inheritdoc EndNote
+ * @example StartExample @inheritdoc EndExample
+ * @author StartAuthor @inheritdoc EndAuthor
+ * @version StartVer @inheritdoc EndVer
+ * @since StartSince @inheritdoc EndSince
+ * @todo StartTodo @inheritdoc And dad! EndTodo
+ */
+ override def function[T](arg1: T, arg2: String): Double = 1.0d
+} \ No newline at end of file
diff --git a/test/scaladoc/resources/explicit-inheritance-usecase.scala b/test/scaladoc/resources/explicit-inheritance-usecase.scala
new file mode 100644
index 0000000000..e10cec437a
--- /dev/null
+++ b/test/scaladoc/resources/explicit-inheritance-usecase.scala
@@ -0,0 +1,47 @@
+// This tests the implicit comment inheritance capabilities of scaladoc for usecases (no $super, no @inheritdoc)
+/** Testing use case inheritance */
+class UseCaseInheritDoc {
+ /**
+ * The base comment. And another sentence...
+ *
+ * @param arg1 The T term comment
+ * @param arg2 The string comment
+ * @tparam T the type of the first argument
+ * @throws SomeException if the function is not called with correct parameters
+ * @return The return comment
+ * @see The Manual
+ * @note Be careful!
+ * @example function[Int](3, "something")
+ * @author a Scala developer
+ * @version 0.0.2
+ * @since 0.0.1
+ * @todo Call mom.
+ *
+ * @usecase def function[T](arg1: T, arg2: String): Double
+ *
+ * Starting line
+ *
+ * @inheritdoc
+ * @inheritdoc
+ *
+ * Ending line
+ *
+ * @param arg1 Start1 @inheritdoc End1
+ * @param arg2 Start2 @inheritdoc End2
+ * @param arg3 Start3 ShouldWarn @inheritdoc End3
+ * @tparam T StartT @inheritdoc EndT
+ * @tparam ShouldWarn StartSW @inheritdoc EndSW
+ * @throws SomeException StartEx @inheritdoc EndEx
+ * @throws SomeOtherException StartSOE Should Warn @inheritdoc EndSOE
+ * @return StartRet @inheritdoc EndRet
+ * @see StartSee @inheritdoc EndSee
+ * @note StartNote @inheritdoc EndNote
+ * @example StartExample @inheritdoc EndExample
+ * @author StartAuthor @inheritdoc EndAuthor
+ * @version StartVer @inheritdoc EndVer
+ * @since StartSince @inheritdoc EndSince
+ * @todo StartTodo @inheritdoc And dad! EndTodo
+ */
+ def function[T](implicit arg1: T, arg2: String): Double = 0.0d
+}
+
diff --git a/test/scaladoc/resources/implicit-inheritance-override.scala b/test/scaladoc/resources/implicit-inheritance-override.scala
index 85b8e8d543..5d692f59ad 100644
--- a/test/scaladoc/resources/implicit-inheritance-override.scala
+++ b/test/scaladoc/resources/implicit-inheritance-override.scala
@@ -2,12 +2,12 @@
class Base {
/**
* The base comment. And another sentence...
- *
- * @param arg1 The T term comment
- * @param arg2 The string comment
+ *
+ * @param arg1 The T term comment
+ * @param arg2 The string comment
* @tparam T the type of the first argument
* @return The return comment
- */
+ */
def function[T](arg1: T, arg2: String): Double = 0.0d
}
diff --git a/test/scaladoc/resources/inheritdoc-corner-cases.scala b/test/scaladoc/resources/inheritdoc-corner-cases.scala
new file mode 100644
index 0000000000..8cd995e605
--- /dev/null
+++ b/test/scaladoc/resources/inheritdoc-corner-cases.scala
@@ -0,0 +1,78 @@
+// TEST1: Inherit from multiple classes
+trait A {
+ /**
+ * Hello 1 comment
+ */
+ def hello1 = 0
+}
+
+trait B {
+ /**
+ * Hello 2 comment
+ */
+ def hello2 = 1
+}
+
+trait C extends B
+
+class D extends A with C {
+ /**
+ * Inherited: @inheritdoc
+ */
+ override def hello1 = super.hello2
+
+ /**
+ * Inherited: @inheritdoc
+ */
+ override def hello2 = super.hello1
+}
+
+// TEST2: Invalid inherit: no parents
+trait E {
+ /**
+ * @inheritdoc
+ */
+ def whereDidThisComeFrom
+}
+
+// TEST3: Invalid inherit, but other parents present
+trait F extends E {
+ /**
+ * @inheritdoc
+ */
+ def howAboutThis
+}
+
+
+// TEST4: Inherit from something that inherits: inherit should propagate
+trait G extends D {
+ /**
+ * @inheritdoc
+ */
+ override def hello1 = 13
+
+ /**
+ * @inheritdoc
+ */
+ override def hello2 = 14
+}
+
+// TEST5: Inherit missing parameters
+trait H extends G {
+ /**
+ * Missing params
+ * @throws HelloException @inheritdoc
+ * @todo @inheritdoc
+ */
+ override def hello1 = 15
+}
+
+// TEST6: Inherit from something that inherits in the usecase
+trait I extends G {
+ /**
+ * @inheritdoc
+ * @usecase def hello1(i: Int)
+ * @inheritdoc
+ */
+ override def hello1 = 13
+} \ No newline at end of file
diff --git a/test/scaladoc/scala/html/HtmlFactoryTest.scala b/test/scaladoc/scala/html/HtmlFactoryTest.scala
index 37aa302ac7..ead7c9e99c 100644
--- a/test/scaladoc/scala/html/HtmlFactoryTest.scala
+++ b/test/scaladoc/scala/html/HtmlFactoryTest.scala
@@ -21,9 +21,9 @@ object XMLUtil {
}
object Test extends Properties("HtmlFactory") {
-
- final val RESOURCES = "test/scaladoc/resources/"
-
+
+ final val RESOURCES = "test/scaladoc/resources/"
+
import scala.tools.nsc.doc.{DocFactory, Settings}
import scala.tools.nsc.doc.model.IndexModelFactory
import scala.tools.nsc.doc.html.HtmlFactory
@@ -87,7 +87,7 @@ object Test extends Properties("HtmlFactory") {
/**
* This tests the text without the markup - ex:
- *
+ *
* <h4 class="signature">
* <span class="modifier_kind">
* <span class="modifier">implicit</span>
@@ -97,24 +97,24 @@ object Test extends Properties("HtmlFactory") {
* <span class="name">test</span><span class="params">()</span><span class="result">: <span name="scala.Int" class="extype">Int</span></span>
* </span>
* </h4>
- *
+ *
* becomes:
- *
+ *
* implicit def test(): Int
- *
+ *
* and is required to contain the text in the given checks
- *
+ *
* NOTE: Comparison is done ignoring all whitespace
*/
def checkText(scalaFile: String, debug: Boolean = true)(checks: (Option[String], String, Boolean)*): Boolean = {
- val htmlFile = scalaFile.stripSuffix(".scala") + ".html"
+ val htmlFile = scalaFile.stripSuffix(".scala") + ".html"
val htmlAllFiles = createTemplates(scalaFile)
var result = true
-
+
for ((fileHint, check, expected) <- checks) {
// resolve the file to be checked
val fileName = fileHint match {
- case Some(file) =>
+ case Some(file) =>
if (file endsWith ".html")
file
else
@@ -122,20 +122,27 @@ object Test extends Properties("HtmlFactory") {
case None =>
htmlFile
}
- val fileText = htmlAllFiles(fileName).text.replace('→',' ').replaceAll("\\s+","")
- val checkText = check.replace('→',' ').replaceAll("\\s+","")
+ val fileTextPretty = htmlAllFiles(fileName).text.replace('→',' ').replaceAll("\\s+"," ")
+ val fileText = fileTextPretty.replaceAll(" ", "")
+
+ val checkTextPretty = check.replace('→',' ').replaceAll("\\s+"," ")
+ val checkText = checkTextPretty.replaceAll(" ", "")
+
val checkValue = fileText.contains(checkText) == expected
if (debug && (!checkValue)) {
- Console.err.println("Check failed: ")
- Console.err.println("HTML: " + fileText)
- Console.err.println("Check: " + checkText)
+ Console.err.println("")
+ Console.err.println("HTML Check failed for resource file " + scalaFile + ":")
+ Console.err.println("Could not match: \n" + checkTextPretty)
+ Console.err.println("In the extracted HTML text: \n" + fileTextPretty)
+ Console.err.println("NOTE: The whitespaces are eliminated before matching!")
+ Console.err.println("")
}
- result &&= checkValue
+ result &&= checkValue
}
-
+
result
}
-
+
def shortComments(root: scala.xml.Node) =
XMLUtil.stripGroup(root).descendant.flatMap {
@@ -284,7 +291,7 @@ object Test extends Properties("HtmlFactory") {
case _ => false
}
}
-
+
property("Trac #4420 - no whitespace at end of line") = {
val files = createTemplates("Trac4420.scala")
@@ -432,47 +439,46 @@ object Test extends Properties("HtmlFactory") {
createTemplate("SI_4898.scala")
true
}
-
+
property("Use cases should override their original members") =
checkText("SI_5054_q1.scala")(
(None,"""def test(): Int""", true),
(None,"""def test(implicit lost: Int): Int""", false)
)
- property("Use cases should keep their flags - final should not be lost") =
+ property("Use cases should keep their flags - final should not be lost") =
checkText("SI_5054_q2.scala")((None, """final def test(): Int""", true))
-
- property("Use cases should keep their flags - implicit should not be lost") =
+
+ property("Use cases should keep their flags - implicit should not be lost") =
checkText("SI_5054_q3.scala")((None, """implicit def test(): Int""", true))
-
- property("Use cases should keep their flags - real abstract should not be lost") =
+
+ property("Use cases should keep their flags - real abstract should not be lost") =
checkText("SI_5054_q4.scala")((None, """abstract def test(): Int""", true))
- property("Use cases should keep their flags - traits should not be affected") =
+ property("Use cases should keep their flags - traits should not be affected") =
checkText("SI_5054_q5.scala")((None, """def test(): Int""", true))
- property("Use cases should keep their flags - traits should not be affected") =
+ property("Use cases should keep their flags - traits should not be affected") =
checkText("SI_5054_q6.scala")((None, """abstract def test(): Int""", true))
-
- property("Use case individual signature test") =
+
+ property("Use case individual signature test") =
checkText("SI_5054_q7.scala")(
(None, """abstract def test2(explicit: Int): Int [use case] This takes the explicit value passed.""", true),
(None, """abstract def test1(): Int [use case] This takes the implicit value in scope.""", true)
)
- property("Display correct \"Definition classes\"") =
- checkText("SI_5287.scala")(
+ property("Display correct \"Definition classes\"") =
+ checkText("SI_5287.scala")(
(None,
"""def method(): Int
[use case] The usecase explanation
[use case] The usecase explanation
Definition Classes SI_5287 SI_5287_B SI_5287_A""", true)
- ) // the explanation appears twice, as small comment and full comment
-
-
- property("Correct comment inheritance for overriding") =
+ ) // the explanation appears twice, as small comment and full comment
+
+ property("Correct comment inheritance for overriding") =
checkText("implicit-inheritance-override.scala")(
- (Some("Base"),
+ (Some("Base"),
"""def function[T](arg1: T, arg2: String): Double
The base comment.
The base comment. And another sentence...
@@ -481,7 +487,7 @@ object Test extends Properties("HtmlFactory") {
arg2 The string comment
returns The return comment
""", true),
- (Some("DerivedA"),
+ (Some("DerivedA"),
"""def function[T](arg1: T, arg2: String): Double
Overriding the comment, the params and returns comments should stay the same.
Overriding the comment, the params and returns comments should stay the same.
@@ -490,21 +496,21 @@ object Test extends Properties("HtmlFactory") {
arg2 The string comment
returns The return comment
""", true),
- (Some("DerivedB"),
+ (Some("DerivedB"),
"""def function[T](arg1: T, arg2: String): Double
T the type of the first argument
arg1 The overridden T term comment
arg2 The overridden string comment
returns The return comment
""", true),
- (Some("DerivedC"),
+ (Some("DerivedC"),
"""def function[T](arg1: T, arg2: String): Double
T the type of the first argument
arg1 The T term comment
arg2 The string comment
returns The overridden return comment
""", true),
- (Some("DerivedD"),
+ (Some("DerivedD"),
"""def function[T](arg1: T, arg2: String): Double
T The overriden type parameter comment
arg1 The T term comment
@@ -512,11 +518,11 @@ object Test extends Properties("HtmlFactory") {
returns The return comment
""", true)
)
-
+
for (useCaseFile <- List("UseCaseInheritance", "UseCaseOverrideInheritance")) {
- property("Correct comment inheritance for usecases") =
+ property("Correct comment inheritance for usecases") =
checkText("implicit-inheritance-usecase.scala")(
- (Some(useCaseFile),
+ (Some(useCaseFile),
"""def missing_arg[T](arg1: T): Double
[use case]
[use case]
@@ -524,7 +530,7 @@ object Test extends Properties("HtmlFactory") {
arg1 The T term comment
returns The return comment
""", true),
- (Some(useCaseFile),
+ (Some(useCaseFile),
"""def missing_targ(arg1: Int, arg2: String): Double
[use case]
[use case]
@@ -532,7 +538,7 @@ object Test extends Properties("HtmlFactory") {
arg2 The string comment
returns The return comment
""", true),
- (Some(useCaseFile),
+ (Some(useCaseFile),
"""def overridden_arg1[T](implicit arg1: T, arg2: String): Double
[use case]
[use case]
@@ -541,7 +547,7 @@ object Test extends Properties("HtmlFactory") {
arg2 The string comment
returns The return comment
""", true),
- (Some(useCaseFile),
+ (Some(useCaseFile),
"""def overridden_targ[T](implicit arg1: T, arg2: String): Double
[use case]
[use case]
@@ -550,7 +556,7 @@ object Test extends Properties("HtmlFactory") {
arg2 The string comment
returns The return comment
""", true),
- (Some(useCaseFile),
+ (Some(useCaseFile),
"""def overridden_return[T](implicit arg1: T, arg2: String): Double
[use case]
[use case]
@@ -559,7 +565,7 @@ object Test extends Properties("HtmlFactory") {
arg2 The string comment
returns The overridden return comment
""", true),
- (Some(useCaseFile),
+ (Some(useCaseFile),
"""def added_arg[T](implicit arg1: T, arg2: String, arg3: Float): Double
[use case]
[use case]
@@ -569,7 +575,7 @@ object Test extends Properties("HtmlFactory") {
arg3 The added float comment
returns The return comment
""", true),
- (Some(useCaseFile),
+ (Some(useCaseFile),
"""def overridden_comment[T](implicit arg1: T, arg2: String): Double
[use case] The overridden comment.
[use case] The overridden comment.
@@ -578,9 +584,93 @@ object Test extends Properties("HtmlFactory") {
arg2 The string comment
returns The return comment
""", true)
- )
- }
-
+ )
+ }
+
+ property("Correct explicit inheritance for override") =
+ checkText("explicit-inheritance-override.scala")(
+ (Some("InheritDocDerived"),
+ """def function[T](arg1: T, arg2: String): Double
+ Starting line
+ Starting line
+ The base comment. And another sentence...
+ The base comment. And another sentence...
+ Ending line
+ T StartT the type of the first argument EndT
+ arg1 Start1 The T term comment End1
+ arg2 Start2 The string comment End2
+ returns StartRet The return comment EndRet
+ Definition Classes InheritDocDerived → InheritDocBase
+ Example: StartExample function[Int](3, "something") EndExample
+ Version StartVer 0.0.2 EndVer
+ Since StartSince 0.0.1 EndSince
+ Exceptions thrown
+ SomeException StartEx if the function is not called with correct parameters EndEx
+ SomeOtherException StartSOE Should Warn <invalid inheritdoc annotation> EndSOE
+ To do StartTodo Call mom. And dad! EndTodo
+ Note StartNote Be careful! EndNote
+ See also StartSee The Manual EndSee
+ """, true))
+
+ property("Correct explicit inheritance for usecase") =
+ checkText("explicit-inheritance-usecase.scala")(
+ (Some("UseCaseInheritDoc"),
+ """def function[T](arg1: T, arg2: String): Double
+ [use case] Starting line
+ [use case] Starting line
+ The base comment. And another sentence...
+ The base comment. And another sentence...
+ Ending line
+ T StartT the type of the first argument EndT
+ arg1 Start1 The T term comment End1
+ arg2 Start2 The string comment End2
+ returns StartRet The return comment EndRet
+ Example: StartExample function[Int](3,"something") EndExample
+ Version StartVer 0.0.2 EndVer
+ Since StartSince 0.0.1 EndSince
+ Exceptions thrown
+ SomeException StartEx if the function is not called with correct parameters EndEx
+ SomeOtherException StartSOE Should Warn <invalid inheritdoc annotation> EndSOE
+ To do StartTodo Call mom. And dad! EndTodo
+ Note StartNote Be careful! EndNote
+ See also StartSee The Manual EndSee
+ """, true))
+
+ property("Correct explicit inheritance in corner cases") =
+ checkText("inheritdoc-corner-cases.scala")(
+ (Some("D"),
+ """def hello1: Int
+ Inherited: Hello 1 comment
+ Inherited: Hello 1 comment
+ Definition Classes D → A
+ """, true),
+ (Some("D"),
+ """def hello2: Int
+ Inherited: Hello 2 comment
+ Inherited: Hello 2 comment
+ Definition Classes D → B
+ """, true),
+ (Some("G"),
+ """def hello1: Int
+ Inherited: Hello 1 comment
+ Inherited: Hello 1 comment
+ Definition Classes G → D → A
+ """, true),
+ (Some("G"),
+ """def hello2: Int
+ Inherited: Hello 2 comment
+ Inherited: Hello 2 comment
+ Definition Classes G → D → B
+ """, true),
+ (Some("I"),
+ """def hello1(i: Int): Unit
+ [use case] Inherited: Hello 1 comment
+ [use case] Inherited: Hello 1 comment
+ Definition Classes I → G → D → A
+ """, true)
+ // traits E, F and H shouldn't crash scaladoc but we don't need to check the output
+ )
+
{
val files = createTemplates("basic.scala")
//println(files)