diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-11-13 11:01:24 -0800 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-11-13 11:01:24 -0800 |
commit | 946b76ad8b31b1fd74e2f8e1972c4a9159ac690a (patch) | |
tree | 53f3f256ccd4dd84a89273a1e34cd2e956aaf6f7 /test/files | |
parent | 0e64a2e8254498155e243396e3e0fb184c86a563 (diff) | |
parent | 9484833838700e8db1b76081c32ee5e2bd9e8011 (diff) | |
download | scala-946b76ad8b31b1fd74e2f8e1972c4a9159ac690a.tar.gz scala-946b76ad8b31b1fd74e2f8e1972c4a9159ac690a.tar.bz2 scala-946b76ad8b31b1fd74e2f8e1972c4a9159ac690a.zip |
Merge pull request #3090 from densh/pull/undo-for
Add support for For loops to quasiquotes
Diffstat (limited to 'test/files')
15 files changed, 195 insertions, 102 deletions
diff --git a/test/files/scalacheck/quasiquotes/ArbitraryTreesAndNames.scala b/test/files/scalacheck/quasiquotes/ArbitraryTreesAndNames.scala index 4118d92076..c4b93dae48 100644 --- a/test/files/scalacheck/quasiquotes/ArbitraryTreesAndNames.scala +++ b/test/files/scalacheck/quasiquotes/ArbitraryTreesAndNames.scala @@ -1,11 +1,6 @@ -import org.scalacheck._ -import Prop._ -import Gen._ -import Arbitrary._ - -import scala.reflect.api._ -import scala.reflect.runtime.universe._ -import scala.reflect.runtime.universe.Flag._ +import org.scalacheck._, Prop._, Gen._, Arbitrary._ +import scala.reflect.api.{Liftable, Universe} +import scala.reflect.runtime.universe._, Flag._ trait ArbitraryTreesAndNames { def smallList[T](size: Int, g: Gen[T]) = { diff --git a/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala b/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala index e8ddb4b72a..2ec679e78b 100644 --- a/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/DefinitionConstructionProps.scala @@ -1,11 +1,5 @@ -import org.scalacheck._ -import Prop._ -import Gen._ -import Arbitrary._ - -import scala.reflect.runtime.universe._ -import scala.reflect.runtime.universe.build.ScalaDot -import Flag._ +import org.scalacheck._, Prop._, Gen._, Arbitrary._ +import scala.reflect.runtime.universe._, Flag._, build.ScalaDot object DefinitionConstructionProps extends QuasiquoteProperties("definition construction") diff --git a/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala index 993ef899b0..dbd26bf72a 100644 --- a/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/DefinitionDeconstructionProps.scala @@ -1,10 +1,5 @@ -import org.scalacheck._ -import Prop._ -import Gen._ -import Arbitrary._ - -import scala.reflect.runtime.universe._ -import Flag._ +import org.scalacheck._, Prop._, Gen._, Arbitrary._ +import scala.reflect.runtime.universe._, Flag._ object DefinitionDeconstructionProps extends QuasiquoteProperties("definition deconstruction") diff --git a/test/files/scalacheck/quasiquotes/ErrorProps.scala b/test/files/scalacheck/quasiquotes/ErrorProps.scala index b0a7641577..cb46a60dbe 100644 --- a/test/files/scalacheck/quasiquotes/ErrorProps.scala +++ b/test/files/scalacheck/quasiquotes/ErrorProps.scala @@ -1,10 +1,4 @@ -import org.scalacheck._ -import Prop._ -import Gen._ -import Arbitrary._ - -import scala.reflect.runtime.universe._ -import Flag._ +import org.scalacheck._, Prop._, Gen._, Arbitrary._ object ErrorProps extends QuasiquoteProperties("errors") { property("can't extract two .. cardinalities in a row") = fails( diff --git a/test/files/scalacheck/quasiquotes/ForProps.scala b/test/files/scalacheck/quasiquotes/ForProps.scala new file mode 100644 index 0000000000..e71822aaea --- /dev/null +++ b/test/files/scalacheck/quasiquotes/ForProps.scala @@ -0,0 +1,70 @@ +import org.scalacheck._, Prop._, Gen._, Arbitrary._ +import scala.reflect.runtime.universe._, Flag._, build.{Ident => _, _} + +object ForProps extends QuasiquoteProperties("for") { + case class ForEnums(val value: List[Tree]) + + def genSimpleBind: Gen[Bind] = + for(name <- genTermName) + yield pq"$name @ _" + + def genForFilter: Gen[Tree] = + for(cond <- genIdent(genTermName)) + yield fq"if $cond" + + def genForFrom: Gen[Tree] = + for(lhs <- genSimpleBind; rhs <- genIdent(genTermName)) + yield fq"$lhs <- $rhs" + + def genForEq: Gen[Tree] = + for(lhs <- genSimpleBind; rhs <- genIdent(genTermName)) + yield fq"$lhs = $rhs" + + def genForEnums(size: Int): Gen[ForEnums] = + for(first <- genForFrom; rest <- listOfN(size, oneOf(genForFrom, genForFilter, genForEq))) + yield new ForEnums(first :: rest) + + implicit val arbForEnums: Arbitrary[ForEnums] = arbitrarySized(genForEnums) + + property("construct-reconstruct for") = forAll { (enums: ForEnums, body: Tree) => + val SyntacticFor(recoveredEnums, recoveredBody) = SyntacticFor(enums.value, body) + recoveredEnums ≈ enums.value && recoveredBody ≈ body + } + + property("construct-reconstruct for-yield") = forAll { (enums: ForEnums, body: Tree) => + val SyntacticForYield(recoveredEnums, recoveredBody) = SyntacticForYield(enums.value, body) + recoveredEnums ≈ enums.value && recoveredBody ≈ body + } + + val abcde = List(fq"a <-b", fq"if c", fq"d = e") + val foobarbaz = pq"foo @ Bar(baz)" + val fv = q"f(v)" + + property("construct/deconstruct for loop with fq") = test { + val for0 = q"for(..$abcde) $fv" + assertEqAst(for0, "for(a <- b; if c; d = e) f(v)") + val q"for(..$enums) $body" = for0 + assert(enums ≈ abcde) + assert(body ≈ fv) + } + + property("construct/deconstruct valfrom with fq") = test { + assert(fq"$foobarbaz <- $fv" ≈ fq"foo @ Bar(baz) <- f(v)") + val fq"$lhs <- $rhs" = fq"$foobarbaz <- $fv" + assert(lhs ≈ foobarbaz) + assert(rhs ≈ fv) + } + + property("construct/deconstruct valeq with fq") = test { + assert(fq"$foobarbaz = $fv" ≈ fq"foo @ Bar(baz) = f(v)") + val fq"$lhs = $rhs" = fq"$foobarbaz = $fv" + assert(lhs ≈ foobarbaz) + assert(rhs ≈ fv) + } + + property("construct/deconstruct filter with fq") = test { + assert(fq"if $fv" ≈ fq"if f(v)") + val fq"if $cond" = fq"if $fv" + assert(cond ≈ fv) + } +}
\ No newline at end of file diff --git a/test/files/scalacheck/quasiquotes/LiftableProps.scala b/test/files/scalacheck/quasiquotes/LiftableProps.scala index 510ab99068..1271e1accd 100644 --- a/test/files/scalacheck/quasiquotes/LiftableProps.scala +++ b/test/files/scalacheck/quasiquotes/LiftableProps.scala @@ -1,10 +1,5 @@ -import org.scalacheck._ -import Prop._ -import Gen._ -import Arbitrary._ - -import scala.reflect.runtime.universe._ -import Flag._ +import org.scalacheck._, Prop._, Gen._, Arbitrary._ +import scala.reflect.runtime.universe._, Flag._ object LiftableProps extends QuasiquoteProperties("liftable") { property("splice byte") = test { diff --git a/test/files/scalacheck/quasiquotes/PatternConstructionProps.scala b/test/files/scalacheck/quasiquotes/PatternConstructionProps.scala index 504cb2a77d..582e915258 100644 --- a/test/files/scalacheck/quasiquotes/PatternConstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/PatternConstructionProps.scala @@ -1,10 +1,5 @@ -import org.scalacheck._ -import Prop._ -import Gen._ -import Arbitrary._ - -import scala.reflect.runtime.universe._ -import Flag._ +import org.scalacheck._, Prop._, Gen._, Arbitrary._ +import scala.reflect.runtime.universe._, Flag._ object PatternConstructionProps extends QuasiquoteProperties("pattern construction") { property("splice bind") = forAll { (bind: Bind) => diff --git a/test/files/scalacheck/quasiquotes/PatternDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/PatternDeconstructionProps.scala index f73fd29b22..cccf8095db 100644 --- a/test/files/scalacheck/quasiquotes/PatternDeconstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/PatternDeconstructionProps.scala @@ -1,11 +1,5 @@ -import org.scalacheck._ -import Prop._ -import Gen._ -import Arbitrary._ - -import scala.reflect.runtime.universe._ -import Flag._ -import definitions._ +import org.scalacheck._, Prop._, Gen._, Arbitrary._ +import scala.reflect.runtime.universe._, Flag._ object PatternDeconstructionProps extends QuasiquoteProperties("pattern deconstruction") { property("extract bind") = forAll { (bind: Bind) => diff --git a/test/files/scalacheck/quasiquotes/QuasiquoteProperties.scala b/test/files/scalacheck/quasiquotes/QuasiquoteProperties.scala index 6a531071bf..b2bce124ee 100644 --- a/test/files/scalacheck/quasiquotes/QuasiquoteProperties.scala +++ b/test/files/scalacheck/quasiquotes/QuasiquoteProperties.scala @@ -1,15 +1,7 @@ -import scala.reflect.runtime.universe._ -import scala.reflect.runtime.universe.definitions._ -import scala.reflect.runtime.universe.Flag._ -import scala.reflect.runtime.currentMirror -import scala.reflect.api.{Liftable, Universe} -import scala.reflect.macros.TypecheckException +import org.scalacheck._, Prop._, Gen._, Arbitrary._ import scala.tools.reflect.{ToolBox, ToolBoxError} - -import org.scalacheck._ -import Prop._ -import Gen._ -import Arbitrary._ +import scala.reflect.runtime.currentMirror +import scala.reflect.runtime.universe._, Flag._ class QuasiquoteProperties(name: String) extends Properties(name) with ArbitraryTreesAndNames with Helpers @@ -18,14 +10,36 @@ trait Helpers { * if no exception has been thrown while executing code * block. This is useful for simple one-off tests. */ - def test[T](block: => T)= - Prop { (params) => + def test[T](block: => T) = + Prop { params => block Result(Prop.Proof) } + object simplify extends Transformer { + object SimplifiedName { + def unapply[T <: Name](name: T): Option[T] = + name.toString.split("\\$").toSeq match { + case first :+ last if scala.util.Try(last.toInt).isSuccess && first.nonEmpty => + val value = first.mkString("", "$", "$") + Some((if (name.isTermName) TermName(value) else TypeName(value)).asInstanceOf[T]) + case _ => None + } + } + + override def transform(tree: Tree): Tree = tree match { + case Ident(SimplifiedName(name)) => Ident(name) + case ValDef(mods, SimplifiedName(name), tpt, rhs) => ValDef(mods, name, tpt, rhs) + case Bind(SimplifiedName(name), rhs) => Bind(name, rhs) + case _ => + super.transform(tree) + } + + def apply(tree: Tree): Tree = transform(tree) + } + implicit class TestSimilarTree(tree1: Tree) { - def ≈(tree2: Tree) = tree1.equalsStructure(tree2) + def ≈(tree2: Tree) = simplify(tree1).equalsStructure(simplify(tree2)) } implicit class TestSimilarListTree(lst: List[Tree]) { @@ -68,6 +82,18 @@ trait Helpers { val compile = toolbox.compile(_) val eval = toolbox.eval(_) + def typecheck(tree: Tree) = toolbox.typeCheck(tree) + + def typecheckTyp(tree: Tree) = { + val q"type $_ = $res" = typecheck(q"type T = $tree") + res + } + + def typecheckPat(tree: Tree) = { + val q"$_ match { case $res => }" = typecheck(q"((): Any) match { case $tree => }") + res + } + def fails(msg: String, block: String) = { def result(ok: Boolean, description: String = "") = { val status = if (ok) Prop.Proof else Prop.False diff --git a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala index f68656d0f7..cdd96205de 100644 --- a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala @@ -1,10 +1,5 @@ -import org.scalacheck._ -import Prop._ -import Gen._ -import Arbitrary._ - -import scala.reflect.runtime.universe._ -import Flag._ +import org.scalacheck._, Prop._, Gen._, Arbitrary._ +import scala.reflect.runtime.universe._, Flag._ object TermConstructionProps extends QuasiquoteProperties("term construction") { property("splice single tree return tree itself") = forAll { (t: Tree) => @@ -148,8 +143,8 @@ object TermConstructionProps extends QuasiquoteProperties("term construction") { val a1 = q"a1" val a2 = q"a2" val as = List(a1, a2) - assert(q"(..$as)" ≈ q"Tuple2($a1, $a2)") - assert(q"(a0, ..$as)" ≈ q"Tuple3(a0, $a1, $a2)") + assert(q"(..$as)" ≈ q"scala.Tuple2($a1, $a2)") + assert(q"(a0, ..$as)" ≈ q"scala.Tuple3(a0, $a1, $a2)") } property("splice empty list into tuple") = test { @@ -193,11 +188,11 @@ object TermConstructionProps extends QuasiquoteProperties("term construction") { property("fresh names are regenerated at each evaluation") = test { def plusOne = q"{ _ + 1 }" - assert(!(plusOne ≈ plusOne)) + assert(!plusOne.equalsStructure(plusOne)) def whileTrue = q"while(true) false" - assert(!(whileTrue ≈ whileTrue)) + assert(!whileTrue.equalsStructure(whileTrue)) def withEvidence = q"def foo[T: X]" - assert(!(withEvidence ≈ withEvidence)) + assert(!withEvidence.equalsStructure(withEvidence)) } property("make sure inference doesn't infer any") = test { diff --git a/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala index f37e4d9975..bd81afa125 100644 --- a/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala @@ -1,10 +1,5 @@ -import org.scalacheck._ -import Prop._ -import Gen._ -import Arbitrary._ - -import scala.reflect.runtime.universe._ -import Flag._ +import org.scalacheck._, Prop._, Gen._, Arbitrary._ +import scala.reflect.runtime.universe._, Flag._ object TermDeconstructionProps extends QuasiquoteProperties("term deconstruction") { property("f(..x) = f") = test { diff --git a/test/files/scalacheck/quasiquotes/Test.scala b/test/files/scalacheck/quasiquotes/Test.scala index f41d961888..8b1e779ab2 100644 --- a/test/files/scalacheck/quasiquotes/Test.scala +++ b/test/files/scalacheck/quasiquotes/Test.scala @@ -12,4 +12,6 @@ object Test extends Properties("quasiquotes") { include(DefinitionConstructionProps) include(DefinitionDeconstructionProps) include(DeprecationProps) + include(ForProps) + include(TypecheckedProps) } diff --git a/test/files/scalacheck/quasiquotes/TypeConstructionProps.scala b/test/files/scalacheck/quasiquotes/TypeConstructionProps.scala index cac83ff8ac..be7a96d91e 100644 --- a/test/files/scalacheck/quasiquotes/TypeConstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/TypeConstructionProps.scala @@ -1,10 +1,5 @@ -import org.scalacheck._ -import Prop._ -import Gen._ -import Arbitrary._ - -import scala.reflect.runtime.universe._ -import Flag._ +import org.scalacheck._, Prop._, Gen._, Arbitrary._ +import scala.reflect.runtime.universe._, Flag._ object TypeConstructionProps extends QuasiquoteProperties("type construction") { property("bare idents contain type names") = test { @@ -18,9 +13,9 @@ object TypeConstructionProps extends QuasiquoteProperties("type construction") property("tuple type") = test { val empty = List[Tree]() val ts = List(tq"t1", tq"t2") - assert(tq"(..$empty)" ≈ tq"scala.Unit") - assert(tq"(..$ts)" ≈ tq"Tuple2[t1, t2]") - assert(tq"(t0, ..$ts)" ≈ tq"Tuple3[t0, t1, t2]") + assert(tq"(..$empty)" ≈ build.ScalaDot(TypeName("Unit"))) + assert(tq"(..$ts)" ≈ tq"scala.Tuple2[t1, t2]") + assert(tq"(t0, ..$ts)" ≈ tq"scala.Tuple3[t0, t1, t2]") } property("refined type") = test { diff --git a/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala index e1d5f4df96..499f5d6d8e 100644 --- a/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala +++ b/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala @@ -1,10 +1,5 @@ -import org.scalacheck._ -import Prop._ -import Gen._ -import Arbitrary._ - -import scala.reflect.runtime.universe._ -import Flag._ +import org.scalacheck._, Prop._, Gen._, Arbitrary._ +import scala.reflect.runtime.universe._, Flag._ object TypeDeconstructionProps extends QuasiquoteProperties("type deconstruction") { property("ident(type name)") = forAll { (name: TypeName) => diff --git a/test/files/scalacheck/quasiquotes/TypecheckedProps.scala b/test/files/scalacheck/quasiquotes/TypecheckedProps.scala new file mode 100644 index 0000000000..f443330e0b --- /dev/null +++ b/test/files/scalacheck/quasiquotes/TypecheckedProps.scala @@ -0,0 +1,53 @@ +import org.scalacheck._, Prop._, Gen._, Arbitrary._ +import scala.reflect.runtime.universe._, Flag._, build.{Ident => _, _} + +object TypecheckedProps extends QuasiquoteProperties("typechecked") { + def original(tree: Tree) = tree match { + case tt: TypeTree => Some(tt.original) + case _ => None + } + def originals(trees: List[Tree]) = trees.flatMap(original) + val int = ScalaDot(TypeName("Int")) + val intint = List(int, int) + + property("tuple term") = test { + val q"(..$elements)" = typecheck(q"(1, 2)") + assert(elements ≈ List(q"1", q"2")) + } + + property("tuple type") = test { + val tq"(..$els0)" = typecheckTyp(tq"Unit") + assert(els0.isEmpty) + val tq"(..$els1)" = typecheckTyp(tq"(Int, Int)") + assert(originals(els1) ≈ intint) + } + + property("function type") = test { + val tq"(..$argtpes) => $restpe" = typecheckTyp(tq"(Int, Int) => Int") + assert(originals(argtpes) ≈ intint) + assert(original(restpe).get ≈ int) + } + + property("for/for-yield") = test { + val enums = fq"x <- xs" :: fq"x1 = x + 1" :: fq"if x1 % 2 == 0" :: Nil + val body = q"x1" + val xs = q"val xs = List(1, 2, 3)" + val q"$_; for(..$enums0) yield $body0" = typecheck(q"$xs; for(..$enums) yield $body") + assert(enums0 ≈ enums) + assert(body0 ≈ body) + val q"$_; for(..$enums1) $body1" = typecheck(q"$xs; for(..$enums) $body") + assert(enums1 ≈ enums) + assert(body1 ≈ body) + } + + property("for .filter instead of .withFilter") = test { + val enums = fq"foo <- new Foo" :: fq"if foo != null" :: Nil + val body = q"foo" + val q"$_; for(..$enums1) yield $body1" = typecheck(q""" + class Foo { def map(f: Any => Any) = this; def filter(cond: Any => Boolean) = this } + for(..$enums) yield $body + """) + assert(enums1 ≈ enums) + assert(body1 ≈ body) + } +}
\ No newline at end of file |