summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-12-06 05:24:14 -0800
committerJason Zaugg <jzaugg@gmail.com>2013-12-06 05:24:14 -0800
commit6926e8d4a0f9bbb6deb29586ef7134b4efa0ca2b (patch)
treeb2078f6dd38128c5d0a295635ddfab2289d789f7
parent49f7414a1ed42f00f0b5e703d01d0327eb103943 (diff)
parent2ea8aad5bc63582b563bb999c96e980597a84084 (diff)
downloadscala-6926e8d4a0f9bbb6deb29586ef7134b4efa0ca2b.tar.gz
scala-6926e8d4a0f9bbb6deb29586ef7134b4efa0ca2b.tar.bz2
scala-6926e8d4a0f9bbb6deb29586ef7134b4efa0ca2b.zip
Merge pull request #3228 from retronym/merge/2.10.x-and-pr-3209-to-master
Merge #3209 and 2.10.x to master
-rw-r--r--src/interactive/scala/tools/nsc/interactive/CompilerControl.scala23
-rw-r--r--src/interactive/scala/tools/nsc/interactive/Global.scala32
-rw-r--r--src/interactive/scala/tools/nsc/interactive/Picklers.scala2
-rw-r--r--src/interactive/scala/tools/nsc/interactive/REPL.scala2
-rw-r--r--src/interactive/scala/tools/nsc/interactive/tests/core/AskCommand.scala4
-rw-r--r--src/library/scala/concurrent/Future.scala5
-rw-r--r--test/files/jvm/future-spec/PromiseTests.scala4
-rw-r--r--test/files/jvm/scala-concurrent-tck.scala4
-rw-r--r--test/files/presentation/ide-t1001388.check1
-rw-r--r--test/files/presentation/ide-t1001388/Test.scala28
-rw-r--r--test/files/presentation/ide-t1001388/src/a/A.scala6
-rw-r--r--test/files/presentation/t7548.check1
-rw-r--r--test/files/presentation/t7548/Test.scala17
-rw-r--r--test/files/presentation/t7548/src/Foo.scala7
-rw-r--r--test/files/presentation/t7548b.check1
-rw-r--r--test/files/presentation/t7548b/Test.scala17
-rw-r--r--test/files/presentation/t7548b/src/Foo.scala12
17 files changed, 137 insertions, 29 deletions
diff --git a/src/interactive/scala/tools/nsc/interactive/CompilerControl.scala b/src/interactive/scala/tools/nsc/interactive/CompilerControl.scala
index 69cae24808..2e4f6b08e9 100644
--- a/src/interactive/scala/tools/nsc/interactive/CompilerControl.scala
+++ b/src/interactive/scala/tools/nsc/interactive/CompilerControl.scala
@@ -186,15 +186,20 @@ trait CompilerControl { self: Global =>
postWorkItem(new AskToDoFirstItem(source))
/** If source is not yet loaded, loads it, and starts a new run, otherwise
- * continues with current pass.
- * Waits until source is fully type checked and returns body in response.
- * @param source The source file that needs to be fully typed.
- * @param response The response, which is set to the fully attributed tree of `source`.
+ * continues with current pass.
+ * Waits until source is fully type checked and returns body in response.
+ * @param source The source file that needs to be fully typed.
+ * @param keepLoaded Whether to keep that file in the PC if it was not loaded before. If
+ the file is already loaded, this flag is ignored.
+ * @param response The response, which is set to the fully attributed tree of `source`.
* If the unit corresponding to `source` has been removed in the meantime
* the a NoSuchUnitError is raised in the response.
*/
- def askLoadedTyped(source: SourceFile, response: Response[Tree]) =
- postWorkItem(new AskLoadedTypedItem(source, response))
+ def askLoadedTyped(source:SourceFile, keepLoaded: Boolean, response: Response[Tree]): Unit =
+ postWorkItem(new AskLoadedTypedItem(source, keepLoaded, response))
+
+ final def askLoadedTyped(source: SourceFile, response: Response[Tree]): Unit =
+ askLoadedTyped(source, false, response)
/** If source if not yet loaded, get an outline view with askParseEntered.
* If source is loaded, wait for it to be typechecked.
@@ -203,7 +208,7 @@ trait CompilerControl { self: Global =>
*/
def askStructure(keepSrcLoaded: Boolean)(source: SourceFile, response: Response[Tree]) = {
getUnit(source) match {
- case Some(_) => askLoadedTyped(source, response)
+ case Some(_) => askLoadedTyped(source, keepSrcLoaded, response)
case None => askParsedEntered(source, keepSrcLoaded, response)
}
}
@@ -375,8 +380,8 @@ trait CompilerControl { self: Global =>
response raise new MissingResponse
}
- case class AskLoadedTypedItem(source: SourceFile, response: Response[Tree]) extends WorkItem {
- def apply() = self.waitLoadedTyped(source, response, this.onCompilerThread)
+ case class AskLoadedTypedItem(source: SourceFile, keepLoaded: Boolean, response: Response[Tree]) extends WorkItem {
+ def apply() = self.waitLoadedTyped(source, response, keepLoaded, this.onCompilerThread)
override def toString = "wait loaded & typed "+source
def raiseMissing() =
diff --git a/src/interactive/scala/tools/nsc/interactive/Global.scala b/src/interactive/scala/tools/nsc/interactive/Global.scala
index 441398e443..467a210cab 100644
--- a/src/interactive/scala/tools/nsc/interactive/Global.scala
+++ b/src/interactive/scala/tools/nsc/interactive/Global.scala
@@ -327,7 +327,12 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
* @param result The transformed node
*/
override def signalDone(context: Context, old: Tree, result: Tree) {
- if (interruptsEnabled && analyzer.lockedCount == 0) {
+ val canObserveTree = (
+ interruptsEnabled
+ && analyzer.lockedCount == 0
+ && !context.bufferErrors // SI-7558 look away during exploratory typing in "silent mode"
+ )
+ if (canObserveTree) {
if (context.unit.exists &&
result.pos.isOpaqueRange &&
(result.pos includes context.unit.targetPos)) {
@@ -338,14 +343,16 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
}
throw new TyperResult(located)
}
- try {
- checkForMoreWork(old.pos)
- } catch {
- case ex: ValidateException => // Ignore, this will have been reported elsewhere
- debugLog("validate exception caught: "+ex)
- case ex: Throwable =>
- log.flush()
- throw ex
+ else {
+ try {
+ checkForMoreWork(old.pos)
+ } catch {
+ case ex: ValidateException => // Ignore, this will have been reported elsewhere
+ debugLog("validate exception caught: "+ex)
+ case ex: Throwable =>
+ log.flush()
+ throw ex
+ }
}
}
}
@@ -1127,7 +1134,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
}
/** Implements CompilerControl.askLoadedTyped */
- private[interactive] def waitLoadedTyped(source: SourceFile, response: Response[Tree], onSameThread: Boolean = true) {
+ private[interactive] def waitLoadedTyped(source: SourceFile, response: Response[Tree], keepLoaded: Boolean = false, onSameThread: Boolean = true) {
getUnit(source) match {
case Some(unit) =>
if (unit.isUpToDate) {
@@ -1145,7 +1152,10 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "")
case None =>
debugLog("load unit and type")
try reloadSources(List(source))
- finally waitLoadedTyped(source, response, onSameThread)
+ finally {
+ waitLoadedTyped(source, response, onSameThread)
+ if (!keepLoaded) removeUnitOf(source)
+ }
}
}
diff --git a/src/interactive/scala/tools/nsc/interactive/Picklers.scala b/src/interactive/scala/tools/nsc/interactive/Picklers.scala
index 30d3048aa0..1f89e6d3aa 100644
--- a/src/interactive/scala/tools/nsc/interactive/Picklers.scala
+++ b/src/interactive/scala/tools/nsc/interactive/Picklers.scala
@@ -170,7 +170,7 @@ trait Picklers { self: Global =>
implicit def askLoadedTypedItem: CondPickler[AskLoadedTypedItem] =
pkl[SourceFile]
- .wrapped { source => new AskLoadedTypedItem(source, new Response) } { _.source }
+ .wrapped { source => new AskLoadedTypedItem(source, false, new Response) } { _.source }
.asClass (classOf[AskLoadedTypedItem])
implicit def askParsedEnteredItem: CondPickler[AskParsedEnteredItem] =
diff --git a/src/interactive/scala/tools/nsc/interactive/REPL.scala b/src/interactive/scala/tools/nsc/interactive/REPL.scala
index 8e9b0ceee0..ffa61b0524 100644
--- a/src/interactive/scala/tools/nsc/interactive/REPL.scala
+++ b/src/interactive/scala/tools/nsc/interactive/REPL.scala
@@ -118,7 +118,7 @@ object REPL {
comp.askReload(List(toSourceFile(file)), reloadResult)
Thread.sleep(millis.toLong)
println("ask type now")
- comp.askLoadedTyped(toSourceFile(file), typedResult)
+ comp.askLoadedTyped(toSourceFile(file), keepLoaded = true, typedResult)
typedResult.get
case List("typeat", file, off1, off2) =>
doTypeAt(makePos(file, off1, off2))
diff --git a/src/interactive/scala/tools/nsc/interactive/tests/core/AskCommand.scala b/src/interactive/scala/tools/nsc/interactive/tests/core/AskCommand.scala
index 4f9df6808f..d5da52bc13 100644
--- a/src/interactive/scala/tools/nsc/interactive/tests/core/AskCommand.scala
+++ b/src/interactive/scala/tools/nsc/interactive/tests/core/AskCommand.scala
@@ -113,9 +113,9 @@ trait AskTypeAt extends AskCommand {
trait AskLoadedTyped extends AskCommand {
import compiler.Tree
- protected def askLoadedTyped(source: SourceFile)(implicit reporter: Reporter): Response[Tree] = {
+ protected def askLoadedTyped(source: SourceFile, keepLoaded: Boolean = false)(implicit reporter: Reporter): Response[Tree] = {
ask {
- compiler.askLoadedTyped(source, _)
+ compiler.askLoadedTyped(source, keepLoaded, _)
}
}
diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala
index f905785bd6..d271c4cdeb 100644
--- a/src/library/scala/concurrent/Future.scala
+++ b/src/library/scala/concurrent/Future.scala
@@ -384,7 +384,10 @@ trait Future[+T] extends Awaitable[T] {
val p = Promise[U]()
onComplete {
case s @ Success(_) => p complete s
- case _ => p completeWith that
+ case f @ Failure(_) => that onComplete {
+ case s2 @ Success(_) => p complete s2
+ case _ => p complete f // Use the first failure as the failure
+ }
}
p.future
}
diff --git a/test/files/jvm/future-spec/PromiseTests.scala b/test/files/jvm/future-spec/PromiseTests.scala
index 49350586b8..12b9168c5d 100644
--- a/test/files/jvm/future-spec/PromiseTests.scala
+++ b/test/files/jvm/future-spec/PromiseTests.scala
@@ -38,10 +38,10 @@ class PromiseTests extends MinimalScalaTest {
Await.result(failure fallbackTo timedOut, defaultTimeout) mustBe ("Timedout")
Await.result(timedOut fallbackTo empty, defaultTimeout) mustBe ("Timedout")
- Await.result(failure fallbackTo failure fallbackTo timedOut, defaultTimeout) mustBe ("Timedout")
+ Await.result(otherFailure fallbackTo failure fallbackTo timedOut, defaultTimeout) mustBe ("Timedout")
intercept[RuntimeException] {
Await.result(failure fallbackTo otherFailure, defaultTimeout)
- }.getMessage mustBe ("last")
+ }.getMessage mustBe ("br0ken")
}
}
diff --git a/test/files/jvm/scala-concurrent-tck.scala b/test/files/jvm/scala-concurrent-tck.scala
index b431f6b8f8..ce86d4aef0 100644
--- a/test/files/jvm/scala-concurrent-tck.scala
+++ b/test/files/jvm/scala-concurrent-tck.scala
@@ -344,8 +344,8 @@ def testTransformFailure(): Unit = once {
def testFallbackToFailure(): Unit = once {
done =>
val cause = new Exception
- val f = Future { sys.error("failed") }
- val g = Future { throw cause }
+ val f = Future { throw cause }
+ val g = Future { sys.error("failed") }
val h = f fallbackTo g
h onSuccess { case _ => done(false) }
diff --git a/test/files/presentation/ide-t1001388.check b/test/files/presentation/ide-t1001388.check
new file mode 100644
index 0000000000..d58f86d6c6
--- /dev/null
+++ b/test/files/presentation/ide-t1001388.check
@@ -0,0 +1 @@
+Test OK \ No newline at end of file
diff --git a/test/files/presentation/ide-t1001388/Test.scala b/test/files/presentation/ide-t1001388/Test.scala
new file mode 100644
index 0000000000..f6079cf0b2
--- /dev/null
+++ b/test/files/presentation/ide-t1001388/Test.scala
@@ -0,0 +1,28 @@
+import scala.tools.nsc.interactive.tests.InteractiveTest
+import scala.reflect.internal.util.SourceFile
+import scala.tools.nsc.interactive.Response
+
+object Test extends InteractiveTest {
+ override def execute(): Unit = {
+ val sourceA = loadSourceAndWaitUntilTypechecked("A.scala")
+ checkPresent(sourceA)
+ }
+
+ private def loadSourceAndWaitUntilTypechecked(sourceName: String): SourceFile = {
+ val sourceFile = sourceFiles.find(_.file.name == sourceName).head
+ askLoadedTyped(sourceFile).get
+ /* The response to `askLoadedType` may return before `interactive.Global.waitLoadedType`
+ * fully executes. Because this test expects `waitLoadedType` is fully executed before
+ * calling `checkPresent`, with the below no-op presentation compiler request we make
+ * sure this requirement is fulfilled.
+ */
+ compiler.askForResponse(() => ()).get
+ sourceFile
+ }
+
+ private def checkPresent(source: SourceFile): Unit = compiler.getUnitOf(source) match {
+ case Some(unit) => reporter.println("Compilation Unit for " + source.file.name + " still loaded after askLoadedTyped")
+
+ case None => reporter.println("Test OK")
+ }
+}
diff --git a/test/files/presentation/ide-t1001388/src/a/A.scala b/test/files/presentation/ide-t1001388/src/a/A.scala
new file mode 100644
index 0000000000..be09097598
--- /dev/null
+++ b/test/files/presentation/ide-t1001388/src/a/A.scala
@@ -0,0 +1,6 @@
+package a
+
+object A {
+ val tagString = "foo"
+ Seq.empty[Byte].toArray.toSeq
+}
diff --git a/test/files/presentation/t7548.check b/test/files/presentation/t7548.check
new file mode 100644
index 0000000000..5bfb0d27fe
--- /dev/null
+++ b/test/files/presentation/t7548.check
@@ -0,0 +1 @@
+(x: Int)Unit
diff --git a/test/files/presentation/t7548/Test.scala b/test/files/presentation/t7548/Test.scala
new file mode 100644
index 0000000000..94a6048056
--- /dev/null
+++ b/test/files/presentation/t7548/Test.scala
@@ -0,0 +1,17 @@
+import scala.tools.nsc.interactive.tests.InteractiveTest
+
+object Test extends InteractiveTest {
+ override protected def loadSources() { /* don't parse or typecheck sources */ }
+
+ import compiler._
+
+ override def runDefaultTests() {
+ val res = new Response[Tree]
+ val pos = compiler.rangePos(sourceFiles.head, 102,102,102)
+ compiler.askTypeAt(pos, res)
+ res.get match {
+ case Left(tree) => compiler.ask(() => reporter.println(tree.tpe))
+ case Right(ex) => reporter.println(ex)
+ }
+ }
+}
diff --git a/test/files/presentation/t7548/src/Foo.scala b/test/files/presentation/t7548/src/Foo.scala
new file mode 100644
index 0000000000..cc997f6e5f
--- /dev/null
+++ b/test/files/presentation/t7548/src/Foo.scala
@@ -0,0 +1,7 @@
+object Foo {
+ def foo(x: Int) = {}
+ def foo(x: String) = {}
+ def foo(x: Int, y: String) = {}
+
+ foo(2)
+} \ No newline at end of file
diff --git a/test/files/presentation/t7548b.check b/test/files/presentation/t7548b.check
new file mode 100644
index 0000000000..35445fedf6
--- /dev/null
+++ b/test/files/presentation/t7548b.check
@@ -0,0 +1 @@
+Foo.this.I2BI(Foo.this.I).+: (other: Foo.BI.type)Unit
diff --git a/test/files/presentation/t7548b/Test.scala b/test/files/presentation/t7548b/Test.scala
new file mode 100644
index 0000000000..0c022df839
--- /dev/null
+++ b/test/files/presentation/t7548b/Test.scala
@@ -0,0 +1,17 @@
+import scala.tools.nsc.interactive.tests.InteractiveTest
+
+object Test extends InteractiveTest {
+ override protected def loadSources() { /* don't parse or typecheck sources */ }
+
+ import compiler._
+
+ override def runDefaultTests() {
+ val res = new Response[Tree]
+ val pos = compiler.rangePos(sourceFiles.head, 191, 191, 191) // +
+ compiler.askTypeAt(pos, res)
+ res.get match {
+ case Left(tree) => compiler.ask(() => reporter.println(s"$tree: ${tree.tpe}"))
+ case Right(ex) => reporter.println(ex)
+ }
+ }
+}
diff --git a/test/files/presentation/t7548b/src/Foo.scala b/test/files/presentation/t7548b/src/Foo.scala
new file mode 100644
index 0000000000..5cf0a4ef4e
--- /dev/null
+++ b/test/files/presentation/t7548b/src/Foo.scala
@@ -0,0 +1,12 @@
+import language._
+
+object Foo {
+ object I {
+ def +(other: I.type) : Unit = ()
+ }
+ object BI {
+ def +(other: BI.type): Unit = ()
+ }
+ implicit def I2BI(i: I.type): BI.type = BI
+ I.+(BI)
+}