Skip to content

Commit 1ed31b8

Browse files
committed
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 ```
1 parent f7b6248 commit 1ed31b8

File tree

3 files changed

+71
-11
lines changed

3 files changed

+71
-11
lines changed

src/dotty/tools/dotc/parsing/Parsers.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1850,7 +1850,7 @@ object Parsers {
18501850
* | [`case'] `object' ObjectDef
18511851
*/
18521852
def tmplDef(start: Int, mods: Modifiers): Tree = {
1853-
val docstring = in.getDocString()
1853+
val docstring = in.getDocString(start)
18541854
in.token match {
18551855
case TRAIT =>
18561856
classDef(posMods(start, addFlag(mods, Trait)), docstring)
@@ -2131,7 +2131,7 @@ object Parsers {
21312131
if (in.token == PACKAGE) {
21322132
in.nextToken()
21332133
if (in.token == OBJECT) {
2134-
val docstring = in.getDocString()
2134+
val docstring = in.getDocString(start)
21352135
ts += objectDef(atPos(start, in.skipToken()) { Modifiers(Package) }, docstring)
21362136
if (in.token != EOF) {
21372137
acceptStatSep()

src/dotty/tools/dotc/parsing/Scanners.scala

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -185,22 +185,33 @@ object Scanners {
185185
/** The currently closest docstring, replaced every time a new docstring is
186186
* encountered
187187
*/
188-
var closestDocString: List[mutable.Queue[Comment]] = mutable.Queue.empty[Comment] :: Nil
188+
var closestDocString: List[List[Comment]] = List(List())
189189

190190
/** Adds level of nesting to docstrings */
191191
def enterBlock(): Unit =
192-
closestDocString = mutable.Queue.empty[Comment] :: closestDocString
192+
closestDocString = Nil ::: closestDocString
193193

194194
/** Removes level of nesting for docstrings */
195195
def exitBlock(): Unit = closestDocString = closestDocString match {
196-
case x :: Nil => mutable.Queue.empty[Comment] :: Nil
196+
case x :: xs => List(List())
197197
case _ => closestDocString.tail
198198
}
199199

200-
/** Returns `closestDocString`'s raw string and sets it to `None` */
201-
def getDocString(): Option[String] = closestDocString match {
202-
case x :: _ if !x.isEmpty => Some(x.dequeue.chrs)
203-
case _ => None
200+
/** Returns the closest docstring preceding the position supplied */
201+
def getDocString(pos: Int): Option[String] = {
202+
def closest(c: Comment, docstrings: List[Comment]): Comment = docstrings match {
203+
case x :: xs if (c.pos.end < x.pos.end && x.pos.end <= pos) => closest(x, xs)
204+
case Nil => c
205+
}
206+
207+
closestDocString match {
208+
case (list @ (x :: xs)) :: _ => {
209+
val c = closest(x, xs)
210+
closestDocString = list.dropWhile(_ != c).tail :: closestDocString.tail
211+
Some(c.chrs)
212+
}
213+
case _ => None
214+
}
204215
}
205216

206217
/** A buffer for comments */
@@ -580,7 +591,7 @@ object Scanners {
580591
val comment = Comment(pos, flushBuf(commentBuf))
581592

582593
if (comment.isDocComment)
583-
closestDocString.head.enqueue(comment)
594+
closestDocString = (closestDocString.head :+ comment) :: closestDocString.tail
584595

585596
if (keepComments)
586597
revComments = comment :: revComments

test/test/DottyDocTests.scala

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ trait DottyDocTest extends DottyTest { self =>
5353
/** Add tests to the `tests` sequence */
5454
object DottyDocTests extends DottyTest {
5555
private[this] val tests = Seq(
56+
NoComment,
5657
SingleClassInPackage,
5758
MultipleOpenedOnSingleClassInPackage,
5859
MultipleClassesInPackage,
@@ -64,7 +65,9 @@ object DottyDocTests extends DottyTest {
6465
NestedClassThenOuter,
6566
Objects,
6667
ObjectsNestedClass,
67-
PackageObject
68+
PackageObject,
69+
MultipleDocStringsBeforeEntity,
70+
MultipleDocStringsBeforeAndAfter
6871
)
6972

7073
def main(args: Array[String]): Unit = {
@@ -74,6 +77,16 @@ object DottyDocTests extends DottyTest {
7477
}
7578
}
7679

80+
case object NoComment extends DottyDocTest {
81+
override val source = "class Class"
82+
83+
import dotty.tools.dotc.ast.untpd._
84+
override def assertion = {
85+
case PackageDef(_, Seq(c: TypeDef)) =>
86+
assert(c.rawComment == None, "Should not have a comment, mainly used for exhaustive tests")
87+
}
88+
}
89+
7790
case object SingleClassInPackage extends DottyDocTest {
7891
override val source =
7992
"""
@@ -322,3 +335,39 @@ case object PackageObject extends DottyDocTest {
322335
}
323336
}
324337
}
338+
339+
case object MultipleDocStringsBeforeEntity extends DottyDocTest {
340+
override val source =
341+
"""
342+
|/** First comment */
343+
|/** Second comment */
344+
|/** Real comment */
345+
|class Class
346+
""".stripMargin
347+
348+
import dotty.tools.dotc.ast.untpd._
349+
override def assertion = {
350+
case PackageDef(_, Seq(c: TypeDef)) =>
351+
checkDocString(c.rawComment, "/** Real comment */")
352+
}
353+
}
354+
355+
case object MultipleDocStringsBeforeAndAfter extends DottyDocTest {
356+
override val source =
357+
"""
358+
|/** First comment */
359+
|/** Second comment */
360+
|/** Real comment */
361+
|class Class
362+
|/** Following comment 1 */
363+
|/** Following comment 2 */
364+
|/** Following comment 3 */
365+
""".stripMargin
366+
367+
import dotty.tools.dotc.ast.untpd._
368+
override def assertion = {
369+
case PackageDef(_, Seq(c: TypeDef)) =>
370+
checkDocString(c.rawComment, "/** Real comment */")
371+
}
372+
373+
}

0 commit comments

Comments
 (0)