diff options
Diffstat (limited to 'test/dotty/tools/dotc/parsing/DocstringTests.scala')
-rw-r--r-- | test/dotty/tools/dotc/parsing/DocstringTests.scala | 491 |
1 files changed, 491 insertions, 0 deletions
diff --git a/test/dotty/tools/dotc/parsing/DocstringTests.scala b/test/dotty/tools/dotc/parsing/DocstringTests.scala new file mode 100644 index 000000000..930ec117a --- /dev/null +++ b/test/dotty/tools/dotc/parsing/DocstringTests.scala @@ -0,0 +1,491 @@ +package dotty.tools +package dotc +package parsing + +import dotty.tools.dotc.core.Contexts.Context +import dotty.tools.dotc.ast.Trees._ + +import org.junit.Assert._ +import org.junit.Test + +class DocstringTests extends DocstringTest { + + @Test def noComment = { + import dotty.tools.dotc.ast.untpd._ + val source = "class Class" + + checkFrontend(source) { + case PackageDef(_, Seq(c: TypeDef)) => + assert(c.rawComment.map(_.raw) == None, "Should not have a comment, mainly used for exhaustive tests") + } + } + + @Test def singleClassInPackage = { + val source = + """ + |package a + | + |/** Hello world! */ + |class Class(val x: String) + """.stripMargin + + checkFrontend(source) { + case PackageDef(_, Seq(t @ TypeDef(name, _))) if name.toString == "Class" => + checkDocString(t.rawComment.map(_.raw), "/** Hello world! */") + } + } + + @Test def multipleOpenedOnSingleClassInPackage = { + val source = + """ + |package a + | + |/** Hello /* multiple open */ world! */ + |class Class(val x: String) + """.stripMargin + + checkFrontend(source) { + case PackageDef(_, Seq(t @ TypeDef(name, _))) if name.toString == "Class" => + checkDocString(t.rawComment.map(_.raw), "/** Hello /* multiple open */ world! */") + } + } + @Test def multipleClassesInPackage = { + val source = + """ + |package a + | + |/** Class1 docstring */ + |class Class1(val x: String) + | + |/** Class2 docstring */ + |class Class2(val x: String) + """.stripMargin + + checkCompile("frontend", source) { (_, ctx) => + ctx.compilationUnit.untpdTree match { + case PackageDef(_, Seq(c1 @ TypeDef(_,_), c2 @ TypeDef(_,_))) => { + checkDocString(c1.rawComment.map(_.raw), "/** Class1 docstring */") + checkDocString(c2.rawComment.map(_.raw), "/** Class2 docstring */") + } + } + } + } + + @Test def singleCaseClassWithoutPackage = { + val source = + """ + |/** Class without package */ + |case class Class(val x: Int) + """.stripMargin + + checkFrontend(source) { + case PackageDef(_, Seq(t @ TypeDef(_,_))) => checkDocString(t.rawComment.map(_.raw), "/** Class without package */") + } + } + + @Test def SingleTraitWihoutPackage = { + val source = "/** Trait docstring */\ntrait Trait" + + checkFrontend(source) { + case PackageDef(_, Seq(t @ TypeDef(_,_))) => checkDocString(t.rawComment.map(_.raw), "/** Trait docstring */") + } + } + + @Test def multipleTraitsWithoutPackage = { + val source = + """ + |/** Trait1 docstring */ + |trait Trait1 + | + |/** Trait2 docstring */ + |trait Trait2 + """.stripMargin + + checkFrontend(source) { + case PackageDef(_, Seq(t1 @ TypeDef(_,_), t2 @ TypeDef(_,_))) => { + checkDocString(t1.rawComment.map(_.raw), "/** Trait1 docstring */") + checkDocString(t2.rawComment.map(_.raw), "/** Trait2 docstring */") + } + } + } + + @Test def multipleMixedEntitiesWithPackage = { + val source = + """ + |/** Trait1 docstring */ + |trait Trait1 + | + |/** Class2 docstring */ + |class Class2(val x: Int) + | + |/** CaseClass3 docstring */ + |case class CaseClass3() + | + |case class NoComment() + | + |/** AbstractClass4 docstring */ + |abstract class AbstractClass4(val x: Int) + """.stripMargin + + checkFrontend(source) { + case PackageDef(_, Seq(t1 @ TypeDef(_,_), c2 @ TypeDef(_,_), cc3 @ TypeDef(_,_), _, ac4 @ TypeDef(_,_))) => { + checkDocString(t1.rawComment.map(_.raw), "/** Trait1 docstring */") + checkDocString(c2.rawComment.map(_.raw), "/** Class2 docstring */") + checkDocString(cc3.rawComment.map(_.raw), "/** CaseClass3 docstring */") + checkDocString(ac4.rawComment.map(_.raw), "/** AbstractClass4 docstring */") + } + } + } + + @Test def nestedClass = { + val source = + """ + |/** Outer docstring */ + |class Outer { + | /** Inner docstring */ + | class Inner(val x: Int) + |} + """.stripMargin + + checkFrontend(source) { + case PackageDef(_, Seq(outer @ TypeDef(_, tpl @ Template(_,_,_,_)))) => { + checkDocString(outer.rawComment.map(_.raw), "/** Outer docstring */") + tpl.body match { + case (inner @ TypeDef(_,_)) :: _ => checkDocString(inner.rawComment.map(_.raw), "/** Inner docstring */") + case _ => assert(false, "Couldn't find inner class") + } + } + } + } + + @Test def nestedClassThenOuter = { + val source = + """ + |/** Outer1 docstring */ + |class Outer1 { + | /** Inner docstring */ + | class Inner(val x: Int) + |} + | + |/** Outer2 docstring */ + |class Outer2 + """.stripMargin + + checkFrontend(source) { + case PackageDef(_, Seq(o1 @ TypeDef(_, tpl @ Template(_,_,_,_)), o2 @ TypeDef(_,_))) => { + checkDocString(o1.rawComment.map(_.raw), "/** Outer1 docstring */") + checkDocString(o2.rawComment.map(_.raw), "/** Outer2 docstring */") + tpl.body match { + case (inner @ TypeDef(_,_)) :: _ => checkDocString(inner.rawComment.map(_.raw), "/** Inner docstring */") + case _ => assert(false, "Couldn't find inner class") + } + } + } + } + + @Test def objects = { + val source = + """ + |package p + | + |/** Object1 docstring */ + |object Object1 + | + |/** Object2 docstring */ + |object Object2 + """.stripMargin + + checkFrontend(source) { + case p @ PackageDef(_, Seq(o1: MemberDef[Untyped], o2: MemberDef[Untyped])) => { + assertEquals(o1.name.toString, "Object1") + checkDocString(o1.rawComment.map(_.raw), "/** Object1 docstring */") + assertEquals(o2.name.toString, "Object2") + checkDocString(o2.rawComment.map(_.raw), "/** Object2 docstring */") + } + } + } + + @Test def objectsNestedClass = { + val source = + """ + |package p + | + |/** Object1 docstring */ + |object Object1 + | + |/** Object2 docstring */ + |object Object2 { + | class A1 + | /** Inner docstring */ + | class Inner + |} + """.stripMargin + + import dotty.tools.dotc.ast.untpd._ + checkFrontend(source) { + case p @ PackageDef(_, Seq(o1: ModuleDef, o2: ModuleDef)) => { + assert(o1.name.toString == "Object1") + checkDocString(o1.rawComment.map(_.raw), "/** Object1 docstring */") + assert(o2.name.toString == "Object2") + checkDocString(o2.rawComment.map(_.raw), "/** Object2 docstring */") + + o2.impl.body match { + case _ :: (inner @ TypeDef(_,_)) :: _ => checkDocString(inner.rawComment.map(_.raw), "/** Inner docstring */") + case _ => assert(false, "Couldn't find inner class") + } + } + } + } + + @Test def packageObject = { + val source = + """ + |/** Package object docstring */ + |package object foo { + | /** Boo docstring */ + | case class Boo() + | + | /** Trait docstring */ + | trait Trait + | + | /** InnerObject docstring */ + | object InnerObject { + | /** InnerClass docstring */ + | class InnerClass + | } + |} + """.stripMargin + + import dotty.tools.dotc.ast.untpd._ + checkFrontend(source) { + case PackageDef(_, Seq(p: ModuleDef)) => { + checkDocString(p.rawComment.map(_.raw), "/** Package object docstring */") + + p.impl.body match { + case (b: TypeDef) :: (t: TypeDef) :: (o: ModuleDef) :: Nil => { + checkDocString(b.rawComment.map(_.raw), "/** Boo docstring */") + checkDocString(t.rawComment.map(_.raw), "/** Trait docstring */") + checkDocString(o.rawComment.map(_.raw), "/** InnerObject docstring */") + checkDocString(o.impl.body.head.asInstanceOf[TypeDef].rawComment.map(_.raw), "/** InnerClass docstring */") + } + case _ => assert(false, "Incorrect structure inside package object") + } + } + } + } + + @Test def multipleDocStringsBeforeEntity = { + val source = + """ + |/** First comment */ + |/** Second comment */ + |/** Real comment */ + |class Class + """.stripMargin + + import dotty.tools.dotc.ast.untpd._ + checkFrontend(source) { + case PackageDef(_, Seq(c: TypeDef)) => + checkDocString(c.rawComment.map(_.raw), "/** Real comment */") + } + } + + @Test def multipleDocStringsBeforeAndAfter = { + val source = + """ + |/** First comment */ + |/** Second comment */ + |/** Real comment */ + |class Class + |/** Following comment 1 */ + |/** Following comment 2 */ + |/** Following comment 3 */ + """.stripMargin + + import dotty.tools.dotc.ast.untpd._ + checkFrontend(source) { + case PackageDef(_, Seq(c: TypeDef)) => + checkDocString(c.rawComment.map(_.raw), "/** Real comment */") + } + } + + @Test def valuesWithDocString = { + val source = + """ + |object Object { + | /** val1 */ + | val val1 = 1 + | + | /** val2 */ + | val val2: Int = 2 + | /** bogus docstring */ + | + | /** bogus docstring */ + | /** val3 */ + | val val3: List[Int] = 1 :: 2 :: 3 :: Nil + |} + """.stripMargin + + import dotty.tools.dotc.ast.untpd._ + checkFrontend(source) { + case PackageDef(_, Seq(o: ModuleDef)) => { + o.impl.body match { + case (v1: MemberDef) :: (v2: MemberDef) :: (v3: MemberDef) :: Nil => { + checkDocString(v1.rawComment.map(_.raw), "/** val1 */") + checkDocString(v2.rawComment.map(_.raw), "/** val2 */") + checkDocString(v3.rawComment.map(_.raw), "/** val3 */") + } + case _ => assert(false, "Incorrect structure inside object") + } + } + } + } + + @Test def varsWithDocString = { + val source = + """ + |object Object { + | /** var1 */ + | var var1 = 1 + | + | /** var2 */ + | var var2: Int = 2 + | /** bogus docstring */ + | + | /** bogus docstring */ + | /** var3 */ + | var var3: List[Int] = 1 :: 2 :: 3 :: Nil + |} + """.stripMargin + + import dotty.tools.dotc.ast.untpd._ + checkFrontend(source) { + case PackageDef(_, Seq(o: ModuleDef)) => { + o.impl.body match { + case (v1: MemberDef) :: (v2: MemberDef) :: (v3: MemberDef) :: Nil => { + checkDocString(v1.rawComment.map(_.raw), "/** var1 */") + checkDocString(v2.rawComment.map(_.raw), "/** var2 */") + checkDocString(v3.rawComment.map(_.raw), "/** var3 */") + } + case _ => assert(false, "Incorrect structure inside object") + } + } + } + } + + @Test def defsWithDocString = { + val source = + """ + |object Object { + | /** def1 */ + | def def1 = 1 + | + | /** def2 */ + | def def2: Int = 2 + | /** bogus docstring */ + | + | /** bogus docstring */ + | /** def3 */ + | def def3: List[Int] = 1 :: 2 :: 3 :: Nil + |} + """.stripMargin + + import dotty.tools.dotc.ast.untpd._ + checkFrontend(source) { + case PackageDef(_, Seq(o: ModuleDef)) => { + o.impl.body match { + case (v1: MemberDef) :: (v2: MemberDef) :: (v3: MemberDef) :: Nil => { + checkDocString(v1.rawComment.map(_.raw), "/** def1 */") + checkDocString(v2.rawComment.map(_.raw), "/** def2 */") + checkDocString(v3.rawComment.map(_.raw), "/** def3 */") + } + case _ => assert(false, "Incorrect structure inside object") + } + } + } + } + + @Test def typesWithDocString = { + val source = + """ + |object Object { + | /** type1 */ + | type T1 = Int + | + | /** type2 */ + | type T2 = String + | /** bogus docstring */ + | + | /** bogus docstring */ + | /** type3 */ + | type T3 = T2 + |} + """.stripMargin + + import dotty.tools.dotc.ast.untpd._ + checkFrontend(source) { + case PackageDef(_, Seq(o: ModuleDef)) => { + o.impl.body match { + case (v1: MemberDef) :: (v2: MemberDef) :: (v3: MemberDef) :: Nil => { + checkDocString(v1.rawComment.map(_.raw), "/** type1 */") + checkDocString(v2.rawComment.map(_.raw), "/** type2 */") + checkDocString(v3.rawComment.map(_.raw), "/** type3 */") + } + case _ => assert(false, "Incorrect structure inside object") + } + } + } + } + + @Test def defInnerClass = { + val source = + """ + |object Foo { + | def foo() = { + | /** Innermost */ + | class Innermost + | } + |} + """.stripMargin + + import dotty.tools.dotc.ast.untpd._ + checkFrontend(source) { + case PackageDef(_, Seq(o: ModuleDef)) => + o.impl.body match { + case (foo: MemberDef) :: Nil => + expectNoDocString(foo.rawComment.map(_.raw)) + case _ => assert(false, "Incorrect structure inside object") + } + } + } + + @Test def withExtends = { + val source = + """ + |trait Trait1 + |/** Class1 */ + |class Class1 extends Trait1 + """.stripMargin + + import dotty.tools.dotc.ast.untpd._ + checkFrontend(source) { + case p @ PackageDef(_, Seq(_, c: TypeDef)) => + checkDocString(c.rawComment.map(_.raw), "/** Class1 */") + } + } + + @Test def withAnnotation = { + val source = + """ + |/** Class1 */ + |@SerialVersionUID(1) + |class Class1 + """.stripMargin + + import dotty.tools.dotc.ast.untpd._ + checkFrontend(source) { + case p @ PackageDef(_, Seq(c: TypeDef)) => + checkDocString(c.rawComment.map(_.raw), "/** Class1 */") + } + } +} /* End class */ |