aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Mulder <felix.mulder@gmail.com>2016-03-10 14:00:03 +0100
committerFelix Mulder <felix.mulder@gmail.com>2016-04-07 08:40:27 +0200
commitc66998bc56ba73b5b2cbbf6b10f4d5b83017db13 (patch)
treef48e25457df90810a6e5f764b2469e52e241e924
parent3aab803d513cec98dab8a58e92924d96662a7d7d (diff)
downloaddotty-c66998bc56ba73b5b2cbbf6b10f4d5b83017db13.tar.gz
dotty-c66998bc56ba73b5b2cbbf6b10f4d5b83017db13.tar.bz2
dotty-c66998bc56ba73b5b2cbbf6b10f4d5b83017db13.zip
Fix association of docstrings based on posisition
This commit fixes errors that would've occurred in this situation: ``` /** Docstring 1 */ <- this one would've been chosen /** Docstring 2 */ /** Docstring 3 */ class Class ``` And this situation: ``` /** Docstring 1 */ trait Trait /** Docstring 2 */ <- this one would've been chosen ```
-rw-r--r--src/dotty/tools/dotc/parsing/Parsers.scala4
-rw-r--r--src/dotty/tools/dotc/parsing/Scanners.scala27
-rw-r--r--test/test/DottyDocTests.scala51
3 files changed, 71 insertions, 11 deletions
diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala
index 3ea504657..053b28a64 100644
--- a/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -1889,7 +1889,7 @@ object Parsers {
* | [`case'] `object' ObjectDef
*/
def tmplDef(start: Int, mods: Modifiers): Tree = {
- val docstring = in.getDocString()
+ val docstring = in.getDocString(start)
in.token match {
case TRAIT =>
classDef(posMods(start, addFlag(mods, Trait)), docstring)
@@ -2170,7 +2170,7 @@ object Parsers {
if (in.token == PACKAGE) {
in.nextToken()
if (in.token == OBJECT) {
- val docstring = in.getDocString()
+ val docstring = in.getDocString(start)
ts += objectDef(atPos(start, in.skipToken()) { Modifiers(Package) }, docstring)
if (in.token != EOF) {
acceptStatSep()
diff --git a/src/dotty/tools/dotc/parsing/Scanners.scala b/src/dotty/tools/dotc/parsing/Scanners.scala
index 60042e5a6..9ad982e45 100644
--- a/src/dotty/tools/dotc/parsing/Scanners.scala
+++ b/src/dotty/tools/dotc/parsing/Scanners.scala
@@ -185,22 +185,33 @@ object Scanners {
/** The currently closest docstring, replaced every time a new docstring is
* encountered
*/
- var closestDocString: List[mutable.Queue[Comment]] = mutable.Queue.empty[Comment] :: Nil
+ var closestDocString: List[List[Comment]] = List(List())
/** Adds level of nesting to docstrings */
def enterBlock(): Unit =
- closestDocString = mutable.Queue.empty[Comment] :: closestDocString
+ closestDocString = Nil ::: closestDocString
/** Removes level of nesting for docstrings */
def exitBlock(): Unit = closestDocString = closestDocString match {
- case x :: Nil => mutable.Queue.empty[Comment] :: Nil
+ case x :: xs => List(List())
case _ => closestDocString.tail
}
- /** Returns `closestDocString`'s raw string and sets it to `None` */
- def getDocString(): Option[String] = closestDocString match {
- case x :: _ if !x.isEmpty => Some(x.dequeue.chrs)
- case _ => None
+ /** Returns the closest docstring preceding the position supplied */
+ def getDocString(pos: Int): Option[String] = {
+ def closest(c: Comment, docstrings: List[Comment]): Comment = docstrings match {
+ case x :: xs if (c.pos.end < x.pos.end && x.pos.end <= pos) => closest(x, xs)
+ case Nil => c
+ }
+
+ closestDocString match {
+ case (list @ (x :: xs)) :: _ => {
+ val c = closest(x, xs)
+ closestDocString = list.dropWhile(_ != c).tail :: closestDocString.tail
+ Some(c.chrs)
+ }
+ case _ => None
+ }
}
/** A buffer for comments */
@@ -580,7 +591,7 @@ object Scanners {
val comment = Comment(pos, flushBuf(commentBuf))
if (comment.isDocComment)
- closestDocString.head.enqueue(comment)
+ closestDocString = (closestDocString.head :+ comment) :: closestDocString.tail
if (keepComments)
revComments = comment :: revComments
diff --git a/test/test/DottyDocTests.scala b/test/test/DottyDocTests.scala
index 2a60e7e7d..5161f98b8 100644
--- a/test/test/DottyDocTests.scala
+++ b/test/test/DottyDocTests.scala
@@ -53,6 +53,7 @@ trait DottyDocTest extends DottyTest { self =>
/** Add tests to the `tests` sequence */
object DottyDocTests extends DottyTest {
private[this] val tests = Seq(
+ NoComment,
SingleClassInPackage,
MultipleOpenedOnSingleClassInPackage,
MultipleClassesInPackage,
@@ -64,7 +65,9 @@ object DottyDocTests extends DottyTest {
NestedClassThenOuter,
Objects,
ObjectsNestedClass,
- PackageObject
+ PackageObject,
+ MultipleDocStringsBeforeEntity,
+ MultipleDocStringsBeforeAndAfter
)
def main(args: Array[String]): Unit = {
@@ -74,6 +77,16 @@ object DottyDocTests extends DottyTest {
}
}
+case object NoComment extends DottyDocTest {
+ override val source = "class Class"
+
+ import dotty.tools.dotc.ast.untpd._
+ override def assertion = {
+ case PackageDef(_, Seq(c: TypeDef)) =>
+ assert(c.rawComment == None, "Should not have a comment, mainly used for exhaustive tests")
+ }
+}
+
case object SingleClassInPackage extends DottyDocTest {
override val source =
"""
@@ -322,3 +335,39 @@ case object PackageObject extends DottyDocTest {
}
}
}
+
+case object MultipleDocStringsBeforeEntity extends DottyDocTest {
+ override val source =
+ """
+ |/** First comment */
+ |/** Second comment */
+ |/** Real comment */
+ |class Class
+ """.stripMargin
+
+ import dotty.tools.dotc.ast.untpd._
+ override def assertion = {
+ case PackageDef(_, Seq(c: TypeDef)) =>
+ checkDocString(c.rawComment, "/** Real comment */")
+ }
+}
+
+case object MultipleDocStringsBeforeAndAfter extends DottyDocTest {
+ override val source =
+ """
+ |/** First comment */
+ |/** Second comment */
+ |/** Real comment */
+ |class Class
+ |/** Following comment 1 */
+ |/** Following comment 2 */
+ |/** Following comment 3 */
+ """.stripMargin
+
+ import dotty.tools.dotc.ast.untpd._
+ override def assertion = {
+ case PackageDef(_, Seq(c: TypeDef)) =>
+ checkDocString(c.rawComment, "/** Real comment */")
+ }
+
+}