summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Scanners.scala34
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala2
-rwxr-xr-xsrc/compiler/scala/tools/nsc/doc/base/MemberLookupBase.scala33
-rw-r--r--src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala25
-rw-r--r--src/compiler/scala/tools/nsc/interactive/Global.scala1
-rw-r--r--src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Macros.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala7
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala14
-rw-r--r--src/library/scala/collection/mutable/ArrayBuffer.scala2
-rw-r--r--src/library/scala/concurrent/Future.scala12
-rw-r--r--src/library/scala/math/BigInt.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Flags.scala2
-rw-r--r--src/reflect/scala/reflect/internal/util/Statistics.scala2
-rw-r--r--test/disabled/jvm/scala-concurrent-tck-akka.scala391
-rw-r--r--test/disabled/presentation/akka/src/akka/dispatch/Future.scala832
-rw-r--r--test/disabled/presentation/akka/src/pi.scala108
-rw-r--r--test/files/pos/annotated-original/C_2.scala7
-rw-r--r--test/files/pos/annotated-original/M_1.scala7
-rw-r--r--test/files/pos/t5744/Macros_1.scala22
-rw-r--r--test/files/pos/t5744/Test_2.scala6
-rw-r--r--test/files/pos/t7091.scala7
-rwxr-xr-xtest/files/presentation/doc/doc.scala22
-rw-r--r--test/files/presentation/ide-t1000567.check1
-rw-r--r--test/files/presentation/ide-t1000567/Runner.scala15
-rw-r--r--test/files/presentation/ide-t1000567/src/a/a.scala5
-rw-r--r--test/files/presentation/ide-t1000567/src/b/b.scala5
-rw-r--r--test/files/presentation/memory-leaks/MemoryLeaksTest.scala2
-rw-r--r--test/files/run/annotatedRetyping.check6
-rw-r--r--test/files/run/annotatedRetyping.scala62
31 files changed, 224 insertions, 1424 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
index 3025e4c440..1554be6ebb 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
@@ -133,24 +133,16 @@ trait Scanners extends ScannersCommon {
/** Should doc comments be built? */
def buildDocs: Boolean = forScaladoc
- /** buffer for the documentation comment
+ /** holder for the documentation comment
*/
- var docBuffer: StringBuilder = null
- var docPos: Position = null
+ var docComment: DocComment = null
- /** Return current docBuffer and set docBuffer to null */
def flushDoc: DocComment = {
- val ret = if (docBuffer != null) DocComment(docBuffer.toString, docPos) else null
- docBuffer = null
+ val ret = docComment
+ docComment = null
ret
}
- /** add the given character to the documentation buffer
- */
- protected def putDocChar(c: Char) {
- if (docBuffer ne null) docBuffer.append(c)
- }
-
protected def foundComment(value: String, start: Int, end: Int) = ()
protected def foundDocComment(value: String, start: Int, end: Int) = ()
@@ -227,11 +219,11 @@ trait Scanners extends ScannersCommon {
while (!sepRegions.isEmpty && sepRegions.head != RBRACE)
sepRegions = sepRegions.tail
if (!sepRegions.isEmpty) sepRegions = sepRegions.tail
- docBuffer = null
+ docComment = null
case RBRACKET | RPAREN =>
if (!sepRegions.isEmpty && sepRegions.head == lastToken)
sepRegions = sepRegions.tail
- docBuffer = null
+ docComment = null
case ARROW =>
if (!sepRegions.isEmpty && sepRegions.head == lastToken)
sepRegions = sepRegions.tail
@@ -537,7 +529,7 @@ trait Scanners extends ScannersCommon {
nextChar()
} while ((ch != CR) && (ch != LF) && (ch != SU))
} else {
- docBuffer = null
+ docComment = null
var openComments = 1
appendToComment()
nextChar()
@@ -545,24 +537,23 @@ trait Scanners extends ScannersCommon {
var buildingDocComment = false
if (ch == '*' && buildDocs) {
buildingDocComment = true
- docBuffer = new StringBuilder("/**")
}
while (openComments > 0) {
do {
do {
if (ch == '/') {
- nextChar(); putDocChar(ch); appendToComment()
+ nextChar(); appendToComment()
if (ch == '*') {
- nextChar(); putDocChar(ch); appendToComment()
+ nextChar(); appendToComment()
openComments += 1
}
}
if (ch != '*' && ch != SU) {
- nextChar(); putDocChar(ch); appendToComment()
+ nextChar(); appendToComment()
}
} while (ch != '*' && ch != SU)
while (ch == '*') {
- nextChar(); putDocChar(ch); appendToComment()
+ nextChar(); appendToComment()
}
} while (ch != '/' && ch != SU)
if (ch == '/') nextChar()
@@ -1297,7 +1288,8 @@ trait Scanners extends ScannersCommon {
}
override def foundDocComment(value: String, start: Int, end: Int) {
- docPos = new RangePosition(unit.source, start, start, end)
+ val docPos = new RangePosition(unit.source, start, start, end)
+ docComment = new DocComment(value, docPos)
unit.comment(docPos, value)
}
}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 5497719f89..add932441d 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -567,7 +567,7 @@ abstract class TreeBuilder {
if (contextBounds.isEmpty) vparamss
else {
val mods = Modifiers(if (owner.isTypeName) PARAMACCESSOR | LOCAL | PRIVATE else PARAM)
- def makeEvidenceParam(tpt: Tree) = ValDef(mods | IMPLICIT, freshTermName(nme.EVIDENCE_PARAM_PREFIX), tpt, EmptyTree)
+ def makeEvidenceParam(tpt: Tree) = ValDef(mods | IMPLICIT | SYNTHETIC, freshTermName(nme.EVIDENCE_PARAM_PREFIX), tpt, EmptyTree)
val evidenceParams = contextBounds map makeEvidenceParam
val vparamssLast = if(vparamss.nonEmpty) vparamss.last else Nil
diff --git a/src/compiler/scala/tools/nsc/doc/base/MemberLookupBase.scala b/src/compiler/scala/tools/nsc/doc/base/MemberLookupBase.scala
index 216157e19a..8d80333195 100755
--- a/src/compiler/scala/tools/nsc/doc/base/MemberLookupBase.scala
+++ b/src/compiler/scala/tools/nsc/doc/base/MemberLookupBase.scala
@@ -10,15 +10,15 @@ import comment._
trait MemberLookupBase {
val global: Global
- val settings: doc.Settings
-
import global._
+
def internalLink(sym: Symbol, site: Symbol): Option[LinkTo]
def chooseLink(links: List[LinkTo]): LinkTo
def toString(link: LinkTo): String
+ def findExternalLink(sym: Symbol, name: String): Option[LinkToExternal]
+ def warnNoLink: Boolean
import global._
- import definitions.{ NothingClass, AnyClass, AnyValClass, AnyRefClass, ListClass }
import rootMirror.{RootPackage, EmptyPackage}
private def isRoot(s: Symbol) = s.isRootSymbol || s.isEmptyPackage || s.isEmptyPackageClass
@@ -83,7 +83,7 @@ trait MemberLookupBase {
}
links match {
case Nil =>
- if (!settings.docNoLinkWarnings.value)
+ if (warnNoLink)
reporter.warning(pos, "Could not find any member to link for \"" + query + "\".")
// (4) if we still haven't found anything, create a tooltip
Tooltip(query)
@@ -95,7 +95,7 @@ trait MemberLookupBase {
if (link == chosen) " [chosen]" else ""
toString(link) + chosenInfo + "\n"
}
- if (!settings.docNoLinkWarnings.value) {
+ if (warnNoLink) {
val allLinks = links.map(linkToString).mkString
reporter.warning(pos,
s"""The link target \"$query\" is ambiguous. Several members fit the target:
@@ -199,29 +199,6 @@ trait MemberLookupBase {
members.reverse
}
-
- def findExternalLink(sym: Symbol, name: String): Option[LinkToExternal] = {
- val sym1 =
- if (sym == AnyClass || sym == AnyRefClass || sym == AnyValClass || sym == NothingClass) ListClass
- else if (sym.isPackage)
- /* Get package object which has associatedFile ne null */
- sym.info.member(newTermName("package"))
- else sym
- sym1.associatedFile.underlyingSource flatMap { src =>
- val path = src.path
- settings.extUrlMapping get path map { url =>
- LinkToExternal(name, url + "#" + name)
- }
- } orElse {
- // Deprecated option.
- settings.extUrlPackageMapping find {
- case (pkg, _) => name startsWith pkg
- } map {
- case (_, url) => LinkToExternal(name, url + "#" + name)
- }
- }
- }
-
def externalSignature(sym: Symbol) = {
sym.info // force it, otherwise we see lazy types
(sym.nameString + sym.signatureString).replaceAll("\\s", "")
diff --git a/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala b/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala
index c7a767f992..23259a4ae8 100644
--- a/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala
+++ b/src/compiler/scala/tools/nsc/doc/model/MemberLookup.scala
@@ -9,6 +9,7 @@ trait MemberLookup extends base.MemberLookupBase {
thisFactory: ModelFactory =>
import global._
+ import definitions.{ NothingClass, AnyClass, AnyValClass, AnyRefClass, ListClass }
override def internalLink(sym: Symbol, site: Symbol): Option[LinkTo] =
findTemplateMaybe(sym) match {
@@ -35,4 +36,28 @@ trait MemberLookup extends base.MemberLookupBase {
mbr.sym.signatureString + " in " + inTpl.sym.toString
case _ => link.toString
}
+
+ override def findExternalLink(sym: Symbol, name: String): Option[LinkToExternal] = {
+ val sym1 =
+ if (sym == AnyClass || sym == AnyRefClass || sym == AnyValClass || sym == NothingClass) ListClass
+ else if (sym.isPackage)
+ /* Get package object which has associatedFile ne null */
+ sym.info.member(newTermName("package"))
+ else sym
+ Option(sym1.associatedFile) flatMap (_.underlyingSource) flatMap { src =>
+ val path = src.path
+ settings.extUrlMapping get path map { url =>
+ LinkToExternal(name, url + "#" + name)
+ }
+ } orElse {
+ // Deprecated option.
+ settings.extUrlPackageMapping find {
+ case (pkg, _) => name startsWith pkg
+ } map {
+ case (_, url) => LinkToExternal(name, url + "#" + name)
+ }
+ }
+ }
+
+ override def warnNoLink = !settings.docNoLinkWarnings.value
}
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index 9bb2d552be..b0318f40c4 100644
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -69,7 +69,6 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
if (verboseIDE) println("[%s][%s]".format(projectName, msg))
override def forInteractive = true
- override def forScaladoc = settings.isScaladoc
/** A map of all loaded files to the rich compilation units that correspond to them.
*/
diff --git a/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala b/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala
index 034a844e2e..5cda0e53fb 100644
--- a/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala
+++ b/src/compiler/scala/tools/nsc/interactive/tests/core/PresentationCompilerInstance.scala
@@ -7,7 +7,7 @@ import reporters.{Reporter => CompilerReporter}
/** Trait encapsulating the creation of a presentation compiler's instance.*/
private[tests] trait PresentationCompilerInstance extends TestSettings {
protected val settings = new Settings
- protected val docSettings = new doc.Settings(_ => ())
+ protected val withDocComments = false
protected val compilerReporter: CompilerReporter = new InteractiveReporter {
override def compiler = PresentationCompilerInstance.this.compiler
@@ -15,7 +15,9 @@ private[tests] trait PresentationCompilerInstance extends TestSettings {
protected lazy val compiler: Global = {
prepareSettings(settings)
- new Global(settings, compilerReporter)
+ new Global(settings, compilerReporter) {
+ override def forScaladoc = withDocComments
+ }
}
/**
diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
index fb8d6b934f..8829a9a92e 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala
@@ -331,7 +331,7 @@ trait Macros extends scala.tools.reflect.FastTrack with Traces {
def param(tree: Tree): Symbol = (
cache.getOrElseUpdate(tree.symbol, {
val sym = tree.symbol
- makeParam(sym.name, sym.pos, implType(sym.isType, sym.tpe), sym getFlag SYNTHETIC)
+ makeParam(sym.name, sym.pos, implType(sym.isType, sym.tpe), sym.flags)
})
)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
index 0992cd7955..f2129992e5 100644
--- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
@@ -67,7 +67,10 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
case t => t
}
acc setInfoAndEnter (tpe cloneInfo acc)
- storeAccessorDefinition(clazz, DefDef(acc, EmptyTree))
+ // Diagnostic for SI-7091
+ if (!accDefs.contains(clazz))
+ reporter.error(sel.pos, s"Internal error: unable to store accessor definition in ${clazz}. clazz.isPackage=${clazz.isPackage}. Accessor required for ${sel} (${showRaw(sel)})")
+ else storeAccessorDefinition(clazz, DefDef(acc, EmptyTree))
acc
}
@@ -288,6 +291,7 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT
currentClass.isTrait
&& sym.isProtected
&& sym.enclClass != currentClass
+ && !sym.owner.isPackageClass // SI-7091 no accessor needed package owned (ie, top level) symbols
&& !sym.owner.isTrait
&& (sym.owner.enclosingPackageClass != currentClass.enclosingPackageClass)
&& (qual.symbol.info.member(sym.name) ne NoSymbol)
diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
index cfe962d65f..81ea5630d0 100644
--- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala
@@ -101,14 +101,9 @@ trait TypeDiagnostics {
"\n(Note that variables need to be initialized to be defined)"
else ""
- /** Only prints the parameter names if they're not synthetic,
- * since "x$1: Int" does not offer any more information than "Int".
- */
private def methodTypeErrorString(tp: Type) = tp match {
case mt @ MethodType(params, resultType) =>
- def forString =
- if (params exists (_.isSynthetic)) params map (_.tpe)
- else params map (_.defString)
+ def forString = params map (_.defString)
forString.mkString("(", ",", ")") + resultType
case x => x.toString
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index c1fcff0c4e..561ca7f382 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -4070,15 +4070,11 @@ trait Typers extends Adaptations with Tags {
def resultingTypeTree(tpe: Type) = {
// we need symbol-ful originals for reification
// hence we go the extra mile to hand-craft tis guy
- val original =
- if (arg1.isType)
- arg1 match {
- case tt @ TypeTree() => Annotated(ann, tt.original)
- // this clause is needed to correctly compile stuff like "new C @D" or "@(inline @getter)"
- case _ => Annotated(ann, arg1)
- }
- else
- tree
+ val original = arg1 match {
+ case tt @ TypeTree() => Annotated(ann, tt.original)
+ // this clause is needed to correctly compile stuff like "new C @D" or "@(inline @getter)"
+ case _ => Annotated(ann, arg1)
+ }
original setType ann.tpe
TypeTree(tpe) setOriginal original setPos tree.pos.focus
}
diff --git a/src/library/scala/collection/mutable/ArrayBuffer.scala b/src/library/scala/collection/mutable/ArrayBuffer.scala
index 0877bfbb69..f1cfd2d69a 100644
--- a/src/library/scala/collection/mutable/ArrayBuffer.scala
+++ b/src/library/scala/collection/mutable/ArrayBuffer.scala
@@ -107,7 +107,7 @@ class ArrayBuffer[A](override protected val initialSize: Int)
* the identity of the buffer. It takes time linear in
* the buffer size.
*
- * @param elem the element to append.
+ * @param elem the element to prepend.
* @return the updated buffer.
*/
def +=:(elem: A): this.type = {
diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala
index 36f3be341f..0670da137c 100644
--- a/src/library/scala/concurrent/Future.scala
+++ b/src/library/scala/concurrent/Future.scala
@@ -299,8 +299,8 @@ trait Future[+T] extends Awaitable[T] {
* val f = future { 5 }
* val g = f filter { _ % 2 == 1 }
* val h = f filter { _ % 2 == 0 }
- * await(g, 0) // evaluates to 5
- * await(h, 0) // throw a NoSuchElementException
+ * Await.result(g, Duration.Zero) // evaluates to 5
+ * Await.result(h, Duration.Zero) // throw a NoSuchElementException
* }}}
*/
def filter(pred: T => Boolean)(implicit executor: ExecutionContext): Future[T] = {
@@ -348,8 +348,8 @@ trait Future[+T] extends Awaitable[T] {
* val h = f collect {
* case x if x > 0 => x * 2
* }
- * await(g, 0) // evaluates to 5
- * await(h, 0) // throw a NoSuchElementException
+ * Await.result(g, Duration.Zero) // evaluates to 5
+ * Await.result(h, Duration.Zero) // throw a NoSuchElementException
* }}}
*/
def collect[S](pf: PartialFunction[T, S])(implicit executor: ExecutionContext): Future[S] = {
@@ -454,7 +454,7 @@ trait Future[+T] extends Awaitable[T] {
* val f = future { sys.error("failed") }
* val g = future { 5 }
* val h = f fallbackTo g
- * await(h, 0) // evaluates to 5
+ * Await.result(h, Duration.Zero) // evaluates to 5
* }}}
*/
def fallbackTo[U >: T](that: Future[U]): Future[U] = {
@@ -634,7 +634,7 @@ object Future {
*
* Example:
* {{{
- * val result = Await.result(Futures.reduce(futures)(_ + _), 5 seconds)
+ * val result = Await.result(Future.reduce(futures)(_ + _), 5 seconds)
* }}}
*/
def reduce[T, R >: T](futures: TraversableOnce[Future[T]])(op: (R, T) => R)(implicit executor: ExecutionContext): Future[R] = {
diff --git a/src/library/scala/math/BigInt.scala b/src/library/scala/math/BigInt.scala
index 8f86fd5aa7..feb538033b 100644
--- a/src/library/scala/math/BigInt.scala
+++ b/src/library/scala/math/BigInt.scala
@@ -247,7 +247,7 @@ class BigInt(val bigInteger: BigInteger) extends ScalaNumber with ScalaNumericCo
*/
def gcd (that: BigInt): BigInt = new BigInt(this.bigInteger.gcd(that.bigInteger))
- /** Returns a BigInt whose value is (this mod m).
+ /** Returns a BigInt whose value is (this mod that).
* This method differs from `%` in that it always returns a non-negative BigInt.
*/
def mod (that: BigInt): BigInt = new BigInt(this.bigInteger.mod(that.bigInteger))
diff --git a/src/reflect/scala/reflect/internal/Flags.scala b/src/reflect/scala/reflect/internal/Flags.scala
index 45c5279574..06f6c46fc3 100644
--- a/src/reflect/scala/reflect/internal/Flags.scala
+++ b/src/reflect/scala/reflect/internal/Flags.scala
@@ -287,7 +287,7 @@ class Flags extends ModifierFlags {
* from Modifiers. Others which may be applied at creation time are:
* SYNTHETIC.
*/
- final val ValueParameterFlags = BYNAMEPARAM | IMPLICIT | DEFAULTPARAM | STABLE
+ final val ValueParameterFlags = BYNAMEPARAM | IMPLICIT | DEFAULTPARAM | STABLE | SYNTHETIC
final val BeanPropertyFlags = DEFERRED | OVERRIDE | STATIC
final val VarianceFlags = COVARIANT | CONTRAVARIANT
diff --git a/src/reflect/scala/reflect/internal/util/Statistics.scala b/src/reflect/scala/reflect/internal/util/Statistics.scala
index b078b7d4f9..0fa798058d 100644
--- a/src/reflect/scala/reflect/internal/util/Statistics.scala
+++ b/src/reflect/scala/reflect/internal/util/Statistics.scala
@@ -109,7 +109,7 @@ quant)
* Quantities with non-empty prefix are printed in the statistics info.
*/
trait Quantity {
- if (prefix.nonEmpty) {
+ if (enabled && prefix.nonEmpty) {
val key = s"${if (underlying != this) underlying.prefix else ""}/$prefix"
qs(key) = this
}
diff --git a/test/disabled/jvm/scala-concurrent-tck-akka.scala b/test/disabled/jvm/scala-concurrent-tck-akka.scala
deleted file mode 100644
index dfd906e59e..0000000000
--- a/test/disabled/jvm/scala-concurrent-tck-akka.scala
+++ /dev/null
@@ -1,391 +0,0 @@
-
-
-import akka.dispatch.{
- Future => future,
- Promise => promise
-}
-import akka.dispatch.Await.{result => await}
-
-// Duration required for await
-import akka.util.Duration
-import java.util.concurrent.TimeUnit
-import TimeUnit._
-
-import scala.concurrent.{
- TimeoutException,
- SyncVar,
- ExecutionException
-}
-//import scala.concurrent.future
-//import scala.concurrent.promise
-//import scala.concurrent.await
-
-
-
-trait TestBase {
-
- implicit val disp = akka.actor.ActorSystem().dispatcher
-
- def once(body: (() => Unit) => Unit) {
- val sv = new SyncVar[Boolean]
- body(() => sv put true)
- sv.take()
- }
-
-}
-
-
-trait FutureCallbacks extends TestBase {
-
- def testOnSuccess(): Unit = once {
- done =>
- var x = 0
- val f = future {
- x = 1
- }
- f onSuccess { case any =>
- done()
- assert(x == 1)
- }
- }
-
- def testOnSuccessWhenCompleted(): Unit = once {
- done =>
- var x = 0
- val f = future {
- x = 1
- }
- f onSuccess { case any =>
- assert(x == 1)
- x = 2
- f onSuccess { case any =>
- assert(x == 2)
- done()
- }
- }
- }
-
- def testOnSuccessWhenFailed(): Unit = once {
- done =>
- val f = future[Unit] {
- done()
- throw new Exception
- }
- f onSuccess { case any =>
- assert(false)
- }
- }
-
- def testOnFailure(): Unit = once {
- done =>
- var x = 0
- val f = future[Unit] {
- x = 1
- throw new Exception
- }
- f onSuccess { case any =>
- done()
- assert(false)
- }
- f onFailure {
- case _ =>
- done()
- assert(x == 1)
- }
- }
-
- def testOnFailureWhenSpecialThrowable(num: Int, cause: Throwable): Unit = once {
- done =>
- val f = future[Unit] {
- throw cause
- }
- f onSuccess { case any =>
- done()
- assert(false)
- }
- f onFailure {
- case e: ExecutionException if (e.getCause == cause) =>
- done()
- case _ =>
- done()
- assert(false)
- }
- }
-
- def testOnFailureWhenTimeoutException(): Unit = once {
- done =>
- val f = future[Unit] {
- throw new TimeoutException()
- }
- f onSuccess { case any =>
- done()
- assert(false)
- }
- f onFailure {
- case e: TimeoutException =>
- done()
- case other =>
- done()
- assert(false)
- }
- }
-
- testOnSuccess()
- testOnSuccessWhenCompleted()
- testOnSuccessWhenFailed()
- testOnFailure()
-// testOnFailureWhenSpecialThrowable(5, new Error)
-// testOnFailureWhenSpecialThrowable(6, new scala.util.control.ControlThrowable { })
-// testOnFailureWhenSpecialThrowable(7, new InterruptedException)
-// testOnFailureWhenTimeoutException()
-
-}
-
-
-trait FutureCombinators extends TestBase {
-
- // map: stub
- def testMapSuccess(): Unit = once {
- done =>
- done()
- }
-
- def testMapFailure(): Unit = once {
- done =>
- done()
- }
-
- // flatMap: stub
- def testFlatMapSuccess(): Unit = once {
- done =>
- done()
- }
-
- def testFlatMapFailure(): Unit = once {
- done =>
- done()
- }
-
- // filter: stub
- def testFilterSuccess(): Unit = once {
- done =>
- done()
- }
-
- def testFilterFailure(): Unit = once {
- done =>
- done()
- }
-
- // foreach: stub
- def testForeachSuccess(): Unit = once {
- done =>
- done()
- }
-
- def testForeachFailure(): Unit = once {
- done =>
- done()
- }
-
- def testRecoverSuccess(): Unit = once {
- done =>
- val cause = new RuntimeException
- val f = future {
- throw cause
- } recover {
- case re: RuntimeException =>
- "recovered"
- } onSuccess { case x =>
- done()
- assert(x == "recovered")
- } onFailure { case any =>
- done()
- assert(false)
- }
- }
-
- def testRecoverFailure(): Unit = once {
- done =>
- val cause = new RuntimeException
- val f = future {
- throw cause
- } recover {
- case te: TimeoutException => "timeout"
- } onSuccess { case x =>
- done()
- assert(false)
- } onFailure { case any =>
- done()
- assert(any == cause)
- }
- }
-
- testMapSuccess()
- testMapFailure()
- testFlatMapSuccess()
- testFlatMapFailure()
- testFilterSuccess()
- testFilterFailure()
- testForeachSuccess()
- testForeachFailure()
- testRecoverSuccess()
- testRecoverFailure()
-
-}
-
-/*
-trait FutureProjections extends TestBase {
-
- def testFailedFailureOnComplete(): Unit = once {
- done =>
- val cause = new RuntimeException
- val f = future {
- throw cause
- }
- f.failed onComplete {
- case Right(t) =>
- assert(t == cause)
- done()
- case Left(t) =>
- assert(false)
- }
- }
-
- def testFailedFailureOnSuccess(): Unit = once {
- done =>
- val cause = new RuntimeException
- val f = future {
- throw cause
- }
- f.failed onSuccess {
- t =>
- assert(t == cause)
- done()
- }
- }
-
- def testFailedSuccessOnComplete(): Unit = once {
- done =>
- val f = future { 0 }
- f.failed onComplete {
- case Right(t) =>
- assert(false)
- case Left(t) =>
- assert(t.isInstanceOf[NoSuchElementException])
- done()
- }
- }
-
- def testFailedSuccessOnFailure(): Unit = once {
- done =>
- val f = future { 0 }
- f.failed onFailure {
- case nsee: NoSuchElementException =>
- done()
- }
- }
-
- def testFailedFailureAwait(): Unit = once {
- done =>
- val cause = new RuntimeException
- val f = future {
- throw cause
- }
- assert(await(0, f.failed) == cause)
- done()
- }
-
- def testFailedSuccessAwait(): Unit = once {
- done =>
- val f = future { 0 }
- try {
- println(await(0, f.failed))
- assert(false)
- } catch {
- case nsee: NoSuchElementException => done()
- }
- }
-
- testFailedFailureOnComplete()
- testFailedFailureOnSuccess()
- testFailedSuccessOnComplete()
- testFailedSuccessOnFailure()
- testFailedFailureAwait()
- //testFailedSuccessAwait()
-
-}
-*/
-
-trait Blocking extends TestBase {
-
- def testAwaitSuccess(): Unit = once {
- done =>
- val f = future { 0 }
- await(f, Duration(500, "ms"))
- done()
- }
-
- def testAwaitFailure(): Unit = once {
- done =>
- val cause = new RuntimeException
- val f = future {
- throw cause
- }
- try {
- await(f, Duration(500, "ms"))
- assert(false)
- } catch {
- case t =>
- assert(t == cause)
- done()
- }
- }
-
- testAwaitSuccess()
- testAwaitFailure()
-
-}
-
-/*
-trait Promises extends TestBase {
-
- def testSuccess(): Unit = once {
- done =>
- val p = promise[Int]()
- val f = p.future
-
- f.onSuccess { x =>
- done()
- assert(x == 5)
- } onFailure { case any =>
- done()
- assert(false)
- }
-
- p.success(5)
- }
-
- testSuccess()
-
-}
-*/
-
-trait Exceptions extends TestBase {
-
-}
-
-
-object Test
-extends App
-with FutureCallbacks
-with FutureCombinators
-/*with FutureProjections*/
-/*with Promises*/
-with Blocking
-with Exceptions
-{
- System.exit(0)
-}
-
-
diff --git a/test/disabled/presentation/akka/src/akka/dispatch/Future.scala b/test/disabled/presentation/akka/src/akka/dispatch/Future.scala
deleted file mode 100644
index 1ad304d726..0000000000
--- a/test/disabled/presentation/akka/src/akka/dispatch/Future.scala
+++ /dev/null
@@ -1,832 +0,0 @@
-/**
- * Copyright (C) 2009-2011 Scalable Solutions AB <http://scalablesolutions.se>
- */
-
-package akka.dispatch
-
-import akka.AkkaException
-import akka.event.EventHandler
-import akka.actor.{ Actor, Channel }
-import akka.util.Duration
-import akka.japi.{ Procedure, Function => JFunc }
-
-import scala.util.continuations._
-
-import java.util.concurrent.locks.ReentrantLock
-import java.util.concurrent.{ ConcurrentLinkedQueue, TimeUnit, Callable }
-import java.util.concurrent.TimeUnit.{ NANOSECONDS => NANOS, MILLISECONDS => MILLIS }
-import java.util.concurrent.atomic.{ AtomicBoolean }
-import java.lang.{ Iterable => JIterable }
-import java.util.{ LinkedList => JLinkedList }
-import scala.collection.mutable.Stack
-import annotation.tailrec
-
-class FutureTimeoutException(message: String, cause: Throwable = null) extends AkkaException(message, cause)
-
-object Futures {
-
- /**
- * Java API, equivalent to Future.apply
- */
- def future[T](body: Callable[T]): Future[T] =
- Future(body.call)
-
- /**
- * Java API, equivalent to Future.apply
- */
- def future[T](body: Callable[T], timeout: Long): Future[T] =
- Future(body.call, timeout)
-
- /**
- * Java API, equivalent to Future.apply
- */
- def future[T](body: Callable[T], dispatcher: MessageDispatcher): Future[T] =
- Future(body.call)(dispatcher)
-
- /**
- * Java API, equivalent to Future.apply
- */
- def future[T](body: Callable[T], timeout: Long, dispatcher: MessageDispatcher): Future[T] =
- Future(body.call, timeout)(dispatcher)
-
- /**
- * Returns a Future to the result of the first future in the list that is completed
- */
- def firstCompletedOf[T](futures: Iterable[Future[T]], timeout: Long = Long.MaxValue): Future[T] = {
- val futureResult = new DefaultCompletableFuture[T](timeout)
-
- val completeFirst: Future[T] => Unit = _.value.foreach(futureResult complete _)
- for (f ← futures) f onComplete completeFirst
-
- futureResult
- }
-
- /**
- * Java API.
- * Returns a Future to the result of the first future in the list that is completed
- */
- def firstCompletedOf[T <: AnyRef](futures: java.lang.Iterable[Future[T]], timeout: Long): Future[T] =
- firstCompletedOf(scala.collection.JavaConversions.iterableAsScalaIterable(futures), timeout)
-
- /**
- * A non-blocking fold over the specified futures.
- * The fold is performed on the thread where the last future is completed,
- * the result will be the first failure of any of the futures, or any failure in the actual fold,
- * or the result of the fold.
- * Example:
- * <pre>
- * val result = Futures.fold(0)(futures)(_ + _).await.result
- * </pre>
- */
- def fold[T, R](zero: R, timeout: Long = Actor.TIMEOUT)(futures: Iterable[Future[T]])(foldFun: (R, T) => R): Future[R] = {
- if (futures.isEmpty) {
- new AlreadyCompletedFuture[R](Right(zero))
- } else {
- val result = new DefaultCompletableFuture[R](timeout)
- val results = new ConcurrentLinkedQueue[T]()
- val allDone = futures.size
-
- val aggregate: Future[T] => Unit = f => if (!result.isCompleted) { //TODO: This is an optimization, is it premature?
- f.value.get match {
- case r: Right[Throwable, T] =>
- results add r.b
- if (results.size == allDone) { //Only one thread can get here
- try {
- result completeWithResult scala.collection.JavaConversions.collectionAsScalaIterable(results).foldLeft(zero)(foldFun)
- } catch {
- case e: Exception =>
- EventHandler.error(e, this, e.getMessage)
- result completeWithException e
- }
- finally {
- results.clear
- }
- }
- case l: Left[Throwable, T] =>
- result completeWithException l.a
- results.clear
- }
- }
-
- futures foreach { _ onComplete aggregate }
- result
- }
- }
-
- /**
- * Java API
- * A non-blocking fold over the specified futures.
- * The fold is performed on the thread where the last future is completed,
- * the result will be the first failure of any of the futures, or any failure in the actual fold,
- * or the result of the fold.
- */
- def fold[T <: AnyRef, R <: AnyRef](zero: R, timeout: Long, futures: java.lang.Iterable[Future[T]], fun: akka.japi.Function2[R, T, R]): Future[R] =
- fold(zero, timeout)(scala.collection.JavaConversions.iterableAsScalaIterable(futures))(fun.apply _)
-
- /**
- * Initiates a fold over the supplied futures where the fold-zero is the result value of the Future that's completed first
- * Example:
- * <pre>
- * val result = Futures.reduce(futures)(_ + _).await.result
- * </pre>
- */
- def reduce[T, R >: T](futures: Iterable[Future[T]], timeout: Long = Actor.TIMEOUT)(op: (R, T) => T): Future[R] = {
- if (futures.isEmpty)
- new AlreadyCompletedFuture[R](Left(new UnsupportedOperationException("empty reduce left")))
- else {
- val result = new DefaultCompletableFuture[R](timeout)
- val seedFound = new AtomicBoolean(false)
- val seedFold: Future[T] => Unit = f => {
- if (seedFound.compareAndSet(false, true)) { //Only the first completed should trigger the fold
- f.value.get match {
- case r: Right[Throwable, T] =>
- result.completeWith(fold(r.b, timeout)(futures.filterNot(_ eq f))(op))
- case l: Left[Throwable, T] =>
- result.completeWithException(l.a)
- }
- }
- }
- for (f ← futures) f onComplete seedFold //Attach the listener to the Futures
- result
- }
- }
-
- /**
- * Java API.
- * Initiates a fold over the supplied futures where the fold-zero is the result value of the Future that's completed first
- */
- def reduce[T <: AnyRef, R >: T](futures: java.lang.Iterable[Future[T]], timeout: Long, fun: akka.japi.Function2[R, T, T]): Future[R] =
- reduce(scala.collection.JavaConversions.iterableAsScalaIterable(futures), timeout)(fun.apply _)
-
- /**
- * Java API.
- * Simple version of Futures.traverse. Transforms a java.lang.Iterable[Future[A]] into a Future[java.util.LinkedList[A]].
- * Useful for reducing many Futures into a single Future.
- */
- def sequence[A](in: JIterable[Future[A]], timeout: Long): Future[JLinkedList[A]] =
- scala.collection.JavaConversions.iterableAsScalaIterable(in).foldLeft(Future(new JLinkedList[A]()))((fr, fa) =>
- for (r ← fr; a ← fa) yield {
- r add a
- r
- })
-
- /**
- * Java API.
- * Simple version of Futures.traverse. Transforms a java.lang.Iterable[Future[A]] into a Future[java.util.LinkedList[A]].
- * Useful for reducing many Futures into a single Future.
- */
- def sequence[A](in: JIterable[Future[A]]): Future[JLinkedList[A]] = sequence(in, Actor.TIMEOUT)
-
- /**
- * Java API.
- * Transforms a java.lang.Iterable[A] into a Future[java.util.LinkedList[B]] using the provided Function A => Future[B].
- * This is useful for performing a parallel map. For example, to apply a function to all items of a list
- * in parallel.
- */
- def traverse[A, B](in: JIterable[A], timeout: Long, fn: JFunc[A, Future[B]]): Future[JLinkedList[B]] =
- scala.collection.JavaConversions.iterableAsScalaIterable(in).foldLeft(Future(new JLinkedList[B]())) { (fr, a) =>
- val fb = fn(a)
- for (r ← fr; b ← fb) yield {
- r add b
- r
- }
- }
-
- /**
- * Java API.
- * Transforms a java.lang.Iterable[A] into a Future[java.util.LinkedList[B]] using the provided Function A => Future[B].
- * This is useful for performing a parallel map. For example, to apply a function to all items of a list
- * in parallel.
- */
- def traverse[A, B](in: JIterable[A], fn: JFunc[A, Future[B]]): Future[JLinkedList[B]] = traverse(in, Actor.TIMEOUT, fn)
-
- // =====================================
- // Deprecations
- // =====================================
-
- /**
- * (Blocking!)
- */
- @deprecated("Will be removed after 1.1, if you must block, use: futures.foreach(_.await)", "1.1")
- def awaitAll(futures: List[Future[_]]): Unit = futures.foreach(_.await)
-
- /**
- * Returns the First Future that is completed (blocking!)
- */
- @deprecated("Will be removed after 1.1, if you must block, use: firstCompletedOf(futures).await", "1.1")
- def awaitOne(futures: List[Future[_]], timeout: Long = Long.MaxValue): Future[_] = firstCompletedOf[Any](futures, timeout).await
-
- /**
- * Applies the supplied function to the specified collection of Futures after awaiting each future to be completed
- */
- @deprecated("Will be removed after 1.1, if you must block, use: futures map { f => fun(f.await) }", "1.1")
- def awaitMap[A, B](in: Traversable[Future[A]])(fun: (Future[A]) => B): Traversable[B] =
- in map { f => fun(f.await) }
-
- /**
- * Returns Future.resultOrException of the first completed of the 2 Futures provided (blocking!)
- */
- @deprecated("Will be removed after 1.1, if you must block, use: firstCompletedOf(List(f1,f2)).await.resultOrException", "1.1")
- def awaitEither[T](f1: Future[T], f2: Future[T]): Option[T] = firstCompletedOf[T](List(f1, f2)).await.resultOrException
-}
-
-object Future {
- /**
- * This method constructs and returns a Future that will eventually hold the result of the execution of the supplied body
- * The execution is performed by the specified Dispatcher.
- */
- def apply[T](body: => T, timeout: Long = Actor.TIMEOUT)(implicit dispatcher: MessageDispatcher): Future[T] =
- dispatcher.dispatchFuture(() => body, timeout)
-
- /**
- * Construct a completable channel
- */
- def channel(timeout: Long = Actor.TIMEOUT) = new Channel[Any] {
- val future = empty[Any](timeout)
- def !(msg: Any) = future completeWithResult msg
- }
-
- /**
- * Create an empty Future with default timeout
- */
- def empty[T](timeout: Long = Actor.TIMEOUT) = new DefaultCompletableFuture[T](timeout)
-
- import scala.collection.mutable.Builder
- import scala.collection.generic.CanBuildFrom
-
- /**
- * Simple version of Futures.traverse. Transforms a Traversable[Future[A]] into a Future[Traversable[A]].
- * Useful for reducing many Futures into a single Future.
- */
- def sequence[A, M[_] <: Traversable[_]](in: M[Future[A]], timeout: Long = Actor.TIMEOUT)(implicit cbf: CanBuildFrom[M[Future[A]], A, M[A]]): Future[M[A]] =
- in.foldLeft(new DefaultCompletableFuture[Builder[A, M[A]]](timeout).completeWithResult(cbf(in)): Future[Builder[A, M[A]]])((fr, fa) => for (r ← fr; a ← fa.asInstanceOf[Future[A]]) yield (r += a)).map(_.result)
-
- /**
- * Transforms a Traversable[A] into a Future[Traversable[B]] using the provided Function A => Future[B].
- * This is useful for performing a parallel map. For example, to apply a function to all items of a list
- * in parallel:
- * <pre>
- * val myFutureList = Futures.traverse(myList)(x => Future(myFunc(x)))
- * </pre>
- */
- def traverse[A, B, M[_] <: Traversable[_]](in: M[A], timeout: Long = Actor.TIMEOUT)(fn: A => Future[B])(implicit cbf: CanBuildFrom[M[A], B, M[B]]): Future[M[B]] =
- in.foldLeft(new DefaultCompletableFuture[Builder[B, M[B]]](timeout).completeWithResult(cbf(in)): Future[Builder[B, M[B]]]) { (fr, a) =>
- val fb = fn(a.asInstanceOf[A])
- for (r ← fr; b ← fb) yield (r += b)
- }.map(_.result)
-
- /**
- * Captures a block that will be transformed into 'Continuation Passing Style' using Scala's Delimited
- * Continuations plugin.
- *
- * Within the block, the result of a Future may be accessed by calling Future.apply. At that point
- * execution is suspended with the rest of the block being stored in a continuation until the result
- * of the Future is available. If an Exception is thrown while processing, it will be contained
- * within the resulting Future.
- *
- * This allows working with Futures in an imperative style without blocking for each result.
- *
- * Completing a Future using 'CompletableFuture << Future' will also suspend execution until the
- * value of the other Future is available.
- *
- * The Delimited Continuations compiler plugin must be enabled in order to use this method.
- */
- def flow[A](body: => A @cps[Future[Any]], timeout: Long = Actor.TIMEOUT): Future[A] = {
- val future = Promise[A](timeout)
- (reset(future.asInstanceOf[CompletableFuture[Any]].completeWithResult(body)): Future[Any]) onComplete { f =>
- val opte = f.exception
- if (opte.isDefined) future completeWithException (opte.get)
- }
- future
- }
-
- private[akka] val callbacksPendingExecution = new ThreadLocal[Option[Stack[() => Unit]]]() {
- override def initialValue = None
- }
-}
-
-sealed trait Future[+T] {
-
- /**
- * For use only within a Future.flow block or another compatible Delimited Continuations reset block.
- *
- * Returns the result of this Future without blocking, by suspending execution and storing it as a
- * continuation until the result is available.
- *
- * If this Future is untyped (a Future[Nothing]), a type parameter must be explicitly provided or
- * execution will fail. The normal result of getting a Future from an ActorRef using !!! will return
- * an untyped Future.
- */
- def apply[A >: T](): A @cps[Future[Any]] = shift(this flatMap (_: A => Future[Any]))
-
- /**
- * Blocks awaiting completion of this Future, then returns the resulting value,
- * or throws the completed exception
- *
- * Scala & Java API
- *
- * throws FutureTimeoutException if this Future times out when waiting for completion
- */
- def get: T = this.await.resultOrException.get
-
- /**
- * Blocks the current thread until the Future has been completed or the
- * timeout has expired. In the case of the timeout expiring a
- * FutureTimeoutException will be thrown.
- */
- def await: Future[T]
-
- /**
- * Blocks the current thread until the Future has been completed or the
- * timeout has expired. The timeout will be the least value of 'atMost' and the timeout
- * supplied at the constructuion of this Future.
- * In the case of the timeout expiring a FutureTimeoutException will be thrown.
- */
- def await(atMost: Duration): Future[T]
-
- /**
- * Blocks the current thread until the Future has been completed. Use
- * caution with this method as it ignores the timeout and will block
- * indefinitely if the Future is never completed.
- */
- @deprecated("Will be removed after 1.1, it's dangerous and can cause deadlocks, agony and insanity.", "1.1")
- def awaitBlocking: Future[T]
-
- /**
- * Tests whether this Future has been completed.
- */
- final def isCompleted: Boolean = value.isDefined
-
- /**
- * Tests whether this Future's timeout has expired.
- *
- * Note that an expired Future may still contain a value, or it may be
- * completed with a value.
- */
- def isExpired: Boolean
-
- /**
- * This Future's timeout in nanoseconds.
- */
- def timeoutInNanos: Long
-
- /**
- * The contained value of this Future. Before this Future is completed
- * the value will be None. After completion the value will be Some(Right(t))
- * if it contains a valid result, or Some(Left(error)) if it contains
- * an exception.
- */
- def value: Option[Either[Throwable, T]]
-
- /**
- * Returns the successful result of this Future if it exists.
- */
- final def result: Option[T] = {
- val v = value
- if (v.isDefined) v.get.right.toOption
- else None
- }
-
- /**
- * Returns the contained exception of this Future if it exists.
- */
- final def exception: Option[Throwable] = {
- val v = value
- if (v.isDefined) v.get.left.toOption
- else None
- }
-
- /**
- * When this Future is completed, apply the provided function to the
- * Future. If the Future has already been completed, this will apply
- * immediately.
- */
- def onComplete(func: Future[T] => Unit): Future[T]
-
- /**
- * When the future is completed with a valid result, apply the provided
- * PartialFunction to the result.
- * <pre>
- * val result = future receive {
- * case Foo => "foo"
- * case Bar => "bar"
- * }.await.result
- * </pre>
- */
- final def receive(pf: PartialFunction[Any, Unit]): Future[T] = onComplete { f =>
- val optr = f.result
- if (optr.isDefined) {
- val r = optr.get
- if (pf.isDefinedAt(r)) pf(r)
- }
- }
-
- /**
- * Creates a new Future by applying a PartialFunction to the successful
- * result of this Future if a match is found, or else return a MatchError.
- * If this Future is completed with an exception then the new Future will
- * also contain this exception.
- * Example:
- * <pre>
- * val future1 = for {
- * a <- actor !!! Req("Hello") collect { case Res(x: Int) => x }
- * b <- actor !!! Req(a) collect { case Res(x: String) => x }
- * c <- actor !!! Req(7) collect { case Res(x: String) => x }
- * } yield b + "-" + c
- * </pre>
- */
- final def collect[A](pf: PartialFunction[Any, A]): Future[A] = {
- val fa = new DefaultCompletableFuture[A](timeoutInNanos, NANOS)
- onComplete { ft =>
- val v = ft.value.get
- fa complete {
- if (v.isLeft) v.asInstanceOf[Either[Throwable, A]]
- else {
- try {
- val r = v.right.get
- if (pf isDefinedAt r) Right(pf(r))
- else Left(new MatchError(r))
- } catch {
- case e: Exception =>
- EventHandler.error(e, this, e.getMessage)
- Left(e)
- }
- }
- }
- }
- fa
- }
-
- /**
- * Creates a new Future that will handle any matching Throwable that this
- * Future might contain. If there is no match, or if this Future contains
- * a valid result then the new Future will contain the same.
- * Example:
- * <pre>
- * Future(6 / 0) failure { case e: ArithmeticException => 0 } // result: 0
- * Future(6 / 0) failure { case e: NotFoundException => 0 } // result: exception
- * Future(6 / 2) failure { case e: ArithmeticException => 0 } // result: 3
- * </pre>
- */
- final def failure[A >: T](pf: PartialFunction[Throwable, A]): Future[A] = {
- val fa = new DefaultCompletableFuture[A](timeoutInNanos, NANOS)
- onComplete { ft =>
- val opte = ft.exception
- fa complete {
- if (opte.isDefined) {
- val e = opte.get
- try {
- if (pf isDefinedAt e) Right(pf(e))
- else Left(e)
- } catch {
- case x: Exception => Left(x)
- }
- } else ft.value.get
- }
- }
- fa
- }
-
- /**
- * Creates a new Future by applying a function to the successful result of
- * this Future. If this Future is completed with an exception then the new
- * Future will also contain this exception.
- * Example:
- * <pre>
- * val future1 = for {
- * a: Int <- actor !!! "Hello" // returns 5
- * b: String <- actor !!! a // returns "10"
- * c: String <- actor !!! 7 // returns "14"
- * } yield b + "-" + c
- * </pre>
- */
- final def map[A](f: T => A): Future[A] = {
- val fa = new DefaultCompletableFuture[A](timeoutInNanos, NANOS)
- onComplete { ft =>
- val optv = ft.value
- if (optv.isDefined) {
- val v = optv.get
- if (v.isLeft)
- fa complete v.asInstanceOf[Either[Throwable, A]]
- else {
- fa complete (try {
- Right(f(v.right.get))
- } catch {
- case e: Exception =>
- EventHandler.error(e, this, e.getMessage)
- Left(e)
- })
- }
- }
- }
- fa
- }
-
- /**
- * Creates a new Future by applying a function to the successful result of
- * this Future, and returns the result of the function as the new Future.
- * If this Future is completed with an exception then the new Future will
- * also contain this exception.
- * Example:
- * <pre>
- * val future1 = for {
- * a: Int <- actor !!! "Hello" // returns 5
- * b: String <- actor !!! a // returns "10"
- * c: String <- actor !!! 7 // returns "14"
- * } yield b + "-" + c
- * </pre>
- */
- final def flatMap[A](f: T => Future[A]): Future[A] = {
- val fa = new DefaultCompletableFuture[A](timeoutInNanos, NANOS)
- onComplete { ft =>
- val optv = ft.value
- if (optv.isDefined) {
- val v = optv.get
- if (v.isLeft)
- fa complete v.asInstanceOf[Either[Throwable, A]]
- else {
- try {
- fa.completeWith(f(v.right.get))
- } catch {
- case e: Exception =>
- EventHandler.error(e, this, e.getMessage)
- fa completeWithException e
- }
- }
- }
- }
- fa
- }
-
- final def foreach(f: T => Unit): Unit = onComplete { ft =>
- val optr = ft.result
- if (optr.isDefined)
- f(optr.get)
- }
-
- final def filter(p: Any => Boolean): Future[Any] = {
- val f = new DefaultCompletableFuture[T](timeoutInNanos, NANOS)
- onComplete { ft =>
- val optv = ft.value
- if (optv.isDefined) {
- val v = optv.get
- if (v.isLeft)
- f complete v
- else {
- val r = v.right.get
- f complete (try {
- if (p(r)) Right(r)
- else Left(new MatchError(r))
- } catch {
- case e: Exception =>
- EventHandler.error(e, this, e.getMessage)
- Left(e)
- })
- }
- }
- }
- f
- }
-
- /**
- * Returns the current result, throws the exception is one has been raised, else returns None
- */
- final def resultOrException: Option[T] = {
- val v = value
- if (v.isDefined) {
- val r = v.get
- if (r.isLeft) throw r.left.get
- else r.right.toOption
- } else None
- }
-
- /* Java API */
- final def onComplete[A >: T](proc: Procedure[Future[A]]): Future[T] = onComplete(proc(_))
-
- final def map[A >: T, B](f: JFunc[A, B]): Future[B] = map(f(_))
-
- final def flatMap[A >: T, B](f: JFunc[A, Future[B]]): Future[B] = flatMap(f(_))
-
- final def foreach[A >: T](proc: Procedure[A]): Unit = foreach(proc(_))
-
- final def filter(p: JFunc[Any, Boolean]): Future[Any] = filter(p(_))
-
-}
-
-object Promise {
-
- def apply[A](timeout: Long): CompletableFuture[A] = new DefaultCompletableFuture[A](timeout)
-
- def apply[A](): CompletableFuture[A] = apply(Actor.TIMEOUT)
-
-}
-
-/**
- * Essentially this is the Promise (or write-side) of a Future (read-side).
- */
-trait CompletableFuture[T] extends Future[T] {
- /**
- * Completes this Future with the specified result, if not already completed.
- * @return this
- */
- def complete(value: Either[Throwable, T]): Future[T]
-
- /**
- * Completes this Future with the specified result, if not already completed.
- * @return this
- */
- final def completeWithResult(result: T): Future[T] = complete(Right(result))
-
- /**
- * Completes this Future with the specified exception, if not already completed.
- * @return this
- */
- final def completeWithException(exception: Throwable): Future[T] = complete(Left(exception))
-
- /**
- * Completes this Future with the specified other Future, when that Future is completed,
- * unless this Future has already been completed.
- * @return this.
- */
- final def completeWith(other: Future[T]): Future[T] = {
- other onComplete { f => complete(f.value.get) }
- this
- }
-
- final def <<(value: T): Future[T] @cps[Future[Any]] = shift { cont: (Future[T] => Future[Any]) => cont(complete(Right(value))) }
-
- final def <<(other: Future[T]): Future[T] @cps[Future[Any]] = shift { cont: (Future[T] => Future[Any]) =>
- val fr = new DefaultCompletableFuture[Any](Actor.TIMEOUT)
- this completeWith other onComplete { f =>
- try {
- fr completeWith cont(f)
- } catch {
- case e: Exception =>
- EventHandler.error(e, this, e.getMessage)
- fr completeWithException e
- }
- }
- fr
- }
-
-}
-
-/**
- * The default concrete Future implementation.
- */
-class DefaultCompletableFuture[T](timeout: Long, timeunit: TimeUnit) extends CompletableFuture[T] {
-
- def this() = this(0, MILLIS)
-
- def this(timeout: Long) = this(timeout, MILLIS)
-
- val timeoutInNanos = timeunit.toNanos(timeout)
- private val _startTimeInNanos = currentTimeInNanos
- private val _lock = new ReentrantLock
- private val _signal = _lock.newCondition
- private var _value: Option[Either[Throwable, T]] = None
- private var _listeners: List[Future[T] => Unit] = Nil
-
- /**
- * Must be called inside _lock.lock<->_lock.unlock
- */
- @tailrec
- private def awaitUnsafe(waitTimeNanos: Long): Boolean = {
- if (_value.isEmpty && waitTimeNanos > 0) {
- val start = currentTimeInNanos
- val remainingNanos = try {
- _signal.awaitNanos(waitTimeNanos)
- } catch {
- case e: InterruptedException =>
- waitTimeNanos - (currentTimeInNanos - start)
- }
- awaitUnsafe(remainingNanos)
- } else {
- _value.isDefined
- }
- }
-
- def await(atMost: Duration) = {
- _lock.lock
- if (try { awaitUnsafe(atMost.toNanos min timeLeft()) } finally { _lock.unlock }) this
- else throw new FutureTimeoutException("Futures timed out after [" + NANOS.toMillis(timeoutInNanos) + "] milliseconds")
- }
-
- def await = {
- _lock.lock
- if (try { awaitUnsafe(timeLeft()) } finally { _lock.unlock }) this
- else throw new FutureTimeoutException("Futures timed out after [" + NANOS.toMillis(timeoutInNanos) + "] milliseconds")
- }
-
- def awaitBlocking = {
- _lock.lock
- try {
- while (_value.isEmpty) {
- _signal.await
- }
- this
- } finally {
- _lock.unlock
- }
- }
-
- def isExpired: Boolean = timeLeft() <= 0
-
- def value: Option[Either[Throwable, T]] = {
- _lock.lock
- try {
- _value
- } finally {
- _lock.unlock
- }
- }
-
- def complete(value: Either[Throwable, T]): DefaultCompletableFuture[T] = {
- _lock.lock
- val notifyTheseListeners = try {
- if (_value.isEmpty && !isExpired) { //Only complete if we aren't expired
- _value = Some(value)
- val existingListeners = _listeners
- _listeners = Nil
- existingListeners
- } else Nil
- } finally {
- _signal.signalAll
- _lock.unlock
- }
-
- if (notifyTheseListeners.nonEmpty) { // Steps to ensure we don't run into a stack-overflow situation
- @tailrec
- def runCallbacks(rest: List[Future[T] => Unit], callbacks: Stack[() => Unit]) {
- if (rest.nonEmpty) {
- notifyCompleted(rest.head)
- while (callbacks.nonEmpty) { callbacks.pop().apply() }
- runCallbacks(rest.tail, callbacks)
- }
- }
-
- val pending = Future.callbacksPendingExecution.get
- if (pending.isDefined) { //Instead of nesting the calls to the callbacks (leading to stack overflow)
- pending.get.push(() => { // Linearize/aggregate callbacks at top level and then execute
- val doNotify = notifyCompleted _ //Hoist closure to avoid garbage
- notifyTheseListeners foreach doNotify
- })
- } else {
- try {
- val callbacks = Stack[() => Unit]() // Allocate new aggregator for pending callbacks
- Future.callbacksPendingExecution.set(Some(callbacks)) // Specify the callback aggregator
- runCallbacks(notifyTheseListeners, callbacks) // Execute callbacks, if they trigger new callbacks, they are aggregated
- } finally { Future.callbacksPendingExecution.set(None) } // Ensure cleanup
- }
- }
-
- this
- }
-
- def onComplete(func: Future[T] => Unit): CompletableFuture[T] = {
- _lock.lock
- val notifyNow = try {
- if (_value.isEmpty) {
- if (!isExpired) { //Only add the listener if the future isn't expired
- _listeners ::= func
- false
- } else false //Will never run the callback since the future is expired
- } else true
- } finally {
- _lock.unlock
- }
-
- if (notifyNow) notifyCompleted(func)
-
- this
- }
-
- private def notifyCompleted(func: Future[T] => Unit) {
- try {
- func(this)
- } catch {
- case e => EventHandler notify EventHandler.Error(e, this)
- }
- }
-
- @inline
- private def currentTimeInNanos: Long = MILLIS.toNanos(System.currentTimeMillis)
- @inline
- private def timeLeft(): Long = timeoutInNanos - (currentTimeInNanos - _startTimeInNanos)
-}
-
-/**
- * An already completed Future is seeded with it's result at creation, is useful for when you are participating in
- * a Future-composition but you already have a value to contribute.
- */
-sealed class AlreadyCompletedFuture[T](suppliedValue: Either[Throwable, T]) extends CompletableFuture[T] {
- val value = Some(suppliedValue)
-
- def complete(value: Either[Throwable, T]): CompletableFuture[T] = this
- def onComplete(func: Future[T] => Unit): Future[T] = { func(this); this }
- def await(atMost: Duration): Future[T] = this
- def await: Future[T] = this
- def awaitBlocking: Future[T] = this
- def isExpired: Boolean = true
- def timeoutInNanos: Long = 0
-}
diff --git a/test/disabled/presentation/akka/src/pi.scala b/test/disabled/presentation/akka/src/pi.scala
deleted file mode 100644
index b4c644052c..0000000000
--- a/test/disabled/presentation/akka/src/pi.scala
+++ /dev/null
@@ -1,108 +0,0 @@
-
-import akka.actor.{Actor, PoisonPill}
-import Actor._
-import akka.routing.{Routing, CyclicIterator}
-import Routing._
-
-import java.util.concurrent.CountDownLatch
-
-object Pi extends App {
-
- calculate/*#*/(nrOfWorkers = 4, nrOfElements = 10000, nrOfMessages = 10000)
-
- // ====================
- // ===== Messages =====
- // ====================
- sealed trait PiMessage
- case object Calculate extends PiMessage/*#*/
- case class Work(start: Int, nrOfElements: Int) extends PiMessage
- case class Result(value: Double) extends PiMessage
-
- // ==================
- // ===== Worker =====
- // ==================
- class Worker extends Actor/*#*/ {
-
- // define the work
- def calculatePiFor(start: Int, nrOfElements: Int): Double = {
- var acc = 0.0
- for (i <- start until (start + nrOfElements))
- acc += 4.0 * (1 - (i % 2) * 2) / (2 * i + 1)
- acc
- }
-
- def receive /*?*/ = {
- case Work(start, nrOfElements) =>
- self reply/*#*/ Result(calculatePiFor(start, nrOfElements)) // perform the work // TODO: this currently returns wrong position for the symbol
- }
- }
-
- // ==================
- // ===== Master =====
- // ==================
- class Master(
- nrOfWorkers: Int, nrOfMessages: Int, nrOfElements: Int, latch: CountDownLatch)
- extends Actor {
-
- var pi: Double = _
- var nrOfResults: Int = _
- var start: Long = _
-
- // create the workers
- val workers = Vector.fill(nrOfWorkers)(actorOf[Worker]./*!*/start())
-
- // wrap them with a load-balancing router
- val router = Routing./*!*/loadBalancerActor(CyclicIterator(workers))./*!*/start()
-
- // message handler
- def receive = {
- case Calculate =>
- // schedule work
- //for (start <- 0 until nrOfMessages) router ! Work(start, nrOfElements)
- for (i <- 0 until nrOfMessages) router ! Work(i * nrOfElements, nrOfElements)
-
- // send a PoisonPill to all workers telling them to shut down themselves
- router./*!*/!(Broadcast(PoisonPill))
-
- // send a PoisonPill to the router, telling him to shut himself down
- router ! PoisonPill
-
- case Result(value) =>
- // handle result from the worker
- pi += value
- nrOfResults/*#*/ += 1
- if (nrOfResults == nrOfMessages) self./*!*/stop()
- }
-
- override def preStart() {
- start = System.currentTimeMillis
- }
-
- override def postStop() {
- // tell the world that the calculation is complete
- println(
- "\n\tPi estimate: \t\t%s\n\tCalculation time: \t%s millis"
- .format(pi, (System.currentTimeMillis - start)))
- latch/*#*/.countDown()
- }
- }
-
- // ==================
- // ===== Run it =====
- // ==================
- def calculate(nrOfWorkers: Int, nrOfElements: Int, nrOfMessages: Int) {
-
- // this latch is only plumbing to know when the calculation is completed
- val latch = new CountDownLatch(1)
-
- // create the master
- val master = actorOf(
- new Master(nrOfWorkers, nrOfMessages, nrOfElements, latch)).start()
-
- // start the calculation
- master ! Calculate
-
- // wait for master to shut down
- latch.await()
- }
-}
diff --git a/test/files/pos/annotated-original/C_2.scala b/test/files/pos/annotated-original/C_2.scala
new file mode 100644
index 0000000000..36a09ffe0c
--- /dev/null
+++ b/test/files/pos/annotated-original/C_2.scala
@@ -0,0 +1,7 @@
+object Bug {
+ M.m {
+ def s = ""
+ M.m(s): @unchecked // error: macro has not been expanded.
+ ???
+ }
+}
diff --git a/test/files/pos/annotated-original/M_1.scala b/test/files/pos/annotated-original/M_1.scala
new file mode 100644
index 0000000000..01654e02cf
--- /dev/null
+++ b/test/files/pos/annotated-original/M_1.scala
@@ -0,0 +1,7 @@
+import language.experimental.macros
+import reflect.macros.Context
+
+object M {
+ def impl(c: Context)(a: c.Expr[Any]) = c.Expr[Any](c.resetLocalAttrs(a.tree))
+ def m(a: Any) = macro impl
+}
diff --git a/test/files/pos/t5744/Macros_1.scala b/test/files/pos/t5744/Macros_1.scala
new file mode 100644
index 0000000000..288a88653d
--- /dev/null
+++ b/test/files/pos/t5744/Macros_1.scala
@@ -0,0 +1,22 @@
+import scala.language.experimental.macros
+import scala.reflect.macros.Context
+
+object Macros {
+ def foo[U: Numeric](x: U) = macro foo_impl[U]
+ def bar[U: Numeric : Equiv, Y <% String](x: U)(implicit s: String) = macro bar_impl[U, Y]
+
+ def foo_impl[U](c: Context)(x: c.Expr[U])(numeric: c.Expr[Numeric[U]]) = {
+ import c.universe._
+ val plusOne = Apply(Select(numeric.tree, newTermName("plus")), List(x.tree, Literal(Constant(1))))
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(plusOne))
+ c.Expr[Unit](body)
+ }
+
+ def bar_impl[U, Y](c: Context)(x: c.Expr[U])(numeric: c.Expr[Numeric[U]], equiv: c.Expr[Equiv[U]], viewAsString: c.Expr[Y => String], s: c.Expr[String]) = {
+ import c.universe._
+ val plusOne = Apply(Select(numeric.tree, newTermName("plus")), List(x.tree, Literal(Constant(1))))
+ val plusLen = Apply(Select(numeric.tree, newTermName("plus")), List(plusOne, Select(s.tree, newTermName("length"))))
+ val body = Apply(Select(Ident(definitions.PredefModule), newTermName("println")), List(plusLen))
+ c.Expr[Unit](body)
+ }
+} \ No newline at end of file
diff --git a/test/files/pos/t5744/Test_2.scala b/test/files/pos/t5744/Test_2.scala
new file mode 100644
index 0000000000..64b57e6032
--- /dev/null
+++ b/test/files/pos/t5744/Test_2.scala
@@ -0,0 +1,6 @@
+object Test extends App {
+ import Macros._
+ foo(42)
+ implicit val s = ""
+ bar(43)
+} \ No newline at end of file
diff --git a/test/files/pos/t7091.scala b/test/files/pos/t7091.scala
new file mode 100644
index 0000000000..72e81a2ea8
--- /dev/null
+++ b/test/files/pos/t7091.scala
@@ -0,0 +1,7 @@
+package p1.p2
+
+protected[p2] class C(var x: Int = 0)
+
+protected[p2] trait T {
+ new C()
+}
diff --git a/test/files/presentation/doc/doc.scala b/test/files/presentation/doc/doc.scala
index 21eabeb284..f9ebd09876 100755
--- a/test/files/presentation/doc/doc.scala
+++ b/test/files/presentation/doc/doc.scala
@@ -7,8 +7,6 @@ import scala.tools.nsc.util._
import scala.tools.nsc.io._
object Test extends InteractiveTest {
- override val settings: doc.Settings = docSettings
-
val tags = Seq(
"@example `\"abb\".permutations = Iterator(abb, bab, bba)`",
"@version 1.0, 09/07/2012",
@@ -29,23 +27,23 @@ object Test extends InteractiveTest {
|class User(c: %sCommented)""".stripMargin.format(comment, tags take nTags mkString "\n", caret)
override lazy val compiler = {
- new {
- override val settings = {
- prepareSettings(Test.this.settings)
- Test.this.settings
- }
- } with Global(settings, compilerReporter) with MemberLookupBase with CommentFactoryBase {
+ prepareSettings(settings)
+ new Global(settings, compilerReporter) with MemberLookupBase with CommentFactoryBase {
outer =>
-
val global: this.type = this
- def chooseLink(links: List[LinkTo]): LinkTo = links.head
- def internalLink(sym: Symbol, site: Symbol) = None
- def toString(link: LinkTo) = link.toString
override lazy val analyzer = new {
val global: outer.type = outer
} with doc.ScaladocAnalyzer
+ def chooseLink(links: List[LinkTo]): LinkTo = links.head
+ def internalLink(sym: Symbol, site: Symbol) = None
+ def toString(link: LinkTo) = link.toString
+ def warnNoLink = false
+ def findExternalLink(sym: Symbol, name: String) = None
+
+ override def forScaladoc = true
+
def getComment(sym: Symbol, source: SourceFile) = {
val docResponse = new Response[(String, String, Position)]
askDocComment(sym, sym.owner, source, docResponse)
diff --git a/test/files/presentation/ide-t1000567.check b/test/files/presentation/ide-t1000567.check
new file mode 100644
index 0000000000..6d62cb3e13
--- /dev/null
+++ b/test/files/presentation/ide-t1000567.check
@@ -0,0 +1 @@
+reload: a.scala, b.scala
diff --git a/test/files/presentation/ide-t1000567/Runner.scala b/test/files/presentation/ide-t1000567/Runner.scala
new file mode 100644
index 0000000000..77a618b60a
--- /dev/null
+++ b/test/files/presentation/ide-t1000567/Runner.scala
@@ -0,0 +1,15 @@
+import scala.tools.nsc.interactive.tests.InteractiveTest
+
+// also known as SI-5013
+
+object Test extends InteractiveTest {
+
+ override def runDefaultTests(): Unit = {
+ val a = sourceFiles.find(_.file.name == "a.scala").head
+ val b = sourceFiles.find(_.file.name == "b.scala").head
+ askLoadedTyped(a).get
+ askLoadedTyped(b).get
+ super.runDefaultTests()
+ }
+
+}
diff --git a/test/files/presentation/ide-t1000567/src/a/a.scala b/test/files/presentation/ide-t1000567/src/a/a.scala
new file mode 100644
index 0000000000..ee21112a3e
--- /dev/null
+++ b/test/files/presentation/ide-t1000567/src/a/a.scala
@@ -0,0 +1,5 @@
+package a
+
+class Foo {
+ protected[Foo] var x = 0
+}
diff --git a/test/files/presentation/ide-t1000567/src/b/b.scala b/test/files/presentation/ide-t1000567/src/b/b.scala
new file mode 100644
index 0000000000..a0185b15cf
--- /dev/null
+++ b/test/files/presentation/ide-t1000567/src/b/b.scala
@@ -0,0 +1,5 @@
+package b
+
+class Bar extends a.Foo {
+ println(x)
+}
diff --git a/test/files/presentation/memory-leaks/MemoryLeaksTest.scala b/test/files/presentation/memory-leaks/MemoryLeaksTest.scala
index 159097cc10..950569c880 100644
--- a/test/files/presentation/memory-leaks/MemoryLeaksTest.scala
+++ b/test/files/presentation/memory-leaks/MemoryLeaksTest.scala
@@ -25,7 +25,7 @@ import scala.tools.nsc.doc
object Test extends InteractiveTest {
final val mega = 1024 * 1024
- override val settings: doc.Settings = docSettings
+ override val withDocComments = true
override def execute(): Unit = memoryConsumptionTest()
diff --git a/test/files/run/annotatedRetyping.check b/test/files/run/annotatedRetyping.check
new file mode 100644
index 0000000000..b296a80526
--- /dev/null
+++ b/test/files/run/annotatedRetyping.check
@@ -0,0 +1,6 @@
+typing List(1, 2).map(((x) => {
+ val another = scala.Tuple2(t.nt, t.tr): @testAnn match {
+ case scala.Tuple2(_, _) => 1
+ };
+ x
+}))
diff --git a/test/files/run/annotatedRetyping.scala b/test/files/run/annotatedRetyping.scala
new file mode 100644
index 0000000000..cf1b0f27b5
--- /dev/null
+++ b/test/files/run/annotatedRetyping.scala
@@ -0,0 +1,62 @@
+import scala.tools.partest._
+import scala.tools.nsc._
+
+object Test extends DirectTest {
+
+ override def extraSettings: String = "-usejavacp"
+
+ def code = """
+ class testAnn extends annotation.Annotation
+
+ object t {
+ def nt = 1
+ def tr = "a"
+ }
+
+ class Test {
+ List(1,2).map(x => {
+ val another = ((t.nt, t.tr): @testAnn) match { case (_, _) => 1 }
+ x
+ })
+ }
+ """.trim
+
+
+ // point of this test: type-check the "Annotated" tree twice. first time the analyzer plugin types it,
+ // second time the typer.
+
+ // bug was that typedAnnotated assigned a type to the Annotated tree. The second type check would consider
+ // the tree as alreadyTyped, which is not cool, the Annotated needs to be transformed into a Typed tree.
+
+ def show() {
+ val global = newCompiler()
+ import global._
+ import analyzer._
+ import collection.{mutable => m}
+
+ object analyzerPlugin extends AnalyzerPlugin {
+ val templates: m.Map[Symbol, (Template, Typer)] = m.Map()
+ override def pluginsTypeSig(tpe: Type, typer: Typer, defTree: Tree, pt: Type): Type = {
+ defTree match {
+ case impl: Template =>
+ templates += typer.context.owner -> (impl, typer)
+
+ case dd: DefDef if dd.symbol.isPrimaryConstructor && templates.contains(dd.symbol.owner) =>
+ val (impl, templTyper) = templates(dd.symbol.owner)
+ for (stat <- impl.body.filterNot(_.isDef)) {
+ println("typing "+ stat)
+ val statsOwner = impl.symbol orElse templTyper.context.owner.newLocalDummy(impl.pos)
+ val tpr = analyzer.newTyper(templTyper.context.make(stat, statsOwner))
+ tpr.typed(stat)
+ }
+
+ case _ =>
+ }
+ tpe
+ }
+ }
+
+ addAnalyzerPlugin(analyzerPlugin)
+ compileString(global)(code)
+ }
+}