From 8542c9b31af57428254b7351514124815006768b Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Mon, 1 Sep 2014 10:07:23 +0200 Subject: [PATCH] Fix SOE with macros in dependencies extraction In some cases, expanded macros report that their original tree and its expansion are the same, thus creating a cyclic chain. This chain may then produce a SOE during dependencies or used names extraction. This kind of problem was already reported in sbt/sbt#1237 and sbt/sbt#1408. Unfortunately, the fix that was applied to the dependencies extraction part was not sufficient. Mark test 'source-dependencies/macro' as passing Fixes #1544 --- .../src/main/scala/xsbt/Dependency.scala | 34 +++++++++++-------- .../macro/{pending => test} | 0 2 files changed, 19 insertions(+), 15 deletions(-) rename sbt/src/sbt-test/source-dependencies/macro/{pending => test} (100%) diff --git a/compile/interface/src/main/scala/xsbt/Dependency.scala b/compile/interface/src/main/scala/xsbt/Dependency.scala index b2b4e012d..5fb688c73 100644 --- a/compile/interface/src/main/scala/xsbt/Dependency.scala +++ b/compile/interface/src/main/scala/xsbt/Dependency.scala @@ -102,6 +102,16 @@ final class Dependency(val global: CallbackGlobal) extends LocateClassFile { } private class ExtractDependenciesByMemberRefTraverser extends ExtractDependenciesTraverser { + + /* + * Some macros appear to contain themselves as original tree. + * We must check that we don't inspect the same tree over and over. + * See https://issues.scala-lang.org/browse/SI-8486 + * https://github.com/sbt/sbt/issues/1237 + * https://github.com/sbt/sbt/issues/1544 + */ + private val inspectedOriginalTrees = collection.mutable.Set.empty[Tree] + override def traverse(tree: Tree): Unit = { tree match { case Import(expr, selectors) => @@ -118,13 +128,13 @@ final class Dependency(val global: CallbackGlobal) extends LocateClassFile { case select: Select => addDependency(select.symbol) /* - * Idents are used in number of situations: - * - to refer to local variable - * - to refer to a top-level package (other packages are nested selections) - * - to refer to a term defined in the same package as an enclosing class; - * this looks fishy, see this thread: - * https://groups.google.com/d/topic/scala-internals/Ms9WUAtokLo/discussion - */ + * Idents are used in number of situations: + * - to refer to local variable + * - to refer to a top-level package (other packages are nested selections) + * - to refer to a term defined in the same package as an enclosing class; + * this looks fishy, see this thread: + * https://groups.google.com/d/topic/scala-internals/Ms9WUAtokLo/discussion + */ case ident: Ident => addDependency(ident.symbol) case typeTree: TypeTree => @@ -136,13 +146,7 @@ final class Dependency(val global: CallbackGlobal) extends LocateClassFile { deps.foreach(addDependency) case Template(parents, self, body) => traverseTrees(body) - /* - * Some macros appear to contain themselves as original tree - * In this case, we don't need to inspect the original tree because - * we already inspected its expansion, which is equal. - * See https://issues.scala-lang.org/browse/SI-8486 - */ - case MacroExpansionOf(original) if original != tree => + case MacroExpansionOf(original) if inspectedOriginalTrees.add(original) => this.traverse(original) case other => () } @@ -191,4 +195,4 @@ final class Dependency(val global: CallbackGlobal) extends LocateClassFile { // for Scala 2.8 and 2.9 this method is provided through SymbolCompat sym.enclosingTopLevelClass -} +} \ No newline at end of file diff --git a/sbt/src/sbt-test/source-dependencies/macro/pending b/sbt/src/sbt-test/source-dependencies/macro/test similarity index 100% rename from sbt/src/sbt-test/source-dependencies/macro/pending rename to sbt/src/sbt-test/source-dependencies/macro/test