Skip to content

Commit 4ed74a0

Browse files
committed
Add docstring support for types, vals, vars and defs
1 parent b386b4b commit 4ed74a0

File tree

2 files changed

+150
-15
lines changed

2 files changed

+150
-15
lines changed

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

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1720,13 +1720,13 @@ object Parsers {
17201720
*/
17211721
def defOrDcl(start: Int, mods: Modifiers): Tree = in.token match {
17221722
case VAL =>
1723-
patDefOrDcl(posMods(start, mods))
1723+
patDefOrDcl(posMods(start, mods), in.getDocString(start))
17241724
case VAR =>
1725-
patDefOrDcl(posMods(start, addFlag(mods, Mutable)))
1725+
patDefOrDcl(posMods(start, addFlag(mods, Mutable)), in.getDocString(start))
17261726
case DEF =>
1727-
defDefOrDcl(posMods(start, mods))
1727+
defDefOrDcl(posMods(start, mods), in.getDocString(start))
17281728
case TYPE =>
1729-
typeDefOrDcl(posMods(start, mods))
1729+
typeDefOrDcl(posMods(start, mods), in.getDocString(start))
17301730
case _ =>
17311731
tmplDef(start, mods)
17321732
}
@@ -1736,7 +1736,7 @@ object Parsers {
17361736
* ValDcl ::= Id {`,' Id} `:' Type
17371737
* VarDcl ::= Id {`,' Id} `:' Type
17381738
*/
1739-
def patDefOrDcl(mods: Modifiers): Tree = {
1739+
def patDefOrDcl(mods: Modifiers, docstring: Option[String] = None): Tree = {
17401740
val lhs = commaSeparated(pattern2)
17411741
val tpt = typedOpt()
17421742
val rhs =
@@ -1750,8 +1750,10 @@ object Parsers {
17501750
}
17511751
} else EmptyTree
17521752
lhs match {
1753-
case (id @ Ident(name: TermName)) :: Nil => cpy.ValDef(id)(name, tpt, rhs).withMods(mods)
1754-
case _ => PatDef(mods, lhs, tpt, rhs)
1753+
case (id @ Ident(name: TermName)) :: Nil =>
1754+
cpy.ValDef(id)(name, tpt, rhs).withMods(mods).withComment(docstring)
1755+
case _ =>
1756+
PatDef(mods, lhs, tpt, rhs)
17551757
}
17561758
}
17571759

@@ -1760,7 +1762,7 @@ object Parsers {
17601762
* DefDcl ::= DefSig `:' Type
17611763
* DefSig ::= id [DefTypeParamClause] ParamClauses
17621764
*/
1763-
def defDefOrDcl(mods: Modifiers): Tree = atPos(tokenRange) {
1765+
def defDefOrDcl(mods: Modifiers, docstring: Option[String] = None): Tree = atPos(tokenRange) {
17641766
def scala2ProcedureSyntax =
17651767
testScala2Mode("Procedure syntax no longer supported; `: Unit =' should be inserted here")
17661768
if (in.token == THIS) {
@@ -1794,7 +1796,7 @@ object Parsers {
17941796
accept(EQUALS)
17951797
expr()
17961798
}
1797-
DefDef(name, tparams, vparamss, tpt, rhs).withMods(mods1)
1799+
DefDef(name, tparams, vparamss, tpt, rhs).withMods(mods1).withComment(docstring)
17981800
}
17991801
}
18001802

@@ -1828,15 +1830,15 @@ object Parsers {
18281830
/** TypeDef ::= type Id [TypeParamClause] `=' Type
18291831
* TypeDcl ::= type Id [TypeParamClause] TypeBounds
18301832
*/
1831-
def typeDefOrDcl(mods: Modifiers): Tree = {
1833+
def typeDefOrDcl(mods: Modifiers, docstring: Option[String] = None): Tree = {
18321834
newLinesOpt()
18331835
atPos(tokenRange) {
18341836
val name = ident().toTypeName
18351837
val tparams = typeParamClauseOpt(ParamOwner.Type)
18361838
in.token match {
18371839
case EQUALS =>
18381840
in.nextToken()
1839-
TypeDef(name, tparams, typ()).withMods(mods)
1841+
TypeDef(name, tparams, typ()).withMods(mods).withComment(docstring)
18401842
case SUPERTYPE | SUBTYPE | SEMI | NEWLINE | NEWLINES | COMMA | RBRACE | EOF =>
18411843
TypeDef(name, tparams, typeBounds()).withMods(mods)
18421844
case _ =>

test/test/DottyDocTests.scala

Lines changed: 137 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,22 @@ trait DottyDocTest extends DottyTest { self =>
4242
assert(false, s"""No docstring found, expected: "$expected"""")
4343
}
4444

45-
def run(): Unit = {
45+
def run(): Unit = try {
4646
val c = compiler(assertion)
4747
c.rootContext(ctx)
4848
c.newRun.compile(source)
4949
println(s"${self.getClass.getSimpleName.split("\\$").last} passed")
50+
} catch { case e: Throwable =>
51+
Console.err.println(s"${self.getClass.getSimpleName.split("\\$").last} failed")
52+
throw e
5053
}
5154
}
5255

5356
/** Add tests to the `tests` sequence */
5457
object DottyDocTests extends DottyTest {
5558
private[this] val tests = Seq(
5659
NoComment,
60+
5761
SingleClassInPackage,
5862
MultipleOpenedOnSingleClassInPackage,
5963
MultipleClassesInPackage,
@@ -67,13 +71,18 @@ object DottyDocTests extends DottyTest {
6771
ObjectsNestedClass,
6872
PackageObject,
6973
MultipleDocStringsBeforeEntity,
70-
MultipleDocStringsBeforeAndAfter
74+
MultipleDocStringsBeforeAndAfter,
75+
76+
ValuesWithDocString,
77+
VarsWithDocString,
78+
DefsWithDocString,
79+
TypesWithDocString
7180
)
7281

7382
def main(args: Array[String]): Unit = {
74-
println("------------ Testing DottyDoc ------------")
83+
println(s"-------------- Testing DottyDoc (${tests.length} tests) --------------")
7584
tests.foreach(_.run)
76-
println("--------- DottyDoc tests passed! ----------")
85+
println("--------------- DottyDoc tests passed! -------------------")
7786
}
7887
}
7988

@@ -371,3 +380,127 @@ case object MultipleDocStringsBeforeAndAfter extends DottyDocTest {
371380
}
372381

373382
}
383+
384+
case object ValuesWithDocString extends DottyDocTest {
385+
override val source =
386+
"""
387+
|object Object {
388+
| /** val1 */
389+
| val val1 = 1
390+
|
391+
| /** val2 */
392+
| val val2: Int = 2
393+
| /** bogus docstring */
394+
|
395+
| /** bogus docstring */
396+
| /** val3 */
397+
| val val3: List[Int] = 1 :: 2 :: 3 :: Nil
398+
|}
399+
""".stripMargin
400+
401+
import dotty.tools.dotc.ast.untpd._
402+
override def assertion = {
403+
case PackageDef(_, Seq(o: ModuleDef)) =>
404+
o.impl.body match {
405+
case (v1: MemberDef) :: (v2: MemberDef) :: (v3: MemberDef) :: Nil => {
406+
checkDocString(v1.rawComment, "/** val1 */")
407+
checkDocString(v2.rawComment, "/** val2 */")
408+
checkDocString(v3.rawComment, "/** val3 */")
409+
}
410+
case _ => assert(false, "Incorrect structure inside object")
411+
}
412+
}
413+
}
414+
415+
case object VarsWithDocString extends DottyDocTest {
416+
override val source =
417+
"""
418+
|object Object {
419+
| /** var1 */
420+
| var var1 = 1
421+
|
422+
| /** var2 */
423+
| var var2: Int = 2
424+
| /** bogus docstring */
425+
|
426+
| /** bogus docstring */
427+
| /** var3 */
428+
| var var3: List[Int] = 1 :: 2 :: 3 :: Nil
429+
|}
430+
""".stripMargin
431+
432+
import dotty.tools.dotc.ast.untpd._
433+
override def assertion = {
434+
case PackageDef(_, Seq(o: ModuleDef)) =>
435+
o.impl.body match {
436+
case (v1: MemberDef) :: (v2: MemberDef) :: (v3: MemberDef) :: Nil => {
437+
checkDocString(v1.rawComment, "/** var1 */")
438+
checkDocString(v2.rawComment, "/** var2 */")
439+
checkDocString(v3.rawComment, "/** var3 */")
440+
}
441+
case _ => assert(false, "Incorrect structure inside object")
442+
}
443+
}
444+
}
445+
446+
case object DefsWithDocString extends DottyDocTest {
447+
override val source =
448+
"""
449+
|object Object {
450+
| /** def1 */
451+
| def def1 = 1
452+
|
453+
| /** def2 */
454+
| def def2: Int = 2
455+
| /** bogus docstring */
456+
|
457+
| /** bogus docstring */
458+
| /** def3 */
459+
| def def3: List[Int] = 1 :: 2 :: 3 :: Nil
460+
|}
461+
""".stripMargin
462+
463+
import dotty.tools.dotc.ast.untpd._
464+
override def assertion = {
465+
case PackageDef(_, Seq(o: ModuleDef)) =>
466+
o.impl.body match {
467+
case (v1: MemberDef) :: (v2: MemberDef) :: (v3: MemberDef) :: Nil => {
468+
checkDocString(v1.rawComment, "/** def1 */")
469+
checkDocString(v2.rawComment, "/** def2 */")
470+
checkDocString(v3.rawComment, "/** def3 */")
471+
}
472+
case _ => assert(false, "Incorrect structure inside object")
473+
}
474+
}
475+
}
476+
477+
case object TypesWithDocString extends DottyDocTest {
478+
override val source =
479+
"""
480+
|object Object {
481+
| /** type1 */
482+
| type T1 = Int
483+
|
484+
| /** type2 */
485+
| type T2 = String
486+
| /** bogus docstring */
487+
|
488+
| /** bogus docstring */
489+
| /** type3 */
490+
| type T3 = T2
491+
|}
492+
""".stripMargin
493+
494+
import dotty.tools.dotc.ast.untpd._
495+
override def assertion = {
496+
case PackageDef(_, Seq(o: ModuleDef)) =>
497+
o.impl.body match {
498+
case (v1: MemberDef) :: (v2: MemberDef) :: (v3: MemberDef) :: Nil => {
499+
checkDocString(v1.rawComment, "/** type1 */")
500+
checkDocString(v2.rawComment, "/** type2 */")
501+
checkDocString(v3.rawComment, "/** type3 */")
502+
}
503+
case _ => assert(false, "Incorrect structure inside object")
504+
}
505+
}
506+
}

0 commit comments

Comments
 (0)