Skip to content

Commit 6c8265c

Browse files
committed
Add docstring support for types, vals, vars and defs
1 parent c66998b commit 6c8265c

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
@@ -1752,13 +1752,13 @@ object Parsers {
17521752
*/
17531753
def defOrDcl(start: Int, mods: Modifiers): Tree = in.token match {
17541754
case VAL =>
1755-
patDefOrDcl(posMods(start, mods))
1755+
patDefOrDcl(posMods(start, mods), in.getDocString(start))
17561756
case VAR =>
1757-
patDefOrDcl(posMods(start, addFlag(mods, Mutable)))
1757+
patDefOrDcl(posMods(start, addFlag(mods, Mutable)), in.getDocString(start))
17581758
case DEF =>
1759-
defDefOrDcl(posMods(start, mods))
1759+
defDefOrDcl(posMods(start, mods), in.getDocString(start))
17601760
case TYPE =>
1761-
typeDefOrDcl(posMods(start, mods))
1761+
typeDefOrDcl(posMods(start, mods), in.getDocString(start))
17621762
case _ =>
17631763
tmplDef(start, mods)
17641764
}
@@ -1768,7 +1768,7 @@ object Parsers {
17681768
* ValDcl ::= Id {`,' Id} `:' Type
17691769
* VarDcl ::= Id {`,' Id} `:' Type
17701770
*/
1771-
def patDefOrDcl(mods: Modifiers): Tree = {
1771+
def patDefOrDcl(mods: Modifiers, docstring: Option[String] = None): Tree = {
17721772
val lhs = commaSeparated(pattern2)
17731773
val tpt = typedOpt()
17741774
val rhs =
@@ -1782,8 +1782,10 @@ object Parsers {
17821782
}
17831783
} else EmptyTree
17841784
lhs match {
1785-
case (id @ Ident(name: TermName)) :: Nil => cpy.ValDef(id)(name, tpt, rhs).withMods(mods)
1786-
case _ => PatDef(mods, lhs, tpt, rhs)
1785+
case (id @ Ident(name: TermName)) :: Nil =>
1786+
cpy.ValDef(id)(name, tpt, rhs).withMods(mods).withComment(docstring)
1787+
case _ =>
1788+
PatDef(mods, lhs, tpt, rhs)
17871789
}
17881790
}
17891791

@@ -1792,7 +1794,7 @@ object Parsers {
17921794
* DefDcl ::= DefSig `:' Type
17931795
* DefSig ::= id [DefTypeParamClause] ParamClauses
17941796
*/
1795-
def defDefOrDcl(mods: Modifiers): Tree = atPos(tokenRange) {
1797+
def defDefOrDcl(mods: Modifiers, docstring: Option[String] = None): Tree = atPos(tokenRange) {
17961798
def scala2ProcedureSyntax(resultTypeStr: String) = {
17971799
val toInsert =
17981800
if (in.token == LBRACE) s"$resultTypeStr ="
@@ -1833,7 +1835,7 @@ object Parsers {
18331835
accept(EQUALS)
18341836
expr()
18351837
}
1836-
DefDef(name, tparams, vparamss, tpt, rhs).withMods(mods1)
1838+
DefDef(name, tparams, vparamss, tpt, rhs).withMods(mods1).withComment(docstring)
18371839
}
18381840
}
18391841

@@ -1867,15 +1869,15 @@ object Parsers {
18671869
/** TypeDef ::= type Id [TypeParamClause] `=' Type
18681870
* TypeDcl ::= type Id [TypeParamClause] TypeBounds
18691871
*/
1870-
def typeDefOrDcl(mods: Modifiers): Tree = {
1872+
def typeDefOrDcl(mods: Modifiers, docstring: Option[String] = None): Tree = {
18711873
newLinesOpt()
18721874
atPos(tokenRange) {
18731875
val name = ident().toTypeName
18741876
val tparams = typeParamClauseOpt(ParamOwner.Type)
18751877
in.token match {
18761878
case EQUALS =>
18771879
in.nextToken()
1878-
TypeDef(name, tparams, typ()).withMods(mods)
1880+
TypeDef(name, tparams, typ()).withMods(mods).withComment(docstring)
18791881
case SUPERTYPE | SUBTYPE | SEMI | NEWLINE | NEWLINES | COMMA | RBRACE | EOF =>
18801882
TypeDef(name, tparams, typeBounds()).withMods(mods)
18811883
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)