aboutsummaryrefslogblamecommitdiff
path: root/test/test/DottyDocParsingTests.scala
blob: b09d048da22581ce6fccc737156e7cc773e14608 (plain) (tree)
1
2
3
4
5
6
7
8
9







                                             
                                                 
 
                         








                                                                                                   
                                    













                                                                                  
                                                    












                                                                                  
                                        




















                                                                          
                                             










                                                                                                               
                                        






                                                                                                         
                                            
















                                                                        
                                                


























                                                                                                                   
                           



















                                                                                                        
                                    























                                                                                                        
                       




















                                                                                      
                                  






























                                                                                                             
                             



































                                                                                                            
                                              














                                                           
                                                

















                                                           
                                   






























                                                                                
                                 






























                                                                                
                                 






























                                                                                
                                  





























                                                                                





















                                                                      





























                                                     
                 
package test

import dotty.tools.dotc.core.Contexts.Context
import dotty.tools.dotc.ast.Trees._

import org.junit.Assert._
import org.junit.Test

class DottyDocParsingTests extends DottyDocTest {

  @Test def noComment = {
    import dotty.tools.dotc.ast.untpd._
    val source = "class Class"

    checkFrontend(source) {
      case PackageDef(_, Seq(c: TypeDef)) =>
        assert(c.rawComment == 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, "/** 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, "/** 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, "/** Class1 docstring */")
          checkDocString(c2.rawComment, "/** 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, "/** Class without package */")
    }
  }

  @Test def SingleTraitWihoutPackage = {
    val source = "/** Trait docstring */\ntrait Trait"

    checkFrontend(source) {
      case PackageDef(_, Seq(t @ TypeDef(_,_))) => checkDocString(t.rawComment, "/** 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, "/** Trait1 docstring */")
        checkDocString(t2.rawComment, "/** 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, "/** Trait1 docstring */")
        checkDocString(c2.rawComment, "/** Class2 docstring */")
        checkDocString(cc3.rawComment, "/** CaseClass3 docstring */")
        checkDocString(ac4.rawComment, "/** 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, "/** Outer docstring */")
        tpl.body match {
          case (inner @ TypeDef(_,_)) :: _ => checkDocString(inner.rawComment, "/** 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, "/** Outer1 docstring */")
        checkDocString(o2.rawComment, "/** Outer2 docstring */")
        tpl.body match {
          case (inner @ TypeDef(_,_)) :: _ => checkDocString(inner.rawComment, "/** 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, "/** Object1 docstring */")
        assertEquals(o2.name.toString, "Object2")
        checkDocString(o2.rawComment, "/** 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, "/** Object1 docstring */")
        assert(o2.name.toString == "Object2")
        checkDocString(o2.rawComment, "/** Object2 docstring */")

        o2.impl.body match {
          case _ :: (inner @ TypeDef(_,_)) :: _ => checkDocString(inner.rawComment, "/** 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, "/** Package object docstring */")

        p.impl.body match {
          case (b: TypeDef) :: (t: TypeDef) :: (o: ModuleDef) :: Nil => {
            checkDocString(b.rawComment, "/** Boo docstring */")
            checkDocString(t.rawComment, "/** Trait docstring */")
            checkDocString(o.rawComment, "/** InnerObject docstring */")
            checkDocString(o.impl.body.head.asInstanceOf[TypeDef].rawComment, "/** 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, "/** 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, "/** 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, "/** val1 */")
            checkDocString(v2.rawComment, "/** val2 */")
            checkDocString(v3.rawComment, "/** 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, "/** var1 */")
            checkDocString(v2.rawComment, "/** var2 */")
            checkDocString(v3.rawComment, "/** 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, "/** def1 */")
            checkDocString(v2.rawComment, "/** def2 */")
            checkDocString(v3.rawComment, "/** 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, "/** type1 */")
            checkDocString(v2.rawComment, "/** type2 */")
            checkDocString(v3.rawComment, "/** 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)
          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, "/** 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, "/** Class1 */")
    }
  }
} /* End class */