aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/scala/async/internal/AsyncAnalysis.scala
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2015-10-09 15:34:59 +1000
committerJason Zaugg <jzaugg@gmail.com>2015-10-09 15:34:59 +1000
commit01b36eae1da662763d969a9c312832a4e7ea1f84 (patch)
treed3bc4adb923e1b47765d0b929942559f078a869c /src/main/scala/scala/async/internal/AsyncAnalysis.scala
parent7263aaad02a75978a0a48f90bf171c66cda4328c (diff)
downloadscala-async-01b36eae1da662763d969a9c312832a4e7ea1f84.tar.gz
scala-async-01b36eae1da662763d969a9c312832a4e7ea1f84.tar.bz2
scala-async-01b36eae1da662763d969a9c312832a4e7ea1f84.zip
Avoid spurious "illegal await" error in IDE with nesting
The presentation compiler runs with `-Ymacro-expand:discard`, which retains the macro expandee in the typechecked trees, rather than substituting in the expansion. This mode was motivated as a means to keep IDE functionality working (e.g. completion, navigation, refactoring) inside macro applications. However, if one has nested async macro applications, as reported in the IDE ticket: https://www.assembla.com/spaces/scala-ide/tickets/1002561 ... the expansion of the outer async application was reporting await calls enclosed by the inner async application. This change tweaks the traversers used for this analysis to stop whenever it sees an async.
Diffstat (limited to 'src/main/scala/scala/async/internal/AsyncAnalysis.scala')
-rw-r--r--src/main/scala/scala/async/internal/AsyncAnalysis.scala20
1 files changed, 15 insertions, 5 deletions
diff --git a/src/main/scala/scala/async/internal/AsyncAnalysis.scala b/src/main/scala/scala/async/internal/AsyncAnalysis.scala
index 6540bdb..6b75493 100644
--- a/src/main/scala/scala/async/internal/AsyncAnalysis.scala
+++ b/src/main/scala/scala/async/internal/AsyncAnalysis.scala
@@ -4,6 +4,7 @@
package scala.async.internal
+import scala.collection.mutable.ListBuffer
import scala.reflect.macros.Context
import scala.collection.mutable
@@ -53,14 +54,13 @@ trait AsyncAnalysis {
}
override def traverse(tree: Tree) {
- def containsAwait = tree exists isAwait
tree match {
- case Try(_, _, _) if containsAwait =>
+ case Try(_, _, _) if containsAwait(tree) =>
reportUnsupportedAwait(tree, "try/catch")
super.traverse(tree)
case Return(_) =>
c.abort(tree.pos, "return is illegal within a async block")
- case DefDef(mods, _, _, _, _, _) if mods.hasFlag(Flag.LAZY) && containsAwait =>
+ case DefDef(mods, _, _, _, _, _) if mods.hasFlag(Flag.LAZY) && containsAwait(tree) =>
reportUnsupportedAwait(tree, "lazy val initializer")
case CaseDef(_, guard, _) if guard exists isAwait =>
// TODO lift this restriction
@@ -74,9 +74,19 @@ trait AsyncAnalysis {
* @return true, if the tree contained an unsupported await.
*/
private def reportUnsupportedAwait(tree: Tree, whyUnsupported: String): Boolean = {
- val badAwaits: List[RefTree] = tree collect {
- case rt: RefTree if isAwait(rt) => rt
+ val badAwaits = ListBuffer[Tree]()
+ object traverser extends Traverser {
+ override def traverse(tree: Tree): Unit = {
+ if (!isAsync(tree))
+ super.traverse(tree)
+ tree match {
+ case rt: RefTree if isAwait(rt) =>
+ badAwaits += rt
+ case _ =>
+ }
+ }
}
+ traverser(tree)
badAwaits foreach {
tree =>
reportError(tree.pos, s"await must not be used under a $whyUnsupported.")