Skip to content

Commit 8819843

Browse files
authored
Merge pull request #10506 from dotty-staging/resolve-doc-variables
Scala3doc: cook comments
2 parents 21aee87 + 9f27fde commit 8819843

File tree

10 files changed

+572
-39
lines changed

10 files changed

+572
-39
lines changed

compiler/src/dotty/tools/dotc/core/Comments.scala

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,13 @@ object Comments {
4444
* @param expanded If this comment has been expanded, it's expansion, otherwise `None`.
4545
* @param usecases The usecases for this comment.
4646
*/
47-
final case class Comment(span: Span, raw: String, expanded: Option[String], usecases: List[UseCase]) {
47+
final case class Comment(
48+
span: Span,
49+
raw: String,
50+
expanded: Option[String],
51+
usecases: List[UseCase],
52+
variables: Map[String, String],
53+
) {
4854

4955
/** Has this comment been cooked or expanded? */
5056
def isExpanded: Boolean = expanded.isDefined
@@ -65,7 +71,7 @@ object Comments {
6571
def expand(f: String => String)(using Context): Comment = {
6672
val expandedComment = f(raw)
6773
val useCases = Comment.parseUsecases(expandedComment, span)
68-
Comment(span, raw, Some(expandedComment), useCases)
74+
Comment(span, raw, Some(expandedComment), useCases, Map.empty)
6975
}
7076
}
7177

@@ -74,7 +80,7 @@ object Comments {
7480
def isDocComment(comment: String): Boolean = comment.startsWith("/**")
7581

7682
def apply(span: Span, raw: String): Comment =
77-
Comment(span, raw, None, Nil)
83+
Comment(span, raw, None, Nil, Map.empty)
7884

7985
private def parseUsecases(expandedComment: String, span: Span)(using Context): List[UseCase] =
8086
if (!isDocComment(expandedComment))

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,11 +190,7 @@ object Scanners {
190190
private def addComment(comment: Comment): Unit = {
191191
val lookahead = lookaheadReader()
192192
def nextPos: Int = (lookahead.getc(): @switch) match {
193-
case ' ' | '\t' => nextPos
194-
case CR | LF | FF =>
195-
// if we encounter line delimiting whitespace we don't count it, since
196-
// it seems not to affect positions in source
197-
nextPos - 1
193+
case ' ' | '\t' | CR | LF | FF => nextPos
198194
case _ => lookahead.charOffset - 1
199195
}
200196
docstringMap = docstringMap + (nextPos -> comment)
@@ -854,6 +850,9 @@ object Scanners {
854850

855851
if (comment.isDocComment)
856852
addComment(comment)
853+
else
854+
// "forward" doc comments over normal ones
855+
getDocComment(start).foreach(addComment)
857856
}
858857

859858
true

compiler/test/dotty/tools/dotc/parsing/DocstringTests.scala

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,37 @@ class DocstringTests extends DocstringTest {
474474
}
475475
}
476476

477+
478+
@Test def overNL = {
479+
val source =
480+
"""
481+
|/** Class1 */
482+
|
483+
|class Class1
484+
""".stripMargin
485+
486+
import dotty.tools.dotc.ast.untpd._
487+
checkFrontend(source) {
488+
case p @ PackageDef(_, Seq(c: TypeDef)) =>
489+
checkDocString(c.rawComment.map(_.raw), "/** Class1 */")
490+
}
491+
}
492+
493+
@Test def overComment = {
494+
val source =
495+
"""
496+
|/** Class1 */
497+
|// foo
498+
|class Class1
499+
""".stripMargin
500+
501+
import dotty.tools.dotc.ast.untpd._
502+
checkFrontend(source) {
503+
case p @ PackageDef(_, Seq(c: TypeDef)) =>
504+
checkDocString(c.rawComment.map(_.raw), "/** Class1 */")
505+
}
506+
}
507+
477508
@Test def withAnnotation = {
478509
val source =
479510
"""
@@ -489,6 +520,22 @@ class DocstringTests extends DocstringTest {
489520
}
490521
}
491522

523+
@Test def withAnnotationOverComment = {
524+
val source =
525+
"""
526+
|/** Class1 */
527+
|// foo
528+
|@SerialVersionUID(1)
529+
|class Class1
530+
""".stripMargin
531+
532+
import dotty.tools.dotc.ast.untpd._
533+
checkFrontend(source) {
534+
case p @ PackageDef(_, Seq(c: TypeDef)) =>
535+
checkDocString(c.rawComment.map(_.raw), "/** Class1 */")
536+
}
537+
}
538+
492539
@Test def nestedComment = {
493540
val source =
494541
"""

scala3doc-testcases/src/tests/tests.scala

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ package tests
1010
* This is an *important* _test_ class.
1111
* Important enough to get multiple sentences in its summary.
1212
*
13+
* Here is foo: $foo
14+
*
1315
* And `this` is inline code.
1416
*
1517
* And this is the **strong** __emphasis__ test.
@@ -56,17 +58,22 @@ package tests
5658
* @version 1.0.0
5759
* @result A class doesn't actually have a result.
5860
* @constructor A class has a constructor, and this one is important.
61+
*
62+
* @define foo Foo expanded.
5963
*/
6064
class A {
6165

62-
/** This is a method.
66+
/** This is my method.
6367
*
6468
* This is a link: [[AA]].
6569
*
6670
* This is another link: [[AA$]].
6771
*
6872
* And yet another: [[B]].
6973
*/
74+
final def myMethod(s: String): String = s
75+
76+
/** This is foo: $foo */
7077
def method(s: String): String = s
7178

7279
class AA
@@ -85,6 +92,8 @@ object A
8592
*
8693
* This is an ''important'' '''test''' __class__. And `this` is inline code.
8794
*
95+
* Here is foo: $foo
96+
*
8897
* While
8998
* {{{
9099
* this.is("a code block")
@@ -104,9 +113,12 @@ object A
104113
*
105114
* And this is his companion: [[tests.A$]].
106115
* @syntax wiki
116+
* @define foo Bar, actually.
107117
*/
108118
class B extends A {
109-
/** This is a method. */
119+
/** @inheritdoc */ override def method(s: String): String = s
120+
121+
/** This is my foo: $foo */
110122
def otherMethod(s: String): String = s
111123

112124
class BB
@@ -127,7 +139,8 @@ object B {
127139
val Z: Int = 0
128140
}
129141

130-
class C {
142+
/** This is foo: $foo */
143+
class C extends A {
131144
object CC
132145
class CC
133146
}
@@ -192,3 +205,10 @@ class Methods:
192205
def primitives(a: Int, b: Double, c: Short): Byte = 0
193206
def strings(a: String): String = ""
194207
def arrays(a: Array[String], b: Array[Int]): Array[Double] = ???
208+
209+
/** @define foo O's foo.
210+
*/
211+
object O:
212+
213+
/** This is foo: $foo */
214+
def method(s: String) = s

scala3doc/src/dotty/dokka/tasty/ScalaDocSupport.scala

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,24 @@ trait ScaladocSupport { self: TastyParser =>
1212
import qctx.reflect._
1313

1414
def parseComment(
15-
commentNode: Documentation,
15+
commentPre: Documentation,
1616
tree: Tree
1717
): dkkd.DocumentationNode = {
18+
val commentNode =
19+
if tree.symbol.isClassDef || tree.symbol.owner.isClassDef then
20+
import dotty.tools.dotc
21+
given ctx as dotc.core.Contexts.Context = qctx.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx
22+
23+
val sym = tree.symbol.asInstanceOf[dotc.core.Symbols.Symbol]
24+
25+
comments.CommentExpander.cookComment(sym)(using ctx)
26+
.get.asInstanceOf[Documentation]
27+
else
28+
commentPre
29+
30+
val commentString = commentNode.expanded getOrElse commentNode.raw
1831
val preparsed =
19-
comments.Preparser.preparse(comments.Cleaner.clean(commentNode.raw))
32+
comments.Preparser.preparse(comments.Cleaner.clean(commentString))
2033

2134
val commentSyntax =
2235
preparsed.syntax.headOption match {

0 commit comments

Comments
 (0)