diff options
Diffstat (limited to 'test')
67 files changed, 2044 insertions, 446 deletions
diff --git a/test/files/codelib/.gitignore b/test/files/codelib/.gitignore new file mode 100644 index 0000000000..f77a26afb7 --- /dev/null +++ b/test/files/codelib/.gitignore @@ -0,0 +1 @@ +code.jar diff --git a/test/files/jvm/bytecode-test-example/Foo_1.flags b/test/files/jvm/bytecode-test-example/Foo_1.flags new file mode 100644 index 0000000000..49f2d2c4c8 --- /dev/null +++ b/test/files/jvm/bytecode-test-example/Foo_1.flags @@ -0,0 +1 @@ +-Ybackend:GenASM diff --git a/test/files/jvm/nooptimise/Foo_1.flags b/test/files/jvm/nooptimise/Foo_1.flags index 9686c20775..f493cf9f3f 100644 --- a/test/files/jvm/nooptimise/Foo_1.flags +++ b/test/files/jvm/nooptimise/Foo_1.flags @@ -1 +1 @@ --optimise -Ynooptimise
\ No newline at end of file +-Ybackend:GenASM -optimise -Ynooptimise
\ No newline at end of file diff --git a/test/files/jvm/scala-concurrent-tck.check b/test/files/jvm/scala-concurrent-tck.check deleted file mode 100644 index 18fc456acb..0000000000 --- a/test/files/jvm/scala-concurrent-tck.check +++ /dev/null @@ -1,3 +0,0 @@ -scala-concurrent-tck.scala:429: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses - f - ^ diff --git a/test/files/jvm/scala-concurrent-tck.scala b/test/files/jvm/scala-concurrent-tck.scala index 438ee310e6..6e2b8ca033 100644 --- a/test/files/jvm/scala-concurrent-tck.scala +++ b/test/files/jvm/scala-concurrent-tck.scala @@ -15,21 +15,17 @@ import scala.reflect.{ classTag, ClassTag } import scala.tools.partest.TestUtil.intercept trait TestBase { - - def once(body: (() => Unit) => Unit) { - val sv = new SyncVar[Boolean] - body(() => sv put true) - sv.take(2000) + trait Done { def apply(proof: => Boolean): Unit } + def once(body: Done => Unit) { + import java.util.concurrent.{ LinkedBlockingQueue, TimeUnit } + val q = new LinkedBlockingQueue[Try[Boolean]] + body(new Done { + def apply(proof: => Boolean): Unit = q offer Try(proof) + }) + assert(q.poll(2000, TimeUnit.MILLISECONDS).get) + // Check that we don't get more than one completion + assert(q.poll(50, TimeUnit.MILLISECONDS) eq null) } - - // def assert(cond: => Boolean) { - // try { - // Predef.assert(cond) - // } catch { - // case e => e.printStackTrace() - // } - // } - } @@ -39,99 +35,52 @@ trait FutureCallbacks extends TestBase { def testOnSuccess(): Unit = once { done => var x = 0 - val f = future { - x = 1 - } - f onSuccess { - case _ => - done() - assert(x == 1) - } + val f = future { x = 1 } + f onSuccess { case _ => done(x == 1) } } def testOnSuccessWhenCompleted(): Unit = once { done => var x = 0 - val f = future { - x = 1 - } + val f = future { x = 1 } f onSuccess { - case _ => - assert(x == 1) + case _ if x == 1 => x = 2 - f onSuccess { - case _ => - assert(x == 2) - done() - } + f onSuccess { case _ => done(x == 2) } } } def testOnSuccessWhenFailed(): Unit = once { done => - val f = future[Unit] { - done() - throw new Exception - } - f onSuccess { - case _ => assert(false) - } + val f = future[Unit] { throw new Exception } + f onSuccess { case _ => done(false) } + f onFailure { case _ => done(true) } } def testOnFailure(): Unit = once { done => - var x = 0 - val f = future[Unit] { - x = 1 - throw new Exception - } - f onSuccess { - case _ => - done() - assert(false) - } - f onFailure { - case _ => - done() - assert(x == 1) - } + val f = future[Unit] { throw new Exception } + f onSuccess { case _ => done(false) } + f onFailure { case _ => done(true) } } def testOnFailureWhenSpecialThrowable(num: Int, cause: Throwable): Unit = once { done => - val f = future[Unit] { - throw cause - } - f onSuccess { - case _ => - done() - assert(false) - } + val f = future[Unit] { throw cause } + f onSuccess { case _ => done(false) } f onFailure { - case e: ExecutionException if (e.getCause == cause) => - done() - case _ => - done() - assert(false) + case e: ExecutionException if e.getCause == cause => done(true) + case _ => done(false) } } def testOnFailureWhenTimeoutException(): Unit = once { done => - val f = future[Unit] { - throw new TimeoutException() - } - f onSuccess { - case _ => - done() - assert(false) - } + val f = future[Unit] { throw new TimeoutException() } + f onSuccess { case _ => done(false) } f onFailure { - case e: TimeoutException => - done() - case other => - done() - assert(false) + case e: TimeoutException => done(true) + case _ => done(false) } } @@ -151,7 +100,6 @@ trait FutureCallbacks extends TestBase { //testOnFailureWhenSpecialThrowable(7, new InterruptedException) testThatNestedCallbacksDoNotYieldStackOverflow() testOnFailureWhenTimeoutException() - } @@ -162,207 +110,120 @@ trait FutureCombinators extends TestBase { done => val f = future { 5 } val g = f map { x => "result: " + x } - g onSuccess { - case s => - done() - assert(s == "result: 5") - } - g onFailure { - case _ => - done() - assert(false) - } + g onSuccess { case s => done(s == "result: 5") } + g onFailure { case _ => done(false) } } def testMapFailure(): Unit = once { done => - val f = future { - throw new Exception("exception message") - } + val f = future[Unit] { throw new Exception("exception message") } val g = f map { x => "result: " + x } - g onSuccess { - case _ => - done() - assert(false) - } - g onFailure { - case t => - done() - assert(t.getMessage() == "exception message") - } + g onSuccess { case _ => done(false) } + g onFailure { case t => done(t.getMessage() == "exception message") } } def testMapSuccessPF(): Unit = once { done => val f = future { 5 } val g = f map { case r => "result: " + r } - g onSuccess { - case s => - done() - assert(s == "result: 5") - } - g onFailure { - case _ => - done() - assert(false) - } + g onSuccess { case s => done(s == "result: 5") } + g onFailure { case _ => done(false) } } def testTransformSuccess(): Unit = once { done => val f = future { 5 } val g = f.transform(r => "result: " + r, identity) - g onSuccess { - case s => - done() - assert(s == "result: 5") - } - g onFailure { - case _ => - done() - assert(false) - } + g onSuccess { case s => done(s == "result: 5") } + g onFailure { case _ => done(false) } } def testTransformSuccessPF(): Unit = once { done => val f = future { 5 } val g = f.transform( { case r => "result: " + r }, identity) - g onSuccess { - case s => - done() - assert(s == "result: 5") - } - g onFailure { - case _ => - done() - assert(false) - } + g onSuccess { case s => done(s == "result: 5") } + g onFailure { case _ => done(false) } + } + +def testTransformFailure(): Unit = once { + done => + val transformed = new Exception("transformed") + val f = future { throw new Exception("expected") } + val g = f.transform(identity, _ => transformed) + g onSuccess { case _ => done(false) } + g onFailure { case e => done(e eq transformed) } + } + + def testTransformFailurePF(): Unit = once { + done => + val e = new Exception("expected") + val transformed = new Exception("transformed") + val f = future[Unit] { throw e } + val g = f.transform(identity, { case `e` => transformed }) + g onSuccess { case _ => done(false) } + g onFailure { case e => done(e eq transformed) } } def testFoldFailure(): Unit = once { done => - val f = future { - throw new Exception("exception message") - } + val f = future[Unit] { throw new Exception("expected") } val g = f.transform(r => "result: " + r, identity) - g onSuccess { - case _ => - done() - assert(false) - } - g onFailure { - case t => - done() - assert(t.getMessage() == "exception message") - } + g onSuccess { case _ => done(false) } + g onFailure { case t => done(t.getMessage() == "expected") } } def testFlatMapSuccess(): Unit = once { done => val f = future { 5 } val g = f flatMap { _ => future { 10 } } - g onSuccess { - case x => - done() - assert(x == 10) - } - g onFailure { - case _ => - done() - assert(false) - } + g onSuccess { case x => done(x == 10) } + g onFailure { case _ => done(false) } } def testFlatMapFailure(): Unit = once { done => - val f = future { - throw new Exception("exception message") - } + val f = future[Unit] { throw new Exception("expected") } val g = f flatMap { _ => future { 10 } } - g onSuccess { - case _ => - done() - assert(false) - } - g onFailure { - case t => - done() - assert(t.getMessage() == "exception message") - } + g onSuccess { case _ => done(false) } + g onFailure { case t => done(t.getMessage() == "expected") } } def testFilterSuccess(): Unit = once { done => val f = future { 4 } val g = f filter { _ % 2 == 0 } - g onSuccess { - case x: Int => - done() - assert(x == 4) - } - g onFailure { - case _ => - done() - assert(false) - } + g onSuccess { case x: Int => done(x == 4) } + g onFailure { case _ => done(false) } } def testFilterFailure(): Unit = once { done => val f = future { 4 } val g = f filter { _ % 2 == 1 } - g onSuccess { - case x: Int => - done() - assert(false) - } + g onSuccess { case x: Int => done(false) } g onFailure { - case e: NoSuchElementException => - done() - assert(true) - case _ => - done() - assert(false) + case e: NoSuchElementException => done(true) + case _ => done(false) } } def testCollectSuccess(): Unit = once { done => val f = future { -5 } - val g = f collect { - case x if x < 0 => -x - } - g onSuccess { - case x: Int => - done() - assert(x == 5) - } - g onFailure { - case _ => - done() - assert(false) - } + val g = f collect { case x if x < 0 => -x } + g onSuccess { case x: Int => done(x == 5) } + g onFailure { case _ => done(false) } } def testCollectFailure(): Unit = once { done => val f = future { -5 } - val g = f collect { - case x if x > 0 => x * 2 - } - g onSuccess { - case _ => - done() - assert(false) - } + val g = f collect { case x if x > 0 => x * 2 } + g onSuccess { case _ => done(false) } g onFailure { - case e: NoSuchElementException => - done() - assert(true) - case _ => - done() - assert(false) + case e: NoSuchElementException => done(true) + case _ => done(false) } } @@ -376,16 +237,8 @@ trait FutureCombinators extends TestBase { f foreach { x => p.success(x * 2) } val g = p.future - g.onSuccess { - case res: Int => - done() - assert(res == 10) - } - g.onFailure { - case _ => - done() - assert(false) - } + g.onSuccess { case res: Int => done(res == 10) } + g.onFailure { case _ => done(false) } } def testForeachFailure(): Unit = once { @@ -396,16 +249,8 @@ trait FutureCombinators extends TestBase { f onFailure { case _ => p.failure(new Exception) } val g = p.future - g.onSuccess { - case _ => - done() - assert(false) - } - g.onFailure { - case _ => - done() - assert(true) - } + g.onSuccess { case _ => done(false) } + g.onFailure { case _ => done(true) } } def testRecoverSuccess(): Unit = once { @@ -415,18 +260,9 @@ trait FutureCombinators extends TestBase { throw cause } recover { case re: RuntimeException => - "recovered" - } - f onSuccess { - case x => - done() - assert(x == "recovered") - } - f onFailure { case any => - done() - assert(false) - } - f + "recovered" } + f onSuccess { case x => done(x == "recovered") } + f onFailure { case any => done(false) } } def testRecoverFailure(): Unit = once { @@ -437,15 +273,8 @@ trait FutureCombinators extends TestBase { } recover { case te: TimeoutException => "timeout" } - f onSuccess { - case x => - done() - assert(false) - } - f onFailure { case any => - done() - assert(any == cause) - } + f onSuccess { case _ => done(false) } + f onFailure { case any => done(any == cause) } } def testRecoverWithSuccess(): Unit = once { @@ -457,15 +286,8 @@ trait FutureCombinators extends TestBase { case re: RuntimeException => future { "recovered" } } - f onSuccess { - case x => - done() - assert(x == "recovered") - } - f onFailure { case any => - done() - assert(false) - } + f onSuccess { case x => done(x == "recovered") } + f onFailure { case any => done(false) } } def testRecoverWithFailure(): Unit = once { @@ -477,15 +299,8 @@ trait FutureCombinators extends TestBase { case te: TimeoutException => future { "timeout" } } - f onSuccess { - case x => - done() - assert(false) - } - f onFailure { case any => - done() - assert(any == cause) - } + f onSuccess { case x => done(false) } + f onFailure { case any => done(any == cause) } } def testZipSuccess(): Unit = once { @@ -493,52 +308,28 @@ trait FutureCombinators extends TestBase { val f = future { 5 } val g = future { 6 } val h = f zip g - h onSuccess { - case (l: Int, r: Int) => - done() - assert(l+r == 11) - } - h onFailure { - case _ => - done() - assert(false) - } + h onSuccess { case (l: Int, r: Int) => done(l+r == 11) } + h onFailure { case _ => done(false) } } def testZipFailureLeft(): Unit = once { done => - val cause = new Exception("exception message") + val cause = new Exception("expected") val f = future { throw cause } val g = future { 6 } val h = f zip g - h onSuccess { - case _ => - done() - assert(false) - } - h onFailure { - case e: Exception => - done() - assert(e.getMessage == "exception message") - } + h onSuccess { case _ => done(false) } + h onFailure { case e: Exception => done(e.getMessage == "expected") } } def testZipFailureRight(): Unit = once { done => - val cause = new Exception("exception message") + val cause = new Exception("expected") val f = future { 5 } val g = future { throw cause } val h = f zip g - h onSuccess { - case _ => - done() - assert(false) - } - h onFailure { - case e: Exception => - done() - assert(e.getMessage == "exception message") - } + h onSuccess { case _ => done(false) } + h onFailure { case e: Exception => done(e.getMessage == "expected") } } def testFallbackTo(): Unit = once { @@ -546,17 +337,8 @@ trait FutureCombinators extends TestBase { val f = future { sys.error("failed") } val g = future { 5 } val h = f fallbackTo g - - h onSuccess { - case x: Int => - done() - assert(x == 5) - } - h onFailure { - case _ => - done() - assert(false) - } + h onSuccess { case x: Int => done(x == 5) } + h onFailure { case _ => done(false) } } def testFallbackToFailure(): Unit = once { @@ -566,16 +348,8 @@ trait FutureCombinators extends TestBase { val g = future { throw cause } val h = f fallbackTo g - h onSuccess { - case _ => - done() - assert(false) - } - h onFailure { - case e: Exception => - done() - assert(e == cause) - } + h onSuccess { case _ => done(false) } + h onFailure { case e => done(e eq cause) } } testMapSuccess() @@ -597,6 +371,8 @@ trait FutureCombinators extends TestBase { testZipFailureRight() testFallbackTo() testFallbackToFailure() + testTransformSuccess() + testTransformSuccessPF() } @@ -606,40 +382,26 @@ trait FutureProjections extends TestBase { def testFailedFailureOnComplete(): Unit = once { done => val cause = new RuntimeException - val f = future { - throw cause - } + val f = future { throw cause } f.failed onComplete { - case Success(t) => - assert(t == cause) - done() - case Failure(t) => - assert(false) + case Success(t) => done(t == cause) + case Failure(t) => done(false) } } def testFailedFailureOnSuccess(): Unit = once { done => val cause = new RuntimeException - val f = future { - throw cause - } - f.failed onSuccess { - case t => - assert(t == cause) - done() - } + val f = future { throw cause } + f.failed onSuccess { case t => done(t == cause) } } def testFailedSuccessOnComplete(): Unit = once { done => val f = future { 0 } f.failed onComplete { - case Success(t) => - assert(false) - case Failure(t) => - assert(t.isInstanceOf[NoSuchElementException]) - done() + case Failure(_: NoSuchElementException) => done(true) + case _ => done(false) } } @@ -647,19 +409,17 @@ trait FutureProjections extends TestBase { done => val f = future { 0 } f.failed onFailure { - case nsee: NoSuchElementException => - done() + case e: NoSuchElementException => done(true) + case _ => done(false) } + f.failed onSuccess { case _ => done(false) } } def testFailedFailureAwait(): Unit = once { done => val cause = new RuntimeException - val f = future { - throw cause - } - assert(Await.result(f.failed, Duration(500, "ms")) == cause) - done() + val f = future { throw cause } + done(Await.result(f.failed, Duration(500, "ms")) == cause) } def testFailedSuccessAwait(): Unit = once { @@ -667,9 +427,10 @@ trait FutureProjections extends TestBase { val f = future { 0 } try { Await.result(f.failed, Duration(500, "ms")) - assert(false) + done(false) } catch { - case nsee: NoSuchElementException => done() + case nsee: NoSuchElementException => done(true) + case _: Throwable => done(false) } } @@ -682,8 +443,8 @@ trait FutureProjections extends TestBase { Await.ready(f, Duration.Zero) Await.ready(f, Duration(500, "ms")) Await.ready(f, Duration.Inf) - done() - } onFailure { case x => throw x } + done(true) + } onFailure { case x => done(throw x) } } def testAwaitNegativeDuration(): Unit = once { done => @@ -692,8 +453,8 @@ trait FutureProjections extends TestBase { intercept[TimeoutException] { Await.ready(f, Duration.Zero) } intercept[TimeoutException] { Await.ready(f, Duration.MinusInf) } intercept[TimeoutException] { Await.ready(f, Duration(-500, "ms")) } - done() - } onFailure { case x => throw x } + done(true) + } onFailure { case x => done(throw x) } } testFailedFailureOnComplete() @@ -704,7 +465,6 @@ trait FutureProjections extends TestBase { testFailedSuccessAwait() testAwaitPositiveDuration() testAwaitNegativeDuration() - } @@ -714,33 +474,25 @@ trait Blocking extends TestBase { def testAwaitSuccess(): Unit = once { done => val f = future { 0 } - Await.result(f, Duration(500, "ms")) - done() + done(Await.result(f, Duration(500, "ms")) == 0) } def testAwaitFailure(): Unit = once { done => val cause = new RuntimeException - val f = future { - throw cause - } + val f = future { throw cause } try { Await.result(f, Duration(500, "ms")) - assert(false) + done(false) } catch { - case t: Throwable => - assert(t == cause) - done() + case t: Throwable => done(t == cause) } } def testFQCNForAwaitAPI(): Unit = once { done => - - assert(classOf[CanAwait].getName == "scala.concurrent.CanAwait") - assert(Await.getClass.getName == "scala.concurrent.Await") - - done() + done(classOf[CanAwait].getName == "scala.concurrent.CanAwait" && + Await.getClass.getName == "scala.concurrent.Await") } testAwaitSuccess() @@ -813,22 +565,26 @@ trait Promises extends TestBase { val p = promise[Int]() val f = p.future - f onSuccess { - case x => - done() - assert(x == 5) - } - f onFailure { - case any => - done() - assert(false) - } + f onSuccess { case x => done(x == 5) } + f onFailure { case any => done(false) } p.success(5) } - testSuccess() + def testFailure(): Unit = once { + done => + val e = new Exception("expected") + val p = promise[Int]() + val f = p.future + + f onSuccess { case x => done(false) } + f onFailure { case any => done(any eq e) } + + p.failure(e) + } + testSuccess() + testFailure() } @@ -888,11 +644,11 @@ trait CustomExecutionContext extends TestBase { val count = countExecs { implicit ec => blocking { once { done => - val f = future({ assertNoEC() })(defaultEC) + val f = future(assertNoEC())(defaultEC) f onSuccess { case _ => assertEC() - done() + done(true) } assertNoEC() } @@ -911,7 +667,7 @@ trait CustomExecutionContext extends TestBase { f onSuccess { case _ => assertEC() - done() + done(true) } } } @@ -935,15 +691,10 @@ trait CustomExecutionContext extends TestBase { Promise.successful(x + 1).future.map(addOne).map(addOne) } onComplete { case Failure(t) => - try { - throw new AssertionError("error in test: " + t.getMessage, t) - } finally { - done() - } + done(throw new AssertionError("error in test: " + t.getMessage, t)) case Success(x) => assertEC() - assert(x == 14) - done() + done(x == 14) } assertNoEC() } @@ -999,21 +750,14 @@ trait ExecutionContextPrepare extends TestBase { done => theLocal.set("secret") val fut = future { 42 } - fut onComplete { - case _ => - assert(theLocal.get == "secret") - done() - } + fut onComplete { case _ => done(theLocal.get == "secret") } } def testMap(): Unit = once { done => theLocal.set("secret2") val fut = future { 42 } - fut map { x => - assert(theLocal.get == "secret2") - done() - } + fut map { x => done(theLocal.get == "secret2") } } testOnComplete() diff --git a/test/files/lib/.gitignore b/test/files/lib/.gitignore new file mode 100644 index 0000000000..b4ac0b8789 --- /dev/null +++ b/test/files/lib/.gitignore @@ -0,0 +1,8 @@ +annotations.jar +enums.jar +genericNest.jar +javac-artifacts.jar +jsoup-1.3.1.jar +methvsfield.jar +nest.jar +scalacheck.jar diff --git a/test/files/neg/case-collision.flags b/test/files/neg/case-collision.flags index 85d8eb2ba2..14c1069dee 100644 --- a/test/files/neg/case-collision.flags +++ b/test/files/neg/case-collision.flags @@ -1 +1 @@ --Xfatal-warnings +-Ybackend:GenASM -Xfatal-warnings diff --git a/test/files/neg/case-collision2.check b/test/files/neg/case-collision2.check new file mode 100644 index 0000000000..b8481f46bb --- /dev/null +++ b/test/files/neg/case-collision2.check @@ -0,0 +1,12 @@ +case-collision2.scala:5: warning: Class foo.BIPPY differs only in case from foo.Bippy. Such classes will overwrite one another on case-insensitive filesystems. +class BIPPY + ^ +case-collision2.scala:8: warning: Class foo.DINGO$ differs only in case from foo.Dingo$. Such classes will overwrite one another on case-insensitive filesystems. +object DINGO + ^ +case-collision2.scala:11: warning: Class foo.HyRaX$ differs only in case from foo.Hyrax$. Such classes will overwrite one another on case-insensitive filesystems. +object HyRaX + ^ +error: No warnings can be incurred under -Xfatal-warnings. +three warnings found +one error found diff --git a/test/files/neg/case-collision2.flags b/test/files/neg/case-collision2.flags new file mode 100644 index 0000000000..5bfa9da5c5 --- /dev/null +++ b/test/files/neg/case-collision2.flags @@ -0,0 +1 @@ +-Ynooptimize -Ybackend:GenBCode -Xfatal-warnings diff --git a/test/files/neg/case-collision2.scala b/test/files/neg/case-collision2.scala new file mode 100644 index 0000000000..924e33005a --- /dev/null +++ b/test/files/neg/case-collision2.scala @@ -0,0 +1,12 @@ +package foo + +class Bippy + +class BIPPY + +object Dingo +object DINGO + +case class Hyrax() +object HyRaX + diff --git a/test/files/neg/macro-quasiquotes.check b/test/files/neg/macro-quasiquotes.check new file mode 100644 index 0000000000..a2d48723b5 --- /dev/null +++ b/test/files/neg/macro-quasiquotes.check @@ -0,0 +1,7 @@ +Macros_1.scala:14: error: macro implementation has wrong shape: + required: (x: Impls.this.c.Expr[Int]): Impls.this.c.Expr[Any] + found : (x: Impls.this.c.universe.Block): Impls.this.c.universe.Apply +type mismatch for parameter x: Impls.this.c.Expr[Int] does not conform to Impls.this.c.universe.Block + def m3(x: Int) = macro Impls.impl3 + ^ +one error found diff --git a/test/files/neg/macro-quasiquotes/Macros_1.scala b/test/files/neg/macro-quasiquotes/Macros_1.scala new file mode 100644 index 0000000000..17c1034720 --- /dev/null +++ b/test/files/neg/macro-quasiquotes/Macros_1.scala @@ -0,0 +1,15 @@ +import language.experimental.macros +import scala.reflect.macros.Macro + +trait Impls extends Macro { + import c.universe._ + def impl1(x: Expr[Int]) = q"println(x)" + def impl2(x: Tree) = q"println(x)" + def impl3(x: Block) = q"println(x)" +} + +object Macros { + def m1(x: Int) = macro Impls.impl1 + def m2(x: Int) = macro Impls.impl2 + def m3(x: Int) = macro Impls.impl3 +}
\ No newline at end of file diff --git a/test/files/neg/macro-quasiquotes/Test_2.scala b/test/files/neg/macro-quasiquotes/Test_2.scala new file mode 100644 index 0000000000..c7b8948d79 --- /dev/null +++ b/test/files/neg/macro-quasiquotes/Test_2.scala @@ -0,0 +1,5 @@ +object Test extends App { + Macros.m1 + Macros.m2 + Macros.m3 +} diff --git a/test/files/neg/names-defaults-neg.check b/test/files/neg/names-defaults-neg.check index f6bd703e1f..cdc12c2490 100644 --- a/test/files/neg/names-defaults-neg.check +++ b/test/files/neg/names-defaults-neg.check @@ -125,9 +125,12 @@ names-defaults-neg.scala:134: error: missing parameter type for expanded functio names-defaults-neg.scala:135: error: parameter 'a' is already specified at parameter position 1 val taf3 = testAnnFun(b = _: String, a = get(8)) ^ -names-defaults-neg.scala:136: error: wrong number of parameters; expected = 2 +names-defaults-neg.scala:136: error: missing parameter type for expanded function ((x$3) => testAnnFun(x$3, ((x$4) => b = x$4))) val taf4: (Int, String) => Unit = testAnnFun(_, b = _) - ^ + ^ +names-defaults-neg.scala:136: error: missing parameter type for expanded function ((x$4) => b = x$4) + val taf4: (Int, String) => Unit = testAnnFun(_, b = _) + ^ names-defaults-neg.scala:144: error: variable definition needs type because 'x' is used as a named argument in its body. def t3 { var x = t.f(x = 1) } ^ @@ -165,4 +168,4 @@ names-defaults-neg.scala:180: error: reference to x is ambiguous; it is both a m class u18 { var x: Int = u.f(x = 1) } ^ four warnings found -41 errors found +42 errors found diff --git a/test/files/neg/t1181.check b/test/files/neg/t1181.check index 3724752a85..13b73d5381 100644 --- a/test/files/neg/t1181.check +++ b/test/files/neg/t1181.check @@ -1,8 +1,10 @@ t1181.scala:8: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses case (Nil, Nil) => map ^ -t1181.scala:9: error: missing parameter type +t1181.scala:9: error: type mismatch; + found : scala.collection.immutable.Map[Symbol,Symbol] + required: Symbol _ => buildMap(map.updated(keyList.head, valueList.head), keyList.tail, valueList.tail) - ^ + ^ one warning found one error found diff --git a/test/files/neg/t556.check b/test/files/neg/t556.check index c278e13991..5135dc92ef 100644 --- a/test/files/neg/t556.check +++ b/test/files/neg/t556.check @@ -1,4 +1,4 @@ -t556.scala:3: error: wrong number of parameters; expected = 1 +t556.scala:3: error: missing parameter type def g:Int = f((x,y)=>x) - ^ + ^ one error found diff --git a/test/files/neg/t6574.check b/test/files/neg/t6574.check new file mode 100644 index 0000000000..c67b4ed804 --- /dev/null +++ b/test/files/neg/t6574.check @@ -0,0 +1,7 @@ +t6574.scala:4: error: could not optimize @tailrec annotated method notTailPos$extension: it contains a recursive call not in tail position + println("tail") + ^ +t6574.scala:8: error: could not optimize @tailrec annotated method differentTypeArgs$extension: it is called recursively with different type arguments + {(); new Bad[String, Unit](0)}.differentTypeArgs + ^ +two errors found diff --git a/test/files/neg/t6574.scala b/test/files/neg/t6574.scala new file mode 100644 index 0000000000..bba97ad62e --- /dev/null +++ b/test/files/neg/t6574.scala @@ -0,0 +1,10 @@ +class Bad[X, Y](val v: Int) extends AnyVal { + @annotation.tailrec final def notTailPos[Z](a: Int)(b: String) { + this.notTailPos[Z](a)(b) + println("tail") + } + + @annotation.tailrec final def differentTypeArgs { + {(); new Bad[String, Unit](0)}.differentTypeArgs + } +} diff --git a/test/files/neg/valueclasses-impl-restrictions.check b/test/files/neg/valueclasses-impl-restrictions.check index 63924493aa..0af9173f74 100644 --- a/test/files/neg/valueclasses-impl-restrictions.check +++ b/test/files/neg/valueclasses-impl-restrictions.check @@ -6,12 +6,8 @@ valueclasses-impl-restrictions.scala:9: error: implementation restriction: neste This restriction is planned to be removed in subsequent releases. trait I2 { ^ -valueclasses-impl-restrictions.scala:15: error: implementation restriction: nested class is not allowed in value class -This restriction is planned to be removed in subsequent releases. - val i2 = new I2 { val q = x.s } - ^ -valueclasses-impl-restrictions.scala:21: error: implementation restriction: nested class is not allowed in value class +valueclasses-impl-restrictions.scala:23: error: implementation restriction: nested class is not allowed in value class This restriction is planned to be removed in subsequent releases. private[this] class I2(val q: String) ^ -four errors found +three errors found diff --git a/test/files/neg/valueclasses-impl-restrictions.scala b/test/files/neg/valueclasses-impl-restrictions.scala index 137f3f854c..f0577a94aa 100644 --- a/test/files/neg/valueclasses-impl-restrictions.scala +++ b/test/files/neg/valueclasses-impl-restrictions.scala @@ -12,8 +12,10 @@ class X1(val s: String) extends AnyVal { } def y(x: X1) = { - val i2 = new I2 { val q = x.s } + val i2 = new I2 { val q = x.s } // allowed as of SI-7571 i2.z + + { case x => x } : PartialFunction[Int, Int] // allowed } } diff --git a/test/files/pos/SI-7638.scala b/test/files/pos/SI-7638.scala new file mode 100644 index 0000000000..da16e0bd2c --- /dev/null +++ b/test/files/pos/SI-7638.scala @@ -0,0 +1,51 @@ +package miniboxing.tests.compile + +trait Ordering[@specialized(Int) A] { + def eqv(x: Array[A], y: Array[A]): Boolean = false +} + +trait ArrayVectorOrder[@specialized(Int) A] extends Ordering[A] { + override def eqv(x: Array[A], y: Array[A]): Boolean = super.eqv(x, y) +} + +object vectorOrder { + implicit def arrayOrder[@specialized(Int) A]() = + /* + * Before applying patch: + * + * while compiling: SI-7638.scala + * during phase: mixin + * library version: version 2.10.3-20130625-164027-d22e8d282c + * compiler version: version 2.10.3-20130627-153946-54cb6af7db + * reconstructed args: + * + * last tree to typer: TypeTree(class Array) + * symbol: class Array in package scala (flags: final) + * symbol definition: final class Array[T >: ? <: ?] extends Object + * tpe: Array[Int] + * symbol owners: class Array -> package scala + * context owners: anonymous class anon$1 -> package compile + * + * == Expanded type of tree == + * + * TypeRef( + * TypeSymbol(final class Array[T >: ? <: ?] extends Object) + * args = List(TypeRef(TypeSymbol(final abstract class Int extends ))) + * ) + * + * unhandled exception while transforming SI-7638.scala + * error: uncaught exception during compilation: java.lang.UnsupportedOperationException + * error: java.lang.UnsupportedOperationException: tail of empty list + * at scala.collection.immutable.Nil$.tail(List.scala:339) + * at scala.collection.immutable.Nil$.tail(List.scala:334) + * at scala.tools.nsc.transform.Mixin$$anonfun$scala$tools$nsc$transform$Mixin$$rebindSuper$1.apply(Mixin.scala:123) + * at scala.tools.nsc.transform.Mixin$$anonfun$scala$tools$nsc$transform$Mixin$$rebindSuper$1.apply(Mixin.scala:122) + * at scala.reflect.internal.SymbolTable.atPhase(SymbolTable.scala:207) + * at scala.reflect.internal.SymbolTable.afterPhase(SymbolTable.scala:216) + * at scala.tools.nsc.Global.afterPickler(Global.scala:1104) + * at scala.tools.nsc.transform.Mixin.scala$tools$nsc$transform$Mixin$$rebindSuper(Mixin.scala:122) + * at scala.tools.nsc.transform.Mixin$$anonfun$scala$tools$nsc$transform$Mixin$$mixinTraitMembers$1$1.apply(Mixin.scala:339) + * at scala.tools.nsc.transform.Mixin$$anonfun$scala$tools$nsc$transform$Mixin$$mixinTraitMembers$1$1.apply(Mixin.scala:292) + */ + new ArrayVectorOrder[A] { } +} diff --git a/test/files/pos/t6221.scala b/test/files/pos/t6221.scala new file mode 100644 index 0000000000..dd7776f596 --- /dev/null +++ b/test/files/pos/t6221.scala @@ -0,0 +1,29 @@ +class MyFunc[-A, +B] extends (A => B) { def apply(x: A): B = ??? } + +class MyCollection[A] { + def map[B](f: MyFunc[A, B]): MyCollection[B] = new MyCollection[B] +} + +class OtherFunc[-A, +B] {} + +object Test { + implicit def functionToMyFunc[A, B](f: A => B): MyFunc[A, B] = new MyFunc + + implicit def otherFuncToMyFunc[A, B](f: OtherFunc[A, B]): MyFunc[A, B] = new MyFunc + + def main(args: Array[String]) { + val col = new MyCollection[Int] + + // Doesn't compile: error: missing parameter type for expanded function ((x$1) => x$1.toString) + println(col.map(_.toString)) + + // Doesn't compile: error: missing parameter type + println(col.map(x => x.toString)) + + // Does compile + println(col.map((x: Int) => x.toString)) + + // Does compile (even though type params of OtherFunc not given) + println(col.map(new OtherFunc)) + } +}
\ No newline at end of file diff --git a/test/files/pos/t6574.scala b/test/files/pos/t6574.scala new file mode 100644 index 0000000000..59c1701eb4 --- /dev/null +++ b/test/files/pos/t6574.scala @@ -0,0 +1,19 @@ +class Bad[X, Y](val v: Int) extends AnyVal { + def vv = v + @annotation.tailrec final def foo[Z](a: Int)(b: String) { + this.foo[Z](a)(b) + } + + @annotation.tailrec final def differentReceiver { + {(); new Bad[X, Y](0)}.differentReceiver + } + + @annotation.tailrec final def dependent[Z](a: Int)(b: String): b.type = { + this.dependent[Z](a)(b) + } +} + +class HK[M[_]](val v: Int) extends AnyVal { + def hk[N[_]]: Unit = if (false) hk[M] else () +} + diff --git a/test/files/pos/t7591/Demo.scala b/test/files/pos/t7591/Demo.scala new file mode 100644 index 0000000000..696d53585b --- /dev/null +++ b/test/files/pos/t7591/Demo.scala @@ -0,0 +1,83 @@ +/* NEST (New Scala Test) + * Copyright 2007-2013 LAMP/EPFL + * @author Paul Phillips + */ + +import scala.tools.cmd._ + +/** A sample command specification for illustrative purposes. + * First take advantage of the meta-options: + * + * // this command creates an executable runner script "demo" + * % scala scala.tools.cmd.Demo --self-update demo + * + * // this one creates and sources a completion file - note backticks + * % `./demo --bash` + * + * // and now you have a runner with working completion + * % ./demo --<tab> + * --action --defint --int + * --bash --defstr --str + * --defenv --self-update --unary + * + * The normal option configuration is plausibly self-explanatory. + */ +trait DemoSpec extends Spec with Meta.StdOpts with Interpolation { + lazy val referenceSpec = DemoSpec + lazy val programInfo = Spec.Info("demo", "Usage: demo [<options>]", "scala.tools.cmd.Demo") + + help("""Usage: demo [<options>]""") + heading("Unary options:") + + val optIsUnary = "unary" / "a unary option" --? ; + ("action" / "a body which may be run") --> println("Hello, I am the --action body.") + + heading("Binary options:") + val optopt = "str" / "an optional String" --| + val optoptInt = ("int" / "an optional Int") . --^[Int] + val optEnv = "defenv" / "an optional String" defaultToEnv "PATH" + val optDefault = "defstr" / "an optional String" defaultTo "default" + val optDefaultInt = "defint" / "an optional Int" defaultTo -1 + val optExpand = "alias" / "an option which expands" expandTo ("--int", "15") +} + +object DemoSpec extends DemoSpec with Property { + lazy val propMapper = new PropertyMapper(DemoSpec) + + type ThisCommandLine = SpecCommandLine + def creator(args: List[String]) = + new SpecCommandLine(args) { + override def errorFn(msg: String) = { println("Error: " + msg) ; sys.exit(0) } + } +} + +class Demo(args: List[String]) extends { + val parsed = DemoSpec(args: _*) +} with DemoSpec with Instance { + import java.lang.reflect._ + + def helpMsg = DemoSpec.helpMsg + def demoSpecMethods = this.getClass.getMethods.toList + private def isDemo(m: Method) = (m.getName startsWith "opt") && !(m.getName contains "$") && (m.getParameterTypes.isEmpty) + + def demoString(ms: List[Method]) = { + val longest = ms map (_.getName.length) max + val formatStr = " %-" + longest + "s: %s" + val xs = ms map (m => formatStr.format(m.getName, m.invoke(this))) + + xs mkString ("Demo(\n ", "\n ", "\n)\n") + } + + override def toString = demoString(demoSpecMethods filter isDemo) +} + +object Demo { + def main(args: Array[String]): Unit = { + val runner = new Demo(args.toList) + + if (args.isEmpty) + println(runner.helpMsg) + + println(runner) + } +} diff --git a/test/files/run/macro-quasiquotes.check b/test/files/run/macro-quasiquotes.check new file mode 100644 index 0000000000..94ebaf9001 --- /dev/null +++ b/test/files/run/macro-quasiquotes.check @@ -0,0 +1,4 @@ +1 +2 +3 +4 diff --git a/test/files/run/macro-quasiquotes/Macros_1.scala b/test/files/run/macro-quasiquotes/Macros_1.scala new file mode 100644 index 0000000000..b64eec8743 --- /dev/null +++ b/test/files/run/macro-quasiquotes/Macros_1.scala @@ -0,0 +1,15 @@ +import language.experimental.macros +import scala.reflect.macros.Macro + +trait Impls extends Macro { + import c.universe._ + def impl1 = q"println(1)" + def impl2 = q"{ println(2); println(3) }" + def impl3 = q"4" +} + +object Macros { + def m1 = macro Impls.impl1 + def m2 = macro Impls.impl2 + def m3 = macro Impls.impl3 +}
\ No newline at end of file diff --git a/test/files/run/macro-quasiquotes/Test_2.scala b/test/files/run/macro-quasiquotes/Test_2.scala new file mode 100644 index 0000000000..4be193938f --- /dev/null +++ b/test/files/run/macro-quasiquotes/Test_2.scala @@ -0,0 +1,5 @@ +object Test extends App { + Macros.m1 + Macros.m2 + println(Macros.m3) +} diff --git a/test/files/run/t4594-repl-settings.scala b/test/files/run/t4594-repl-settings.scala new file mode 100644 index 0000000000..d2335460e5 --- /dev/null +++ b/test/files/run/t4594-repl-settings.scala @@ -0,0 +1,26 @@ + +import scala.tools.partest.SessionTest + +// Detected repl transcript paste: ctrl-D to finish. +object Test extends SessionTest { + def session = +""" |Type in expressions to have them evaluated. + |Type :help for more information. + | + |scala> @deprecated(message="Please don't do that.", since="Time began.") def depp = "john" + |depp: String + | + |scala> def a = depp + |warning: there were 1 deprecation warning(s); re-run with -deprecation for details + |a: String + | + |scala> :settings +deprecation + | + |scala> def b = depp + |<console>:8: warning: method depp is deprecated: Please don't do that. + | def b = depp + | ^ + |b: String + | + |scala> """ +} diff --git a/test/files/run/t6221.check b/test/files/run/t6221.check new file mode 100644 index 0000000000..aa1bdd0e6e --- /dev/null +++ b/test/files/run/t6221.check @@ -0,0 +1 @@ +((x) => x.$percent(2).$eq$eq(0)) diff --git a/test/files/run/t6221/Macros_1.scala b/test/files/run/t6221/Macros_1.scala new file mode 100644 index 0000000000..c9500626d8 --- /dev/null +++ b/test/files/run/t6221/Macros_1.scala @@ -0,0 +1,22 @@ +import language.experimental.macros +import language.implicitConversions +import scala.reflect.macros.Context +import scala.reflect.runtime.universe.Tree + +class ReflectiveClosure[A, B](val tree: Tree, fn: A => B) extends (A => B) { + def apply(x: A) = fn(x) +} + +object ReflectiveClosure { + implicit def reflectClosure[A, B](f: A => B): ReflectiveClosure[A, B] = macro Macros.reflectiveClosureImpl[A, B] +} + +object Macros { + def reflectiveClosureImpl[A, B](c: Context)(f: c.Expr[A => B]): c.Expr[ReflectiveClosure[A, B]] = { + import c.universe._ + val u = treeBuild.mkRuntimeUniverseRef + val m = EmptyTree + val tree = c.Expr[scala.reflect.runtime.universe.Tree](Select(c.reifyTree(u, m, f.tree), newTermName("tree"))) + c.universe.reify(new ReflectiveClosure(tree.splice, f.splice)) + } +} diff --git a/test/files/run/t6221/Test_2.scala b/test/files/run/t6221/Test_2.scala new file mode 100644 index 0000000000..9f6b2280a7 --- /dev/null +++ b/test/files/run/t6221/Test_2.scala @@ -0,0 +1,10 @@ +object Test extends App { + implicit class PimpedList[T](val list: List[T]) { + def query(predicate: ReflectiveClosure[T, Boolean]): List[T] = { + println(predicate.tree) + list filter predicate + } + } + + List(1, 2, 3).query(x => x % 2 == 0) +}
\ No newline at end of file diff --git a/test/files/run/t6331.scala b/test/files/run/t6331.scala index 5ac627a8ea..d9d46f10ea 100644 --- a/test/files/run/t6331.scala +++ b/test/files/run/t6331.scala @@ -1,9 +1,4 @@ -import scala.tools.partest._ -import java.io._ -import scala.tools.nsc._ -import scala.tools.cmd.CommandLineParser -import scala.tools.nsc.{Global, Settings, CompilerCommand} -import scala.tools.nsc.reporters.ConsoleReporter +import scala.tools.partest.DirectTest // Test of Constant#equals, which must must account for floating point intricacies. object Test extends DirectTest { diff --git a/test/files/run/t6331b.scala b/test/files/run/t6331b.scala index c567455c5c..3e09965ee8 100644 --- a/test/files/run/t6331b.scala +++ b/test/files/run/t6331b.scala @@ -1,12 +1,5 @@ -import scala.tools.partest._ -import java.io._ -import scala.tools.nsc._ -import scala.tools.cmd.CommandLineParser -import scala.tools.nsc.{Global, Settings, CompilerCommand} -import scala.tools.nsc.reporters.ConsoleReporter - import scala.tools.partest.trace -import scala.util.control.Exception._ +import scala.util.control.Exception.allCatch object Test extends App { diff --git a/test/files/run/t6574b.check b/test/files/run/t6574b.check new file mode 100644 index 0000000000..e10fa4f810 --- /dev/null +++ b/test/files/run/t6574b.check @@ -0,0 +1 @@ +List(5, 4, 3, 2, 1) diff --git a/test/files/run/t6574b.scala b/test/files/run/t6574b.scala new file mode 100644 index 0000000000..df329a31ca --- /dev/null +++ b/test/files/run/t6574b.scala @@ -0,0 +1,7 @@ +object Test extends App { + implicit class AnyOps(val i: Int) extends AnyVal { + private def parentsOf(x: Int): List[Int] = if (x == 0) Nil else x :: parentsOf(x - 1) + def parents: List[Int] = parentsOf(i) + } + println((5).parents) +} diff --git a/test/files/run/t7008-scala-defined.flags b/test/files/run/t7008-scala-defined.flags new file mode 100644 index 0000000000..49f2d2c4c8 --- /dev/null +++ b/test/files/run/t7008-scala-defined.flags @@ -0,0 +1 @@ +-Ybackend:GenASM diff --git a/test/files/run/t7271.scala b/test/files/run/t7271.scala index 55c388b7f5..69d5ea377e 100644 --- a/test/files/run/t7271.scala +++ b/test/files/run/t7271.scala @@ -1,5 +1,4 @@ import scala.tools.partest._ -import java.io._ import scala.tools.nsc._ import scala.tools.cmd.CommandLineParser import scala.tools.nsc.{Global, Settings, CompilerCommand} diff --git a/test/files/run/t7439/Test_2.scala b/test/files/run/t7439/Test_2.scala index 3ebbcfe753..ce9b907145 100644 --- a/test/files/run/t7439/Test_2.scala +++ b/test/files/run/t7439/Test_2.scala @@ -23,7 +23,8 @@ object Test extends StoreReporterDirectTest { val a1Class = new File(testOutput.path, "A_1.class") assert(a1Class.exists) assert(a1Class.delete()) - println(s"Recompiling after deleting $a1Class") + // testIdent normalizes to separate names using '/' regardless of platform, drops all but last two parts + println(s"Recompiling after deleting ${a1Class.testIdent}") // bad symbolic reference error expected (but no stack trace!) compileCode(C) diff --git a/test/files/run/t7571.scala b/test/files/run/t7571.scala new file mode 100644 index 0000000000..00b9695168 --- /dev/null +++ b/test/files/run/t7571.scala @@ -0,0 +1,12 @@ +class Foo(val a: Int) extends AnyVal { + def foo = { {case x => x + a}: PartialFunction[Int, Int]} + + def bar = (new {}).toString +} + +object Test extends App { + val x = new Foo(1).foo.apply(2) + assert(x == 3, x) + val s = new Foo(1).bar + assert(s.nonEmpty, s) +} diff --git a/test/files/run/t7582-private-within.check b/test/files/run/t7582-private-within.check new file mode 100644 index 0000000000..b2743ffa06 --- /dev/null +++ b/test/files/run/t7582-private-within.check @@ -0,0 +1,12 @@ +private[package pack] class JavaPackagePrivate +private[package pack] module JavaPackagePrivate +private[package pack] module class JavaPackagePrivate +private[package pack] field field +private[package pack] primary constructor <init> +private[package pack] method meth +private[package pack] field staticField +private[package pack] method staticMeth +private[package pack] method <clinit> +private[package pack] field staticField +private[package pack] method staticMeth +private[package pack] method <clinit> diff --git a/test/files/run/t7582-private-within/JavaPackagePrivate.java b/test/files/run/t7582-private-within/JavaPackagePrivate.java new file mode 100644 index 0000000000..672d19b57e --- /dev/null +++ b/test/files/run/t7582-private-within/JavaPackagePrivate.java @@ -0,0 +1,8 @@ +package pack; + +class JavaPackagePrivate { + int field = 0; + static int staticField = 0; + void meth() { } + static void staticMeth() { } +} diff --git a/test/files/run/t7582-private-within/Test.scala b/test/files/run/t7582-private-within/Test.scala new file mode 100644 index 0000000000..3d581f063b --- /dev/null +++ b/test/files/run/t7582-private-within/Test.scala @@ -0,0 +1,22 @@ +import scala.tools.partest.DirectTest + +// Testing that the `privateWithin` field is correctly populated on all +// the related symbols (e.g. module class) under separate compilation. +object Test extends DirectTest { + def code = ??? + + def show(): Unit = { + val classpath = List(sys.props("partest.lib"), testOutput.path) mkString sys.props("path.separator") + val global = newCompiler("-usejavacp", "-cp", classpath, "-d", testOutput.path) + import global._ + withRun(global) { _ => + def check(sym: Symbol) = { + sym.initialize + println(f"${sym.accessString}%12s ${sym.accurateKindString} ${sym.name.decode}") // we want to see private[pack] for all of these. + } + val sym = rootMirror.getRequiredClass("pack.JavaPackagePrivate") + val syms = Seq(sym, sym.companionModule, sym.companionModule.moduleClass) + (syms ++ syms.flatMap(_.info.decls)).foreach(check) + } + } +} diff --git a/test/files/run/t7582.check b/test/files/run/t7582.check new file mode 100644 index 0000000000..225fb1ace8 --- /dev/null +++ b/test/files/run/t7582.check @@ -0,0 +1,2 @@ +warning: there were 1 inliner warning(s); re-run with -Yinline-warnings for details +2 diff --git a/test/files/run/t7582.flags b/test/files/run/t7582.flags new file mode 100644 index 0000000000..1182725e86 --- /dev/null +++ b/test/files/run/t7582.flags @@ -0,0 +1 @@ +-optimize
\ No newline at end of file diff --git a/test/files/run/t7582/InlineHolder.scala b/test/files/run/t7582/InlineHolder.scala new file mode 100644 index 0000000000..a18b9effaa --- /dev/null +++ b/test/files/run/t7582/InlineHolder.scala @@ -0,0 +1,16 @@ +package p1 { + object InlineHolder { + @inline def inlinable = p1.PackageProtectedJava.protectedMethod() + 1 + } +} + +object O { + @noinline + def x = p1.InlineHolder.inlinable +} + +object Test { + def main(args: Array[String]) { + println(O.x) + } +} diff --git a/test/files/run/t7582/PackageProtectedJava.java b/test/files/run/t7582/PackageProtectedJava.java new file mode 100644 index 0000000000..b7ea2a7676 --- /dev/null +++ b/test/files/run/t7582/PackageProtectedJava.java @@ -0,0 +1,6 @@ +package p1; + +// public class, protected method +public class PackageProtectedJava { + static final int protectedMethod() { return 1; } +} diff --git a/test/files/run/t7582b.check b/test/files/run/t7582b.check new file mode 100644 index 0000000000..225fb1ace8 --- /dev/null +++ b/test/files/run/t7582b.check @@ -0,0 +1,2 @@ +warning: there were 1 inliner warning(s); re-run with -Yinline-warnings for details +2 diff --git a/test/files/run/t7582b.flags b/test/files/run/t7582b.flags new file mode 100644 index 0000000000..1182725e86 --- /dev/null +++ b/test/files/run/t7582b.flags @@ -0,0 +1 @@ +-optimize
\ No newline at end of file diff --git a/test/files/run/t7582b/InlineHolder.scala b/test/files/run/t7582b/InlineHolder.scala new file mode 100644 index 0000000000..a18b9effaa --- /dev/null +++ b/test/files/run/t7582b/InlineHolder.scala @@ -0,0 +1,16 @@ +package p1 { + object InlineHolder { + @inline def inlinable = p1.PackageProtectedJava.protectedMethod() + 1 + } +} + +object O { + @noinline + def x = p1.InlineHolder.inlinable +} + +object Test { + def main(args: Array[String]) { + println(O.x) + } +} diff --git a/test/files/run/t7582b/PackageProtectedJava.java b/test/files/run/t7582b/PackageProtectedJava.java new file mode 100644 index 0000000000..55a44b79f9 --- /dev/null +++ b/test/files/run/t7582b/PackageProtectedJava.java @@ -0,0 +1,6 @@ +package p1; + +// protected class, public method +class PackageProtectedJava { + public static final int protectedMethod() { return 1; } +} diff --git a/test/files/scalacheck/quasiquotes/ArbitraryTreesAndNames.scala b/test/files/scalacheck/quasiquotes/ArbitraryTreesAndNames.scala new file mode 100644 index 0000000000..03f8aa58d3 --- /dev/null +++ b/test/files/scalacheck/quasiquotes/ArbitraryTreesAndNames.scala @@ -0,0 +1,307 @@ +import org.scalacheck._ +import Prop._ +import Gen._ +import Arbitrary._ + +import scala.reflect.api._ +import scala.reflect.runtime.universe._ +import scala.reflect.runtime.universe.Flag._ + +trait ArbitraryTreesAndNames { + def smallList[T](size: Int, g: Gen[T]) = { + val n: Int = choose(0, size / 2 + 1).sample match { + case Some(i) => i + case None => 0 + } + containerOfN[List, T](n, g) + } + + def shortIdent(len: Int) = + for(name <- identifier) + yield if(name.length <= len) name + else name.substring(0, len - 1) + + def genTermName = for(name <- shortIdent(8)) yield TermName(name) + def genTypeName = for(name <- shortIdent(8)) yield TypeName(name) + def genName = oneOf(genTermName, genTypeName) + + def genFlagSet = oneOf( + TRAIT, INTERFACE, MUTABLE, MACRO, + DEFERRED, ABSTRACT, FINAL, SEALED, + IMPLICIT, LAZY, OVERRIDE, PRIVATE, + PROTECTED, LOCAL, CASE, ABSOVERRIDE, + BYNAMEPARAM, PARAM, COVARIANT, CONTRAVARIANT, + DEFAULTPARAM, PRESUPER, DEFAULTINIT + ) + + def genModifiers = for(flagset <- genFlagSet) yield Modifiers(flagset) + + def genConstant = + for(value <- oneOf(arbitrary[Byte], arbitrary[Short], arbitrary[Char], + arbitrary[Int], arbitrary[Long], arbitrary[Float], + arbitrary[Double], arbitrary[Boolean], arbitrary[String])) + yield Constant(value) + + def genAnnotated(size: Int, argGen: Int => Gen[Tree]) = + for(annot <- genTree(size - 1); arg <- argGen(size - 1)) + yield Annotated(annot, arg) + + def genAlternative(size: Int): Gen[Alternative] = + for(trees <- smallList(size, genTree(size - 1))) + yield Alternative(trees) + + def genAppliedTypeTree(size: Int) = + for(tpt <- genTree(size - 1) if tpt.isType; + args <- smallList(size, genTree(size - 1))) + yield AppliedTypeTree(tpt, args) + + def genApply(size: Int) = + for(fun <- genTree(size - 1); + args <- smallList(size, genTree(size - 1))) + yield Apply(fun, args) + + def genAssign(size: Int) = + for(lhs <- genTree(size - 1); rhs <- genTree(size - 1)) + yield Assign(lhs, rhs) + + def genAssignOrNamedArg(size: Int) = + for(lhs <- genTree(size - 1); rhs <- genTree(size - 1)) + yield AssignOrNamedArg(lhs, rhs) + + def genBind(size: Int, nameGen: Gen[Name]) = + for(name <- nameGen; body <- genTree(size - 1)) + yield Bind(name, body) + + def genBlock(size: Int) = + for(stats <- smallList(size, genTree(size - 1)); expr <- genTree(size - 1)) + yield Block(stats, expr) + + def genCaseDef(size: Int) = + for(pat <- genTree(size - 1); guard <- genTree(size - 1); body <- genTree(size - 1)) + yield CaseDef(pat, guard, body) + + def genClassDef(size: Int) = + for(mods <- genModifiers; name <- genTypeName; + tparams <- smallList(size, genTypeDef(size - 1)); + impl <- genTemplate(size - 1)) + yield ClassDef(mods, name, tparams, impl) + + def genCompoundTypeTree(size: Int) = + for(templ <- genTemplate(size - 1)) + yield CompoundTypeTree(templ) + + def genDefDef(size: Int) = + for(mods <- genModifiers; name <- genName; + tpt <- genTree(size -1); rhs <- genTree(size - 1); + tparams <- smallList(size, genTypeDef(size - 1)); + vparamss <- smallList(size, smallList(size, genValDef(size - 1)))) + yield DefDef(mods, name, tparams, vparamss, tpt, rhs) + + def genExistentialTypeTree(size: Int) = + for(tpt <- genTree(size - 1); where <- smallList(size, genTree(size - 1))) + yield ExistentialTypeTree(tpt, where) + + def genFunction(size: Int) = + for(vparams <- smallList(size, genValDef(size - 1)); body <- genTree(size - 1)) + yield Function(vparams, body) + + def genIdent(nameGen: Gen[Name] = genName) = + for(name <- nameGen) yield Ident(name) + + def genIf(size: Int) = + for(cond <- genTree(size - 1); thenp <- genTree(size - 1); elsep <- genTree(size - 1)) + yield If(cond, thenp, elsep) + + def genImport(size: Int) = + for(expr <- genTree(size - 1); selectors <- smallList(size, genImportSelector(size - 1))) + yield Import(expr, selectors) + + def genImportSelector(size: Int) = + for(name <- genName; namePos <- arbitrary[Int]; rename <- genName; renamePos <- arbitrary[Int]) + yield ImportSelector(name, namePos, rename, renamePos) + + def genTemplate(size: Int) = + for(parents <- smallList(size, genTree(size - 1)); + self <- genValDef(size - 1); + body <- smallList(size, genTree(size - 1))) + yield Template(parents, self, body) + + def genLabelDef(size: Int) = + for(name <- genTermName; params <- smallList(size, genIdent()); rhs <- genTree(size - 1)) + yield LabelDef(name, params, rhs) + + def genLiteral = + for(const <- genConstant) yield Literal(const) + + def genMatch(size: Int) = + for(selector <- genTree(size - 1); cases <- smallList(size, genCaseDef(size - 1))) + yield Match(selector, cases) + + def genModuleDef(size: Int) = + for(mods <- genModifiers; name <- genTermName; impl <- genTemplate(size - 1)) + yield ModuleDef(mods, name, impl) + + def genNew(size: Int) = + for(tpt <- genTree(size - 1)) + yield New(tpt) + + def genRefTree(size: Int) = + oneOf(genSelect(size), genIdent(), genSelectFromTypeTree(size)) + + def genPackageDef(size: Int) = + for(reftree <- genRefTree(size - 1); stats <- smallList(size, genTree(size - 1))) + yield PackageDef(reftree, stats) + + def genTypeSelect(size: Int) = + for(qual <- genTree(size - 1); name <- genTypeName) + yield Select(qual, name) + + def genSelect(size: Int, nameGen: Gen[Name] = genName) = + for(qual <- genTree(size - 1); name <- nameGen) + yield Select(qual, name) + + def genSelectFromTypeTree(size: Int) = + for(qual <- genTreeIsType(size - 1); name <- genTypeName) + yield SelectFromTypeTree(qual, name) + + def genReferenceToBoxed(size: Int) = + for(ident <- genIdent()) + yield ReferenceToBoxed(ident) + + def genReturn(size: Int) = + for(expr <- genTree(size - 1)) + yield Return(expr) + + def genSingletonTypeTree(size: Int) = + for(expr <- genTree(size - 1)) + yield SingletonTypeTree(expr) + + def genStar(size: Int) = + for(expr <- genTree(size - 1)) + yield Star(expr) + + def genSuper(size: Int) = + for(qual <- genTree(size - 1); mix <- genTypeName) + yield Super(qual, mix) + + def genThis(size: Int) = + for(qual <- genTypeName) + yield This(qual) + + def genThrow(size: Int) = + for(expr <- genTree(size - 1)) + yield Throw(expr) + + def genTry(size: Int) = + for(block <- genTree(size - 1); + catches <- smallList(size, genCaseDef(size - 1)); + finalizer <- genTree(size - 1)) + yield Try(block, catches, finalizer) + + def genTypeApply(size: Int) = + for(fun <- genTreeIsTerm(size - 1); args <- smallList(size, genTree(size - 1))) + yield TypeApply(fun, args) + + def genTypeBoundsTree(size: Int) = + for(lo <- genTree(size - 1); hi <- genTree(size - 1)) + yield TypeBoundsTree(lo, hi) + + def genTypeDef(size: Int): Gen[TypeDef] = + for(mods <- genModifiers; name <- genTypeName; + tparams <- smallList(size, genTypeDef(size - 1)); rhs <- genTree(size - 1)) + yield TypeDef(mods, name, tparams, rhs) + + def genTypeTree: Gen[TypeTree] = TypeTree() + + def genTyped(size: Int) = + for(expr <- genTree(size - 1); tpt <- genTree(size - 1)) + yield Typed(expr, tpt) + + def genUnApply(size: Int) = + for(fun <- genTree(size - 1); args <- smallList(size, genTree(size - 1))) + yield UnApply(fun, args) + + def genValDef(size: Int) = + for(mods <- genModifiers; name <- genTermName; + tpt <- genTree(size - 1); rhs <- genTree(size - 1)) + yield ValDef(mods, name, tpt, rhs) + + def genTree(size: Int): Gen[Tree] = + if (size <= 1) oneOf(EmptyTree, genTreeIsTerm(size), genTreeIsType(size)) + else oneOf(genTree(1), + // these trees are neither terms nor types + genPackageDef(size - 1), genModuleDef(size - 1), + genCaseDef(size - 1), genDefDef(size - 1), + genTypeDef(size - 1), genTemplate(size - 1), + genClassDef(size - 1), genValDef(size - 1), + genImport(size - 1)) + + def genTreeIsTerm(size: Int): Gen[Tree] = + if (size <= 1) oneOf(genLiteral, genIdent(genTermName)) + else oneOf(genTreeIsTerm(1), genBind(size - 1, genTermName), + genAnnotated(size - 1, genTreeIsTerm), genSelect(size - 1, genTermName), + genAlternative(size - 1), genApply(size - 1), genAssign(size - 1), + genAssignOrNamedArg(size - 1), genBlock(size - 1), genFunction(size - 1), + genIf(size - 1), genLabelDef(size - 1), genMatch(size - 1), genNew(size - 1), + genReturn(size - 1), genStar(size - 1), genSuper(size - 1), genThis(size - 1), + genThrow(size - 1), genTry(size - 1), genTypeApply(size - 1), + genTyped(size - 1), genUnApply(size - 1)) + + def genTreeIsType(size: Int): Gen[Tree] = + if (size <= 1) genIdent(genTypeName) + else oneOf(genTreeIsType(1), genAnnotated(size - 1, genTreeIsType), + genBind(size - 1, genTypeName), genSelect(size - 1, genTypeName), + genSingletonTypeTree(size - 1), genSelectFromTypeTree(size - 1), + genExistentialTypeTree(size - 1), genCompoundTypeTree(size - 1), + genAppliedTypeTree(size - 1), genTypeBoundsTree(size - 1)) + + /* These are marker types that allow to write tests that + * depend specificly on Trees that are terms or types. + * They are transperantly tranformed to trees through + * implicit conversions and liftables for quasiquotes. + */ + + case class TreeIsTerm(tree: Tree) { require(tree.isTerm, showRaw(tree)) } + case class TreeIsType(tree: Tree) { require(tree.isType, showRaw(tree)) } + + def genTreeIsTermWrapped(size: Int) = + for(tit <- genTreeIsTerm(size)) yield TreeIsTerm(tit) + + def genTreeIsTypeWrapped(size: Int) = + for(tit <- genTreeIsType(size)) yield TreeIsType(tit) + + implicit object liftTreeIsTerm extends Liftable[TreeIsTerm] { + def apply(universe: Universe, value: TreeIsTerm): universe.Tree = + value.tree.asInstanceOf[universe.Tree] + } + implicit object liftTreeIsType extends Liftable[TreeIsType] { + def apply(universe: Universe, value: TreeIsType): universe.Tree = + value.tree.asInstanceOf[universe.Tree] + } + implicit def treeIsTerm2tree(tit: TreeIsTerm) = tit.tree + implicit def treeIsType2tree(tit: TreeIsType) = tit.tree + + implicit val arbConstant: Arbitrary[Constant] = Arbitrary(genConstant) + implicit val arbModifiers: Arbitrary[Modifiers] = Arbitrary(genModifiers) + implicit val arbTermName: Arbitrary[TermName] = Arbitrary(genTermName) + implicit val arbTypeName: Arbitrary[TypeName] = Arbitrary(genTypeName) + implicit val arbName: Arbitrary[Name] = Arbitrary(genName) + + // Trees generators are bound by this size to make + // generation times shorter and less memory hungry. + // TODO: is there any better solution? + val maxTreeSize = 5 + + def arbitrarySized[T](gen: Int => Gen[T]) = + Arbitrary(sized(s => gen(s.min(maxTreeSize)))) + + implicit val arbLiteral: Arbitrary[Literal] = Arbitrary(genLiteral) + implicit val arbIdent: Arbitrary[Ident] = Arbitrary(genIdent()) + implicit val arbValDef: Arbitrary[ValDef] = arbitrarySized(genValDef) + implicit val arbDefDef: Arbitrary[DefDef] = arbitrarySized(genDefDef) + implicit val arbTypeDef: Arbitrary[TypeDef] = arbitrarySized(genTypeDef) + implicit val arbBind: Arbitrary[Bind] = arbitrarySized(genBind(_, genName)) + implicit val arbTree: Arbitrary[Tree] = arbitrarySized(genTree) + implicit val arbTreeIsTerm: Arbitrary[TreeIsTerm] = arbitrarySized(genTreeIsTermWrapped) + implicit val arbTreeIsType: Arbitrary[TreeIsType] = arbitrarySized(genTreeIsTypeWrapped) +}
\ No newline at end of file diff --git a/test/files/scalacheck/quasiquotes/ErrorProps.scala b/test/files/scalacheck/quasiquotes/ErrorProps.scala new file mode 100644 index 0000000000..044a332a04 --- /dev/null +++ b/test/files/scalacheck/quasiquotes/ErrorProps.scala @@ -0,0 +1,199 @@ +import org.scalacheck._ +import Prop._ +import Gen._ +import Arbitrary._ + +import scala.reflect.runtime.universe._ +import Flag._ + +object ErrorProps extends QuasiquoteProperties("errors") { + property("can't extract two .. cardinalities in a row") = fails( + "Can't extract with .. here", + """ + val xs = List(q"x1", q"x2") + val q"f(..$xs1, ..$xs2)" = xs + """) + + property("can't splice with given cardinality") = fails( + "Can't splice List[reflect.runtime.universe.Ident], consider using ..", + """ + val xs = List(q"x", q"x") + q"$xs" + """) + + property("splice typename into typedef with default bounds") = fails( + "reflect.runtime.universe.Name expected but reflect.runtime.universe.TypeDef found", + """ + val T1 = TypeName("T1") + val T2 = q"type T" + val t = EmptyTree + q"type $T1[$T2 >: _root_.scala.Any <: _root_.scala.Nothing] = $t" ≈ + TypeDef(Modifiers(), T1, List(T2), t) + """) + + property("can't splice annotations with ... cardinality") = fails( + "Can't splice with ... here", + """ + val annots = List(List(q"Foo")) + q"@...$annots def foo" + """) + + property("@..$first @$rest def foo") = fails( + "Can't extract with .. here", + """ + val a = annot("a") + val b = annot("b") + val c = annot("c") + val q"@..$first @$rest def foo" = q"@$a @$b @$c def foo" + """) + + property("only literal string arguments") = fails( + "Quasiquotes can only be used with literal strings", + """ + val s: String = "foo" + StringContext(s).q() + """) + + property("don't know how to splice inside of strings") = fails( + "Don't know how to splice here", + """ + val x: Tree = EmptyTree + StringContext("\"", "\"").q(x) + """) + + property("expected different cardinality") = fails( + "Can't splice List[reflect.runtime.universe.Tree] with ..., consider using ..", + """ + val args: List[Tree] = Nil + q"f(...$args)" + """) + + property("non-liftable type ..") = fails( + "Can't splice List[StringBuilder] with .., consider omitting the dots or providing an implicit instance of Liftable[StringBuilder]", + """ + import java.lang.StringBuilder + val bazs = List(new StringBuilder) + q"f(..$bazs)" + """) + + property("non-liftable type ...") = fails( + "Can't splice List[List[StringBuilder]] with .., consider using ... or providing an implicit instance of Liftable[StringBuilder]", + """ + import java.lang.StringBuilder + val bazs = List(List(new StringBuilder)) + q"f(..$bazs)" + """) + + property("use .. card or provide liftable") = fails( + "Can't splice List[StringBuilder], consider using .. or providing an implicit instance of Liftable[List[StringBuilder]]", + """ + import java.lang.StringBuilder + val lst: List[StringBuilder] = Nil + q"f($lst)" + """) + + property("use ... card or provide liftable") = fails( + "Can't splice List[List[reflect.runtime.universe.Ident]], consider using ...", + """ + val xs = List(List(q"x", q"x")) + q"$xs" + """) + + property("use zero card") = fails( + "Can't splice reflect.runtime.universe.Tree with .., consider omitting the dots", + """ + val t = EmptyTree + q"f(..$t)" + """) + + property("not liftable or natively supported") = fails( + "Can't splice StringBuilder, consider providing an implicit instance of Liftable[StringBuilder]", + """ + import java.lang.StringBuilder + val sb = new StringBuilder + q"f($sb)" + """) + + property("casedef expected") = fails( + "reflect.runtime.universe.CaseDef expected but reflect.runtime.universe.Tree found", + """ + val t = EmptyTree + q"_ { case $t }" + """) + + property("can't splice with ... card here") = fails( + "Can't splice with ... here", + """ + val lst: List[List[Tree]] = Nil; val t = EmptyTree + q"f(...$lst, $t)" + """) + + property("name expected") = fails( + "reflect.runtime.universe.Name expected but reflect.runtime.universe.Tree found", + """ + val t = EmptyTree + q"class $t" + """) + + property("flags or mods expected") = fails( + "reflect.runtime.universe.FlagSet or reflect.runtime.universe.Modifiers expected but reflect.runtime.universe.Tree found", + """ + val t = EmptyTree + q"$t def foo" + """) + + property("cant splice flags together with mods") = fails( + "Can't splice flags together with modifiers, consider merging flags into modifiers", + """ + val f = Flag.IMPLICIT; val m = NoMods + q"$f $m def foo" + """) + + property("can't splice mods with annots") = fails( + "Can't splice modifiers together with annotations, consider merging annotations into modifiers", + """ + val m = NoMods + q"@annot $m def foo" + """) + + property("can't splice modifiers with inline flags") = fails( + "Can't splice modifiers together with flags, consider merging flags into modifiers", + """ + val m = NoMods + q"$m implicit def foo" + """) + + property("can't splice multiple mods") = fails( + "Can't splice multiple modifiers, consider merging them into a single modifiers instance", + """ + val m1 = NoMods; val m2 = NoMods + q"$m1 $m2 def foo" + """) + + property("can't extract with .. card here") = fails( + "Can't extract with .. here", + """ + val q"f(..$xs, $y)" = EmptyTree + """) + + property("can't extract mods with annots") = fails( + "Can't extract modifiers together with annotations, consider extracting just modifiers", + """ + val q"@$annot $mods def foo" = EmptyTree + """) + + property("can't extract multiple mods") = fails( + "Can't extract multiple modifiers together, consider extracting a single modifiers instance", + """ + val q"$m1 $m2 def foo" = EmptyTree + """) + + property("can't parse more than one casedef") = fails( + "Can't parse more than one casedef, consider generating a match tree instead", + """ + cq"1 => 2 case 3 => 5" + """) + + // // Make sure a nice error is reported in this case + // { import Flag._; val mods = NoMods; q"lazy $mods val x: Int" } +}
\ No newline at end of file diff --git a/test/files/scalacheck/quasiquotes/LiftableProps.scala b/test/files/scalacheck/quasiquotes/LiftableProps.scala new file mode 100644 index 0000000000..510ab99068 --- /dev/null +++ b/test/files/scalacheck/quasiquotes/LiftableProps.scala @@ -0,0 +1,84 @@ +import org.scalacheck._ +import Prop._ +import Gen._ +import Arbitrary._ + +import scala.reflect.runtime.universe._ +import Flag._ + +object LiftableProps extends QuasiquoteProperties("liftable") { + property("splice byte") = test { + val c: Byte = 0 + assert(q"$c" ≈ Literal(Constant(c))) + } + + property("splice short") = test { + val c: Short = 0 + assert(q"$c" ≈ Literal(Constant(c))) + } + + property("splice char") = test { + val c: Char = 'c' + assert(q"$c" ≈ Literal(Constant(c))) + } + + property("splice int") = test { + val c: Int = 0 + assert(q"$c" ≈ Literal(Constant(c))) + } + + property("splice long") = test { + val c: Long = 0 + assert(q"$c" ≈ Literal(Constant(c))) + } + + property("splice float") = test { + val c: Float = 0.0f + assert(q"$c" ≈ Literal(Constant(c))) + } + + property("splice double") = test { + val c: Double = 0.0 + assert(q"$c" ≈ Literal(Constant(c))) + } + + property("splice boolean") = test { + val c: Boolean = false + assert(q"$c" ≈ Literal(Constant(c))) + } + + property("splice string") = test { + val c: String = "s" + assert(q"$c" ≈ Literal(Constant(c))) + } + + property("splice unit") = test { + val c: Unit = () + assert(q"$c" ≈ Literal(Constant(c))) + } + + property("lift symbol") = test { + val s = rootMirror.staticClass("scala.Int") + assert(q"$s" ≈ Ident(s)) + } + + property("lift type") = test { + val tpe = rootMirror.staticClass("scala.Int").toType + assert(q"$tpe" ≈ TypeTree(tpe)) + } + + property("lift type tag") = test { + val tag = TypeTag.Int + assert(q"$tag" ≈ TypeTree(tag.tpe)) + } + + property("lift weak type tag") = test { + val tag = WeakTypeTag.Int + assert(q"$tag" ≈ TypeTree(tag.tpe)) + } + + property("lift constant") = test { + val const = Constant(0) + assert(q"$const" ≈ q"0") + } +}
\ No newline at end of file diff --git a/test/files/scalacheck/quasiquotes/PatternConstructionProps.scala b/test/files/scalacheck/quasiquotes/PatternConstructionProps.scala new file mode 100644 index 0000000000..aee50c9c5f --- /dev/null +++ b/test/files/scalacheck/quasiquotes/PatternConstructionProps.scala @@ -0,0 +1,37 @@ +import org.scalacheck._ +import Prop._ +import Gen._ +import Arbitrary._ + +import scala.reflect.runtime.universe._ +import Flag._ + +object PatternConstructionProps extends QuasiquoteProperties("pattern construction") { + property("splice bind") = forAll { (bind: Bind) => + pq"$bind" ≈ bind + } + + property("splice name into bind") = forAll { (name: TermName) => + pq"$name" ≈ Bind(name, Ident(nme.WILDCARD)) + } + + property("splice name and tree into bind") = forAll { (name: TermName, tree: Tree) => + pq"$name @ $tree" ≈ Bind(name, tree) + } + + property("splice type name into typed") = forAll { (name: TypeName) => + pq"_ : $name" ≈ Typed(Ident(nme.WILDCARD), Ident(name)) + } + + property("splice tree into typed") = forAll { (typ: Tree) => + pq"_ : $typ" ≈ Typed(Ident(nme.WILDCARD), typ) + } + + property("splice into apply") = forAll { (pat: Tree, subpat: Tree) => + pq"$pat($subpat)" ≈ Apply(pat, List(subpat)) + } + + property("splice into casedef") = forAll { (pat: Tree, cond: Tree, body: Tree) => + cq"$pat if $cond => $body" ≈ CaseDef(pat, cond, Block(List(), body)) + } +}
\ No newline at end of file diff --git a/test/files/scalacheck/quasiquotes/PatternDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/PatternDeconstructionProps.scala new file mode 100644 index 0000000000..f73fd29b22 --- /dev/null +++ b/test/files/scalacheck/quasiquotes/PatternDeconstructionProps.scala @@ -0,0 +1,35 @@ +import org.scalacheck._ +import Prop._ +import Gen._ +import Arbitrary._ + +import scala.reflect.runtime.universe._ +import Flag._ +import definitions._ + +object PatternDeconstructionProps extends QuasiquoteProperties("pattern deconstruction") { + property("extract bind") = forAll { (bind: Bind) => + val pq"$bind0" = pq"$bind" + bind0 ≈ bind + } + + property("extract bind and subpattern") = forAll { (name: TermName, subp: Tree) => + val pq"$name0 @ $subp0" = pq"$name @ $subp" + name0 ≈ name && subp0 ≈ subp + } + + property("extract typed") = forAll { (typ: Tree) => + val pq"_ : $typ0" = pq"_ : $typ" + typ0 ≈ typ + } + + property("extract apply") = forAll { (pat: Tree, subpat: Tree) => + val pq"$pat0($subpat0)" = pq"$pat($subpat)" + pat0 ≈ pat && subpat0 ≈ subpat + } + + property("extract casedef") = forAll { (pat: Tree, cond: Tree, body: Tree) => + val cq"$pat0 if $cond0 => $body0" = cq"$pat if $cond => $body" + pat0 ≈ pat && cond0 ≈ cond && body0 ≈ body + } +}
\ No newline at end of file diff --git a/test/files/scalacheck/quasiquotes/QuasiquoteProperties.scala b/test/files/scalacheck/quasiquotes/QuasiquoteProperties.scala new file mode 100644 index 0000000000..5e87aa57cc --- /dev/null +++ b/test/files/scalacheck/quasiquotes/QuasiquoteProperties.scala @@ -0,0 +1,89 @@ +import scala.reflect.runtime.universe._ +import scala.tools.reflect.ToolBox +import scala.tools.reflect.ToolBoxError +import scala.reflect.macros.TypecheckException + +import org.scalacheck._ +import Prop._ +import Gen._ +import Arbitrary._ + +class QuasiquoteProperties(name: String) extends Properties(name) with ArbitraryTreesAndNames with Helpers + +trait Helpers { + /** Runs a code block and returns proof confirmation + * 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) => + block + Result(Prop.Proof) + } + + implicit class TestSimilarTree(tree1: Tree) { + def ≈(tree2: Tree) = tree1.equalsStructure(tree2) + } + + implicit class TestSimilarListTree(lst: List[Tree]) { + def ≈(other: List[Tree]) = (lst.length == other.length) && lst.zip(other).forall { case (t1, t2) => t1 ≈ t2 } + } + + implicit class TestSimilarListListTree(lst: List[List[Tree]]) { + def ≈(other: List[List[Tree]]) = (lst.length == other.length) && lst.zip(other).forall { case (l1, l2) => l1 ≈ l2 } + } + + implicit class TestSimilarName(name: Name) { + def ≈(other: Name) = name == other + } + + implicit class TestSimilarMods(mods: Modifiers) { + def ≈(other: Modifiers) = (mods.flags == other.flags) && (mods.privateWithin ≈ other.privateWithin) && (mods.annotations ≈ other.annotations) + } + + def assertThrows[T <: AnyRef](f: => Any)(implicit manifest: Manifest[T]): Unit = { + val clazz = manifest.erasure.asInstanceOf[Class[T]] + val thrown = + try { + f + false + } catch { + case u: Throwable => + if (!clazz.isAssignableFrom(u.getClass)) + assert(false, s"wrong exception: $u") + true + } + if(!thrown) + assert(false, "exception wasn't thrown") + } + + def fails(msg: String, block: String) = { + def result(ok: Boolean, description: String = "") = { + val status = if (ok) Prop.Proof else Prop.False + val labels = if (description != "") Set(description) else Set.empty[String] + Prop { new Prop.Result(status, Nil, Set.empty, labels) } + } + try { + val tb = rootMirror.mkToolBox() + val tree = tb.parse(s""" + object Wrapper extends Helpers { + import scala.reflect.runtime.universe._ + $block + } + """) + tb.compile(tree) + result(false, "given code doesn't fail to typecheck") + } catch { + case ToolBoxError(emsg, _) => + if (!emsg.contains(msg)) + result(false, s"error message '${emsg}' is not the same as expected '$msg'") + else + result(true) + } + } + + def annot(name: String): Tree = annot(TypeName(name), Nil) + def annot(name: TypeName): Tree = annot(name, Nil) + def annot(name: String, args: List[Tree]): Tree = annot(TypeName(name), args) + def annot(name: TypeName, args: List[Tree]): Tree = q"new $name(..$args)" +}
\ No newline at end of file diff --git a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala new file mode 100644 index 0000000000..b14945f24b --- /dev/null +++ b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala @@ -0,0 +1,341 @@ +import org.scalacheck._ +import Prop._ +import Gen._ +import Arbitrary._ + +import scala.reflect.runtime.universe._ +import Flag._ + +object TermConstructionProps extends QuasiquoteProperties("term construction") { + val anyRef = Select(Ident(TermName("scala")), TypeName("AnyRef")) + val emtpyConstructor = + DefDef( + Modifiers(), nme.CONSTRUCTOR, List(), + List(List()), TypeTree(), Block(List(Apply(Select(Super(This(tpnme.EMPTY), tpnme.EMPTY), nme.CONSTRUCTOR), List())), Literal(Constant(())))) + + def classWithMethods(name: TypeName, methods: List[DefDef] = Nil) = + ClassDef( + Modifiers(), name, List(), + Template(List(anyRef), emptyValDef, List(emtpyConstructor) ++ methods)) + + property("splice single tree return tree itself") = forAll { (t: Tree) => + q"$t" ≈ t + } + + property("splice trees into if expression") = forAll { (t1: Tree, t2: Tree, t3: Tree) => + q"if($t1) $t2 else $t3" ≈ If(t1, t2, t3) + } + + property("splice term name into val") = forAll { (name: TermName) => + q"val $name = 0" ≈ ValDef(Modifiers(), name, TypeTree(), Literal(Constant(0))) + } + + property("splice type name into typedef") = forAll { (name1: TypeName, name2: TypeName) => + q"type $name1 = $name2" ≈ TypeDef(Modifiers(), name1, List(), Ident(name2)) + } + + property("splice term name into class") = forAll { (name: TypeName) => + q"class $name" ≈ classWithMethods(name) + } + + property("splice method into class") = forAll { (name: TypeName, method: DefDef) => + q"class $name { $method }" ≈ classWithMethods(name, List(method)) + } + + property("splice trees into ascriptiopn") = forAll { (t1: Tree, t2: Tree) => + q"$t1 : $t2" ≈ Typed(t1, t2) + } + + property("splice trees into apply") = forAll { (t1: Tree, t2: Tree, t3: Tree) => + q"$t1($t2, $t3)" ≈ Apply(t1, List(t2, t3)) + } + + property("splice trees with .. cardinality into apply") = forAll { (ts: List[Tree]) => + q"f(..$ts)" ≈ Apply(q"f", ts) + } + + property("splice iterable into apply") = forAll { (trees: List[Tree]) => + val itrees: Iterable[Tree] = trees + q"f(..$itrees)" ≈ Apply(q"f", trees) + } + + property("splice trees with ... cardinality into apply") = forAll { (ts1: List[Tree], ts2: List[Tree]) => + val argss = List(ts1, ts2) + q"f(...$argss)" ≈ Apply(Apply(q"f", ts1), ts2) + } + + property("splice term name into assign") = forAll { (name: TermName, t: Tree) => + q"$name = $t" ≈ Assign(Ident(name), t) + } + + property("splice trees into block") = forAll { (t1: Tree, t2: Tree, t3: Tree) => + q"""{ + $t1 + $t2 + $t3 + }""" ≈ Block(List(t1, t2), t3) + } + + property("splice type name into class parents") = forAll { (name: TypeName, parent: TypeName) => + q"class $name extends $parent" ≈ + ClassDef( + Modifiers(), name, List(), + Template(List(Ident(parent)), emptyValDef, List(emtpyConstructor))) + } + + property("splice tree into new") = forAll { (tree: Tree) => + q"new $tree" ≈ Apply(Select(New(tree), nme.CONSTRUCTOR), List()) + } + + property("splice tree into return") = forAll { (tree: Tree) => + q"return $tree" ≈ Return(tree) + } + + property("splice a list of arguments") = forAll { (fun: Tree, args: List[Tree]) => + q"$fun(..$args)" ≈ Apply(fun, args) + } + + property("splice list and non-list fun arguments") = forAll { (fun: Tree, arg1: Tree, arg2: Tree, args: List[Tree]) => + q"$fun(..$args, $arg1, $arg2)" ≈ Apply(fun, args ++ List(arg1) ++ List(arg2)) && + q"$fun($arg1, ..$args, $arg2)" ≈ Apply(fun, List(arg1) ++ args ++ List(arg2)) && + q"$fun($arg1, $arg2, ..$args)" ≈ Apply(fun, List(arg1) ++ List(arg2) ++ args) + } + + property("splice members into class") = forAll { (name: TypeName, defs: List[DefDef], extra: DefDef) => + q"""class $name { + ..$defs + $extra + }""" ≈ classWithMethods(name, defs ++ List(extra)) + } + + property("splice into new") = forAll { (name: TypeName, body: List[Tree]) => + q"new $name { ..$body }" ≈ + q"""{ + final class $$anon extends $name { + ..$body + } + new $$anon + }""" + } + + + property("splice tree into singleton type tree") = forAll { (name: TypeName, t: Tree) => + q"type $name = $t.type" ≈ q"type $name = ${SingletonTypeTree(t)}" + } + + property("splice type name into this") = forAll { (T: TypeName) => + q"$T.this" ≈ This(T) + } + + property("splice tree into throw") = forAll { (t: Tree) => + q"throw $t" ≈ Throw(t) + } + + property("splice trees into type apply") = forAll { (fun: TreeIsTerm, types: List[Tree]) => + q"$fun[..$types]" ≈ TypeApply(fun, types) + } + + property("splice type names into type bounds") = forAll { (T1: TypeName, T2: TypeName, T3: TypeName) => + q"type $T1 >: $T2 <: $T3" ≈ + TypeDef( + Modifiers(DEFERRED), T1, List(), + TypeBoundsTree(Ident(T2), Ident(T3))) + } + + property("splice trees names into type bounds") = forAll { (T: TypeName, t1: Tree, t2: Tree) => + q"type $T >: $t1 <: $t2" ≈ + TypeDef( + Modifiers(DEFERRED), T, List(), + TypeBoundsTree(t1, t2)) + } + + property("splice tparams into typedef (1)") = forAll { (T: TypeName, targs: List[TypeDef], t: Tree) => + q"type $T[..$targs] = $t" ≈ TypeDef(Modifiers(), T, targs, t) + } + + property("splice tparams into typedef (2)") = forAll { (T: TypeName, targs1: List[TypeDef], targs2: List[TypeDef], t: Tree) => + q"type $T[..$targs1, ..$targs2] = $t" ≈ TypeDef(Modifiers(), T, targs1 ++ targs2, t) + } + + property("splice tparams into typedef (3)") = forAll { (T: TypeName, targ: TypeDef, targs: List[TypeDef], t: Tree) => + q"type $T[$targ, ..$targs] = $t" ≈ TypeDef(Modifiers(), T, targ :: targs, t) + } + + property("splice typename into typedef with default bounds") = forAll { (T1: TypeName, T2: TypeName, t: Tree) => + q"type $T1[$T2 >: Any <: Nothing] = $t" ≈ + TypeDef( + Modifiers(), T1, + List(TypeDef( + Modifiers(PARAM), T2, + List(), + TypeBoundsTree( + Ident(TypeName("Any")), + Ident(TypeName("Nothing"))))), + t) + } + + property("splice type names into compound type tree") = forAll { (T: TypeName, A: TypeName, B: TypeName) => + q"type $T = $A with $B" ≈ + TypeDef( + Modifiers(), T, List(), + CompoundTypeTree( + Template(List(Ident(A), Ident(B)), ValDef(Modifiers(PRIVATE), nme.WILDCARD, TypeTree(), EmptyTree), List()))) + } + + property("splice trees into existential type tree") = forAll { + (T1: TypeName, T2: TypeName, X: TypeName, Lo: TypeName, Hi: TypeName) => + + q"type $T1 = $T2[$X] forSome { type $X >: $Lo <: $Hi }" ≈ + TypeDef( + Modifiers(), T1, List(), + ExistentialTypeTree( + AppliedTypeTree(Ident(T2), List(Ident(X))), + List( + TypeDef(Modifiers(DEFERRED), X, List(), TypeBoundsTree(Ident(Lo), Ident(Hi)))))) + } + + property("splice names into import selector") = forAll { + (expr: Tree, plain: Name, oldname: Name, newname: Name, discard: Name) => + + val Import(expr1, List( + ImportSelector(plain11, _, plain12, _), + ImportSelector(oldname1, _, newname1, _), + ImportSelector(discard1, _, wildcard, _))) = + q"import $expr.{$plain, $oldname => $newname, $discard => _}" + + expr1 ≈ expr && plain11 == plain12 && plain12 == plain && + oldname1 == oldname && newname1 == newname && discard1 == discard && wildcard == nme.WILDCARD + } + + property("splice trees into while loop") = forAll { (cond: Tree, body: Tree) => + val LabelDef(_, List(), If(cond1, Block(List(body1), Apply(_, List())), Literal(Constant(())))) = q"while($cond) $body" + body1 ≈ body && cond1 ≈ cond + } + + property("splice trees into do while loop") = forAll { (cond: Tree, body: Tree) => + val LabelDef(_, List(), Block(List(body1), If(cond1, Apply(_, List()), Literal(Constant(()))))) = q"do $body while($cond)" + body1 ≈ body && cond1 ≈ cond + } + + property("splice trees into alternative") = forAll { (c: Tree, A: Tree, B: Tree) => + q"$c match { case $A | $B => }" ≈ + Match(c, List( + CaseDef(Alternative(List(A, B)), EmptyTree, Literal(Constant(()))))) + } + + property("splice into applied type tree") = forAll { (T1: TypeName, T2: TypeName, args: List[Tree]) => + q"type $T1 = $T2[..$args]" ≈ + TypeDef( + Modifiers(), T1, List(), + AppliedTypeTree(Ident(T2), args)) + } + + property("splice list of trees into block (1)") = forAll { (trees: List[Tree]) => + q"{ ..$trees }" ≈ (trees match { + case Nil => Block(Nil, q"()") + case _ => Block(trees.init, trees.last) + }) + } + + property("splice list of trees into block (2)") = forAll { (trees1: List[Tree], trees2: List[Tree]) => + q"{ ..$trees1 ; ..$trees2 }" ≈ ((trees1 ++ trees2) match { + case Nil => Block(Nil, Literal(Constant(()))) + case trees => Block(trees.init, trees.last) + }) + } + + property("splice list of trees into block (3)") = forAll { (trees: List[Tree], tree: Tree) => + q"{ ..$trees; $tree }" ≈ Block(trees, tree) + } + + def assertSameAnnots(tree: {def mods: Modifiers}, annots: List[Tree]) = + assert(tree.mods.annotations ≈ annots, + s"${tree.mods.annotations} =/= ${annots}") + + def assertSameAnnots(tree1: {def mods: Modifiers}, tree2: {def mods: Modifiers}) = + assert(tree1.mods.annotations ≈ tree2.mods.annotations, + s"${tree1.mods.annotations} =/= ${tree2.mods.annotations}") + + property("splice type name into annotation") = test { + val name = TypeName("annot") + assertSameAnnots(q"@$name def foo", List(annot(name))) + } + + property("splice ident into annotation") = test { + val name = TypeName("annot") + val ident = Ident(name) + assertSameAnnots(q"@$ident def foo", List(annot(name))) + } + + property("splice idents into annotation") = test { + val idents = List(Ident(TypeName("annot1")), Ident(TypeName("annot2"))) + assertSameAnnots(q"@..$idents def foo", + idents.map { ident => Apply(Select(New(ident), nme.CONSTRUCTOR), List()) }) + } + + property("splice constructor calls into annotation") = test { + val ctorcalls = List(annot("a1"), annot("a2")) + assertSameAnnots(q"@..$ctorcalls def foo", ctorcalls) + } + + property("splice multiple annotations (1)") = test { + val annot1 = annot("a1") + val annot2 = annot("a2") + val res = q"@$annot1 @$annot2 def foo" + assertSameAnnots(res, List(annot1, annot2)) + } + + property("splice multiple annotations (2)") = test { + val annot1 = annot("a1") + val annots = List(annot("a2"), annot("a3")) + val res = q"@$annot1 @..$annots def foo" + assertSameAnnots(res, annot1 :: annots) + } + + property("splice annotations with arguments (1)") = test { + val a = annot("a", List(q"x")) + assertSameAnnots(q"@$a def foo", q"@a(x) def foo") + } + + property("splice annotations with arguments (2)") = test { + val a = newTypeName("a") + assertSameAnnots(q"@$a(x) def foo", q"@a(x) def foo") + } + + property("splice annotations with arguments (3") = test { + val a = Ident(newTypeName("a")) + assertSameAnnots(q"@$a(x) def foo", q"@a(x) def foo") + } + + property("can't splice annotations with arguments specificed twice") = test { + val a = annot("a", List(q"x")) + assertThrows[IllegalArgumentException] { + q"@$a(y) def foo" + } + } + + property("splice term into brackets") = test { + val a = q"a" + assert(q"($a)" ≈ a) + } + + property("splice terms into tuple") = test { + 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)") + } + + property("splice empty list into tuple") = test { + val empty = List[Tree]() + assert(q"(..$empty)" ≈ q"()") + } + + property("splice improper tree into annot") = test { + val t = tq"Foo[Baz]" + assertThrows[IllegalArgumentException] { + q"@$t def foo" + } + } +} diff --git a/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala new file mode 100644 index 0000000000..114c9f112b --- /dev/null +++ b/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala @@ -0,0 +1,122 @@ +import org.scalacheck._ +import Prop._ +import Gen._ +import Arbitrary._ + +import scala.reflect.runtime.universe._ +import Flag._ + +object TermDeconstructionProps extends QuasiquoteProperties("term deconstruction") { + + property("f(..x) = f") = test { + assertThrows[MatchError] { + val q"f(..$argss)" = q"f" + } + } + + property("f(x)") = forAll { (x: Tree) => + val q"f($x1)" = q"f($x)" + x1 ≈ x + } + + property("f(..xs)") = forAll { (x1: Tree, x2: Tree) => + val q"f(..$xs)" = q"f($x1, $x2)" + xs ≈ List(x1, x2) + } + + property("f(y, ..ys)") = forAll { (x1: Tree, x2: Tree, x3: Tree) => + val q"f($y, ..$ys)" = q"f($x1, $x2, $x3)" + y ≈ x1 && ys ≈ List(x2, x3) + } + + property("f(y1, y2, ..ys)") = forAll { (x1: Tree, x2: Tree, x3: Tree) => + val q"f($y1, $y2, ..$ys)" = q"f($x1, $x2, $x3)" + y1 ≈ x1 && y2 ≈ x2 && ys ≈ List(x3) + } + + property("f(...xss)") = forAll { (x1: Tree, x2: Tree) => + val q"f(...$argss)" = q"f($x1)($x2)" + argss ≈ List(List(x1), List(x2)) + } + + property("f(...xss) = f") = forAll { (x1: Tree, x2: Tree) => + val q"f(...$argss)" = q"f" + argss ≈ List() + } + + property("@$annot def foo") = forAll { (annotName: TypeName) => + val q"@$annot def foo" = q"@$annotName def foo" + annot ≈ Apply(Select(New(Ident(annotName)), nme.CONSTRUCTOR), List()) + } + + property("@$annot(..$args) def foo") = forAll { (annotName: TypeName, tree: Tree) => + val q"@$annot(..$args) def foo" = q"@$annotName($tree) def foo" + annot ≈ Ident(annotName) && args ≈ List(tree) + } + + property("@..$annots def foo") = test { + val a = annot("a") + val b = annot("b") + val q"@..$annots def foo" = q"@$a @$b def foo" + annots ≈ List(a, b) + } + + property("@$annot @..$annots def foo") = test { + val a = annot("a") + val b = annot("b") + val c = annot("c") + val q"@$first @..$rest def foo" = q"@$a @$b @$c def foo" + first ≈ a && rest ≈ List(b, c) + } + + property("class without params") = test { + val q"class $name { ..$body }" = q"class Foo { def bar = 3 }" + assert(body ≈ List(q"def bar = 3")) + } + + property("class constructor") = test { + val q"class $name(...$argss)" = q"class Foo(x: Int)(y: Int)" + assert(argss.length == 2) + } + + property("class parents") = test { + val q"class $name extends ..$parents" = q"class Foo extends Bar with Blah" + assert(parents ≈ List(tq"Bar", tq"Blah")) + } + + property("class selfdef") = test { + val q"class $name { $self => }" = q"class Foo { self: T => }" + assert(self.name ≈ TermName("self") && self.tpt ≈ tq"T") + } + + property("class tparams") = test { + val q"class $name[..$tparams]" = q"class Foo[A, B]" + assert(tparams.map { _.name } == List(TypeName("A"), TypeName("B"))) + } + + property("deconstruct unit as tuple") = test { + val q"(..$xs)" = q"()" + assert(xs.isEmpty) + } + + property("deconstruct tuple") = test { + val q"(..$xs)" = q"(a, b)" + assert(xs ≈ List(q"a", q"b")) + } + + property("deconstruct tuple mixed") = test { + val q"($first, ..$rest)" = q"(a, b, c)" + assert(first ≈ q"a" && rest ≈ List(q"b", q"c")) + } + + property("deconstruct cases") = test { + val q"$x match { case ..$cases }" = q"x match { case 1 => case 2 => }" + x ≈ q"x" && cases ≈ List(cq"1 =>", cq"2 =>") + } + + property("deconstruct mods") = test { + val mods = Modifiers(IMPLICIT | PRIVATE, TermName("foobar"), Nil) + val q"$mods0 def foo" = q"$mods def foo" + assert(mods0 ≈ mods) + } +}
\ No newline at end of file diff --git a/test/files/scalacheck/quasiquotes/Test.scala b/test/files/scalacheck/quasiquotes/Test.scala new file mode 100644 index 0000000000..2387a9b008 --- /dev/null +++ b/test/files/scalacheck/quasiquotes/Test.scala @@ -0,0 +1,12 @@ +import org.scalacheck._ + +object Test extends Properties("quasiquotes") { + include(TermConstructionProps) + include(TermDeconstructionProps) + include(TypeConstructionProps) + include(TypeDeconstructionProps) + include(PatternConstructionProps) + include(PatternDeconstructionProps) + include(LiftableProps) + include(ErrorProps) +}
\ No newline at end of file diff --git a/test/files/scalacheck/quasiquotes/TypeConstructionProps.scala b/test/files/scalacheck/quasiquotes/TypeConstructionProps.scala new file mode 100644 index 0000000000..535ed8ecbf --- /dev/null +++ b/test/files/scalacheck/quasiquotes/TypeConstructionProps.scala @@ -0,0 +1,25 @@ +import org.scalacheck._ +import Prop._ +import Gen._ +import Arbitrary._ + +import scala.reflect.runtime.universe._ +import Flag._ + +object TypeConstructionProps extends QuasiquoteProperties("type construction") { + property("bare idents contain type names") = test { + tq"x" ≈ Ident(TypeName("x")) + } + + property("splice type names into AppliedTypeTree") = forAll { (name1: TypeName, name2: TypeName) => + tq"$name1[$name2]" ≈ AppliedTypeTree(Ident(name1), List(Ident(name2))) + } + + 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]") + } +}
\ No newline at end of file diff --git a/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala new file mode 100644 index 0000000000..6ab699d4f0 --- /dev/null +++ b/test/files/scalacheck/quasiquotes/TypeDeconstructionProps.scala @@ -0,0 +1,29 @@ +import org.scalacheck._ +import Prop._ +import Gen._ +import Arbitrary._ + +import scala.reflect.runtime.universe._ +import Flag._ + +object TypeDeconstructionProps extends QuasiquoteProperties("type deconstruction") { + property("ident(type name)") = forAll { (name: TypeName) => + val t = Ident(name) + val tq"$t1" = t + t1 ≈ t + } + + property("applied type tree") = forAll { (name1: TypeName, name2: TypeName) => + val tq"$a[$b]" = AppliedTypeTree(Ident(name1), List(Ident(name2))) + a ≈ Ident(name1) && b ≈ Ident(name2) + } + + property("tuple type") = test { + val tq"(..$empty)" = tq"scala.Unit" + assert(empty.isEmpty) + val tq"(..$ts)" = tq"(t1, t2)" + assert(ts ≈ List(tq"t1", tq"t2")) + val tq"($head, ..$tail)" = tq"(t0, t1, t2)" + assert(head ≈ tq"t0" && tail ≈ List(tq"t1", tq"t2")) + } +}
\ No newline at end of file diff --git a/test/files/specialized/SI-7343.scala b/test/files/specialized/SI-7343.scala new file mode 100644 index 0000000000..5ee683064c --- /dev/null +++ b/test/files/specialized/SI-7343.scala @@ -0,0 +1,55 @@ +class Parent[@specialized(Int) T] + +object Test extends App { + + /** + * This method will check if specialization is correctly rewiring parents + * for classes defined inside methods. The pattern is important since this + * is how closures are currently represented: as locally-defined anonymous + * classes, which usually end up inside methods. For these closures we do + * want their parents rewired correctly: + * + * ``` + * def checkSuperClass$mIc$sp[T](t: T, ...) = { + * class X extends Parent$mcI$sp // instead of just Parent + * ... + * } + */ + def checkSuperClass[@specialized(Int) T](t: T, expectedXSuper: String) = { + // test target: + // - in checkSuperClass, X should extend Parent + // - in checkSuperClass$mIc$sp, X should extend Parent$mcI$sp + class X extends Parent[T]() + + // get the superclass for X and make sure it's correct + val actualXSuper = (new X).getClass().getSuperclass().getSimpleName() + assert(actualXSuper == expectedXSuper, actualXSuper + " != " + expectedXSuper) + } + + checkSuperClass("x", "Parent") + checkSuperClass(101, "Parent$mcI$sp") + + /** + * This is the same check, but in value. It should work exactly the same + * as its method counterpart. + */ + class Val[@specialized(Int) T](t: T, expectedXSuper: String) { + val check: T = { + class X extends Parent[T]() + + // get the superclass for X and make sure it's correct + val actualXSuper = (new X).getClass().getSuperclass().getSimpleName() + assert(actualXSuper == expectedXSuper, actualXSuper + " != " + expectedXSuper) + t + } + } + + new Val("x", "Parent") + new Val(101, "Parent$mcI$sp") + + /** + * NOTE: The the same check, only modified to affect constructors, won't + * work since the class X definition will always be lifted to become a + * member of the class, making it impossible to force its duplication. + */ +} diff --git a/test/files/specialized/spec-ame.check b/test/files/specialized/spec-ame.check index 9c1713cc8a..cf18c01191 100644 --- a/test/files/specialized/spec-ame.check +++ b/test/files/specialized/spec-ame.check @@ -1,3 +1,3 @@ abc 10 -3
\ No newline at end of file +2 diff --git a/test/files/specialized/spec-ame.scala b/test/files/specialized/spec-ame.scala index 79ee4217ed..129fb9f447 100644 --- a/test/files/specialized/spec-ame.scala +++ b/test/files/specialized/spec-ame.scala @@ -13,6 +13,9 @@ object Test { def main(args: Array[String]) { println((new A("abc")).foo.value) println((new A(10)).foo.value) + // before fixing SI-7343, this was printing 3. Now it's printing 2, + // since the anonymous class created by doing new B[T] { ... } when + // T = Int is now rewired to B$mcI$sp instead of just B[Int] println(runtime.BoxesRunTime.integerBoxCount) } } diff --git a/test/files/speclib/.gitignore b/test/files/speclib/.gitignore new file mode 100644 index 0000000000..2b26f5dfc5 --- /dev/null +++ b/test/files/speclib/.gitignore @@ -0,0 +1 @@ +instrumented.jar diff --git a/test/junit/scala/collection/TraversableOnceTest.scala b/test/junit/scala/collection/TraversableOnceTest.scala new file mode 100644 index 0000000000..56d8312336 --- /dev/null +++ b/test/junit/scala/collection/TraversableOnceTest.scala @@ -0,0 +1,70 @@ +package scala.collection + +import org.junit.Assert._ +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import scala.util.Random + +@RunWith(classOf[JUnit4]) +/* Test for SI-7614 */ +class TraversableOnceTest { + val list = List.fill(1000)(scala.util.Random.nextInt(10000) - 5000) + + // Basic emptiness check + @Test + def checkEmpty { + def hasException(code: => Any): Boolean = try { + code + false + } catch { + case u: UnsupportedOperationException => true + case t: Throwable => false + } + assert(hasException({ List[Int]().maxBy(_ * 3) }), "maxBy: on empty list should throw UnsupportedOperationException.") + assert(hasException({ List[Int]().minBy(_ * 3) }), "minBy: on empty list should throw UnsupportedOperationException.") + } + + // Basic definition of minBy/maxBy. + @Test + def testCorrectness() = { + def f(x: Int) = -1 * x + val max = list.maxBy(f) + assert(list.forall(f(_) <= f(max)), "f(list.maxBy(f)) should ≥ f(x) where x is any element of list.") + + val min = list.minBy(f) + assert(list.forall(f(_) >= f(min)), "f(list.minBy(f)) should ≤ f(x) where x is any element of list.") + } + + // Ensure that it always returns the first match if more than one element have the same largest/smallest f(x). + // Note that this behavior is not explicitly stated before. + // To make it compatible with the previous implementation, I add this behavior to docs. + @Test + def testReturnTheFirstMatch() = { + val d = List(1, 2, 3, 4, 5, 6, 7, 8) + def f(x: Int) = x % 3; + assert(d.maxBy(f) == 2, "If multiple elements evaluted to the largest value, maxBy should return the first one.") + assert(d.minBy(f) == 3, "If multiple elements evaluted to the largest value, minBy should return the first one.") + } + + // Make sure it evaluates f no more than list.length times. + @Test + def testOnlyEvaluateOnce() = { + var evaluatedCountOfMaxBy = 0 + + val max = list.maxBy(x => { + evaluatedCountOfMaxBy += 1 + x * 10 + }) + assert(evaluatedCountOfMaxBy == list.length, s"maxBy: should evaluate f only ${list.length} times, but it evaluted $evaluatedCountOfMaxBy times.") + + var evaluatedCountOfMinBy = 0 + + val min = list.minBy(x => { + evaluatedCountOfMinBy += 1 + x * 10 + }) + assert(evaluatedCountOfMinBy == list.length, s"minBy: should evaluate f only ${list.length} times, but it evaluted $evaluatedCountOfMinBy times.") + } + +} diff --git a/test/partest b/test/partest index 99a731a49b..0259cdb791 100755 --- a/test/partest +++ b/test/partest @@ -64,7 +64,7 @@ if [ -z "$EXT_CLASSPATH" ] ; then fi done elif [ -f "$SCALA_HOME/build/pack/lib/scala-partest.jar" ] ; then - for lib in `echo "scala-partest scala-library scala-reflect scala-compiler diffutils"`; do + for lib in `echo "scala-partest scala-library scala-parser-combinators scala-xml scala-reflect scala-compiler diffutils"`; do ext="$SCALA_HOME/build/pack/lib/$lib.jar" if [ -z "$EXT_CLASSPATH" ] ; then EXT_CLASSPATH="$ext" |