Skip to content

Commit 6c2781e

Browse files
committed
Add tests for classes and traits
1 parent e9e12d3 commit 6c2781e

File tree

4 files changed

+163
-4
lines changed

4 files changed

+163
-4
lines changed

project/Build.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ object DottyBuild extends Build {
182182
}
183183
).
184184
settings(
185-
addCommandAlias("partest", ";test:package;package;test:runMain dotc.build;lockPartestFile;test:test;runPartestRunner") ++
185+
addCommandAlias("partest", ";test:package;package;test:runMain dotc.build;lockPartestFile;test:test;runPartestRunner;test:runMain test.DottyDocTests") ++
186186
addCommandAlias("partest-only", ";test:package;package;test:runMain dotc.build;lockPartestFile;test:test-only dotc.tests;runPartestRunner") ++
187187
addCommandAlias("partest-only-no-bootstrap", ";test:package;package; lockPartestFile;test:test-only dotc.tests;runPartestRunner")
188188
)

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1870,6 +1870,7 @@ object Parsers {
18701870
*/
18711871
def classDef(mods: Modifiers): TypeDef = atPos(tokenRange) {
18721872
val name = ident().toTypeName
1873+
val docstring = in.getDocString()
18731874
val constr = atPos(in.offset) {
18741875
val tparams = typeParamClauseOpt(ParamOwner.Class)
18751876
val cmods = constrModsOpt()
@@ -1881,7 +1882,7 @@ object Parsers {
18811882

18821883
TypeDef(name, templ)
18831884
.withMods(mods)
1884-
.withComment(in.getDocString())
1885+
.withComment(docstring)
18851886
}
18861887

18871888
/** ConstrMods ::= AccessModifier

test/test/DottyDocTests.scala

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
package test
2+
3+
import dotty.tools.dotc.Compiler
4+
import dotty.tools.dotc.core.Phases.Phase
5+
import dotty.tools.dotc.typer.FrontEnd
6+
import dotty.tools.dotc.core.Contexts.Context
7+
import dotty.tools.dotc.ast.tpd
8+
import dotty.tools.dotc.ast.Trees._
9+
10+
/** All tests need to extend this trait and define `source` and `assertion`
11+
*
12+
* Instances also need to be placed in the `DottyDocTests::tests` sequence to
13+
* be included in the run
14+
*/
15+
trait DottyDocTest extends DottyTest { self =>
16+
/** Source code in string format */
17+
def source: String
18+
19+
/** A test to run against the resulting code */
20+
def assertion: PartialFunction[Tree[Untyped], Unit]
21+
22+
private def defaultAssertion: PartialFunction[Tree[Untyped], Unit] = {
23+
case x => assert(false, "Couldn't match resulting AST to expected AST in: " + x.show)
24+
}
25+
26+
private def compiler(assertion: PartialFunction[Tree[Untyped], Unit]) = new Compiler {
27+
override def phases = {
28+
val checker = new Phase {
29+
def phaseName = "assertionChecker"
30+
override def run(implicit ctx: Context): Unit =
31+
(assertion orElse defaultAssertion)(ctx.compilationUnit.untpdTree)
32+
}
33+
34+
List(List(new FrontEnd)) ::: List(List(checker))
35+
}
36+
}
37+
38+
def checkDocString(actual: Option[String], expected: String): Unit = actual match {
39+
case Some(str) => {
40+
assert(str == expected, s"""Docstring: "$str" didn't match expected "$expected"""")
41+
}
42+
case None =>
43+
assert(false, s"""No docstring found, expected: "$expected"""")
44+
}
45+
46+
def run(): Unit = {
47+
val c = compiler(assertion)
48+
c.rootContext(ctx)
49+
c.newRun.compile(source)
50+
println(s"${self.getClass.getSimpleName.split("\\$").last} passed")
51+
}
52+
}
53+
54+
/** Add tests to the `tests` sequence */
55+
object DottyDocTests extends DottyTest {
56+
private[this] val tests = Seq(
57+
SingleClassInPackage,
58+
MultipleOpenedOnSingleClassInPackage,
59+
MultipleClassesInPackage,
60+
SingleCaseClassWithoutPackage,
61+
SingleTraitWihoutPackage,
62+
MultipleTraitsWithoutPackage
63+
)
64+
65+
def main(args: Array[String]): Unit = {
66+
println("------------ Testing DottyDoc ------------")
67+
tests.foreach(_.run)
68+
println("--------- DottyDoc tests passed! ----------")
69+
}
70+
}
71+
72+
case object SingleClassInPackage extends DottyDocTest {
73+
override val source =
74+
"""
75+
|package a
76+
|
77+
|/** Hello world! */
78+
|class Class(val x: String)
79+
""".stripMargin
80+
81+
override def assertion = {
82+
case PackageDef(_, Seq(t @ TypeDef(name, _))) if name.toString == "Class" =>
83+
checkDocString(t.rawComment, "/** Hello world! */")
84+
}
85+
}
86+
87+
case object MultipleOpenedOnSingleClassInPackage extends DottyDocTest {
88+
override val source =
89+
"""
90+
|package a
91+
|
92+
|/** Hello /* multiple open */ world! */
93+
|class Class(val x: String)
94+
""".stripMargin
95+
96+
override def assertion = {
97+
case PackageDef(_, Seq(t @ TypeDef(name, _))) if name.toString == "Class" =>
98+
checkDocString(t.rawComment, "/** Hello /* multiple open */ world! */")
99+
}
100+
}
101+
102+
case object MultipleClassesInPackage extends DottyDocTest {
103+
override val source =
104+
"""
105+
|package a
106+
|
107+
|/** Class1 docstring */
108+
|class Class1(val x: String)
109+
|
110+
|/** Class2 docstring */
111+
|class Class2(val x: String)
112+
""".stripMargin
113+
114+
override def assertion = {
115+
case PackageDef(_, Seq(c1 @ TypeDef(_,_), c2 @ TypeDef(_,_))) => {
116+
checkDocString(c1.rawComment, "/** Class1 docstring */")
117+
checkDocString(c2.rawComment, "/** Class2 docstring */")
118+
}
119+
}
120+
}
121+
122+
case object SingleCaseClassWithoutPackage extends DottyDocTest {
123+
override val source =
124+
"""
125+
|/** Class without package */
126+
|case class Class(val x: Int)
127+
""".stripMargin
128+
129+
override def assertion = {
130+
case PackageDef(_, Seq(t @ TypeDef(_,_))) => checkDocString(t.rawComment, "/** Class without package */")
131+
}
132+
}
133+
134+
case object SingleTraitWihoutPackage extends DottyDocTest {
135+
override val source = "/** Trait docstring */\ntrait Trait"
136+
137+
override def assertion = {
138+
case PackageDef(_, Seq(t @ TypeDef(_,_))) => checkDocString(t.rawComment, "/** Trait docstring */")
139+
}
140+
}
141+
142+
case object MultipleTraitsWithoutPackage extends DottyDocTest {
143+
//TODO: This will fail if the tratis don't have bodies, because of the Scanner
144+
override val source =
145+
"""
146+
|/** Trait1 docstring */
147+
|trait Trait1 {}
148+
|
149+
|/** Trait2 docstring */
150+
|trait Trait2 {}
151+
""".stripMargin
152+
153+
override def assertion = {
154+
case PackageDef(_, Seq(t1 @ TypeDef(_,_), t2 @ TypeDef(_,_))) => {
155+
checkDocString(t1.rawComment, "/** Trait1 docstring */")
156+
checkDocString(t2.rawComment, "/** Trait2 docstring */")
157+
}
158+
}
159+
}

test/test/DottyTest.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ class DottyTest /*extends ContextEscapeDetection*/ {
3232
}
3333
*/
3434
private def compilerWithChecker(phase: String)(assertion:(tpd.Tree, Context) => Unit) = new Compiler {
35-
self =>
3635
override def phases = {
3736
val allPhases = super.phases
3837
val targetPhase = allPhases.flatten.find(p => p.phaseName == phase).get
@@ -48,7 +47,7 @@ class DottyTest /*extends ContextEscapeDetection*/ {
4847
}
4948
}
5049

51-
def checkCompile(checkAfterPhase: String, source:String)(assertion:(tpd.Tree, Context) => Unit): Unit = {
50+
def checkCompile(checkAfterPhase: String, source: String)(assertion: (tpd.Tree, Context) => Unit): Unit = {
5251
val c = compilerWithChecker(checkAfterPhase)(assertion)
5352
c.rootContext(ctx)
5453
val run = c.newRun

0 commit comments

Comments
 (0)