diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2013-09-30 06:39:27 -0700 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2013-09-30 06:39:27 -0700 |
commit | 2bba7797028a19b541b5bd88bd2b732e9a58681c (patch) | |
tree | cc2be1c087b4d8ef4b7196639b69f56b1a7e356a | |
parent | b96f6f3ca713dac0e1a59b1b0341cadf7709d623 (diff) | |
parent | 4133eb8454fe35ef11aaedc1a9008d052c913930 (diff) | |
download | scala-2bba7797028a19b541b5bd88bd2b732e9a58681c.tar.gz scala-2bba7797028a19b541b5bd88bd2b732e9a58681c.tar.bz2 scala-2bba7797028a19b541b5bd88bd2b732e9a58681c.zip |
Merge pull request #2991 from xeno-by/topic/unapply-copier
transformers no longer ignore UnApply.fun
-rw-r--r-- | src/compiler/scala/tools/reflect/ToolBoxFactory.scala | 93 | ||||
-rw-r--r-- | src/reflect/scala/reflect/internal/Trees.scala | 2 | ||||
-rw-r--r-- | test/files/run/t7871.check | 1 | ||||
-rw-r--r-- | test/files/run/t7871/Macros_1.scala | 27 | ||||
-rw-r--r-- | test/files/run/t7871/Test_2.scala | 6 |
5 files changed, 92 insertions, 37 deletions
diff --git a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala index b60db38ae7..6a495cfcee 100644 --- a/src/compiler/scala/tools/reflect/ToolBoxFactory.scala +++ b/src/compiler/scala/tools/reflect/ToolBoxFactory.scala @@ -2,9 +2,11 @@ package scala package tools package reflect +import scala.tools.cmd.CommandLineParser +import scala.tools.nsc.Global import scala.tools.nsc.reporters._ import scala.tools.nsc.CompilerCommand -import scala.tools.nsc.io.VirtualDirectory +import scala.tools.nsc.io.{AbstractFile, VirtualDirectory} import scala.tools.nsc.util.AbstractFileClassLoader import scala.reflect.internal.Flags._ import scala.reflect.internal.util.{BatchSourceFile, NoSourceFile, NoFile} @@ -13,6 +15,7 @@ import scala.compat.Platform.EOL import scala.reflect.NameTransformer import scala.reflect.api.JavaUniverse import scala.reflect.io.NoAbstractFile +import scala.reflect.internal.FatalError abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => @@ -28,6 +31,13 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => lazy val classLoader = new AbstractFileClassLoader(virtualDirectory, factorySelf.mirror.classLoader) lazy val mirror: u.Mirror = u.runtimeMirror(classLoader) + lazy val arguments = CommandLineParser.tokenize(options) + lazy val virtualDirectory = + arguments.iterator.sliding(2).collectFirst{ case Seq("-d", dir) => dir } match { + case Some(outDir) => AbstractFile.getDirectory(outDir) + case None => new VirtualDirectory("(memory)", None) + } + class ToolBoxGlobal(settings: scala.tools.nsc.Settings, reporter0: Reporter) extends ReflectGlobal(settings, reporter0, toolBoxSelf.classLoader) { import definitions._ @@ -46,7 +56,6 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => } // should be called after every use of ToolBoxGlobal in order to prevent leaks - // there's the `withCleanupCaches` method defined below, which provides a convenient interface for that def cleanupCaches(): Unit = { perRunCaches.clearAll() undoLog.clear() @@ -55,10 +64,6 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => lastSeenContext = null } - def withCleanupCaches[T](body: => T): T = - try body - finally cleanupCaches() - def verify(expr: Tree): Unit = { // Previously toolboxes used to typecheck their inputs before compiling. // Actually, the initial demo by Martin first typechecked the reified tree, @@ -302,38 +307,47 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => } } - // todo. is not going to work with quoted arguments with embedded whitespaces - lazy val arguments = options.split(" ") + trait CompilerApi { + val compiler: ToolBoxGlobal + val importer: compiler.Importer { val from: u.type } + val exporter: u.Importer { val from: compiler.type } + } - lazy val virtualDirectory = - (arguments zip arguments.tail).collect{ case ("-d", dir) => dir }.lastOption match { - case Some(outDir) => scala.tools.nsc.io.AbstractFile.getDirectory(outDir) - case None => new VirtualDirectory("(memory)", None) + object withCompilerApi { + private object api extends CompilerApi { + lazy val compiler: ToolBoxGlobal = { + try { + val errorFn: String => Unit = msg => frontEnd.log(scala.reflect.internal.util.NoPosition, msg, frontEnd.ERROR) + val command = new CompilerCommand(arguments.toList, errorFn) + command.settings.outputDirs setSingleOutput virtualDirectory + val instance = new ToolBoxGlobal(command.settings, frontEndToReporter(frontEnd, command.settings)) + if (frontEnd.hasErrors) { + throw ToolBoxError( + "reflective compilation has failed: cannot initialize the compiler:" + EOL + EOL + + (frontEnd.infos map (_.msg) mkString EOL) + ) + } + instance + } catch { + case ex: Throwable => + throw ToolBoxError(s"reflective compilation has failed: cannot initialize the compiler due to $ex", ex) + } + } + + lazy val importer = compiler.mkImporter(u) + lazy val exporter = importer.reverse } - lazy val compiler: ToolBoxGlobal = { - try { - val errorFn: String => Unit = msg => frontEnd.log(scala.reflect.internal.util.NoPosition, msg, frontEnd.ERROR) - val command = new CompilerCommand(arguments.toList, errorFn) - command.settings.outputDirs setSingleOutput virtualDirectory - val instance = new ToolBoxGlobal(command.settings, frontEndToReporter(frontEnd, command.settings)) - if (frontEnd.hasErrors) { - throw ToolBoxError( - "reflective compilation has failed: cannot initialize the compiler:" + EOL + EOL + - (frontEnd.infos map (_.msg) mkString EOL) - ) - } - instance - } catch { - case ex: Throwable => - throw ToolBoxError(s"reflective compilation has failed: cannot initialize the compiler due to $ex", ex) + def apply[T](f: CompilerApi => T): T = { + try f(api) + catch { case ex: FatalError => throw ToolBoxError(s"fatal compiler error", ex) } + finally api.compiler.cleanupCaches() } } - lazy val importer = compiler.mkImporter(u) - lazy val exporter = importer.reverse + def typeCheck(tree: u.Tree, expectedType: u.Type, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): u.Tree = withCompilerApi { compilerApi => + import compilerApi._ - def typeCheck(tree: u.Tree, expectedType: u.Type, silent: Boolean = false, withImplicitViewsDisabled: Boolean = false, withMacrosDisabled: Boolean = false): u.Tree = compiler.withCleanupCaches { if (compiler.settings.verbose) println("importing "+tree+", expectedType = "+expectedType) val ctree: compiler.Tree = importer.importTree(tree) val cexpectedType: compiler.Type = importer.importType(expectedType) @@ -354,7 +368,9 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => inferImplicit(tree, viewTpe, isView = true, silent = silent, withMacrosDisabled = withMacrosDisabled, pos = pos) } - private def inferImplicit(tree: u.Tree, pt: u.Type, isView: Boolean, silent: Boolean, withMacrosDisabled: Boolean, pos: u.Position): u.Tree = compiler.withCleanupCaches { + private def inferImplicit(tree: u.Tree, pt: u.Type, isView: Boolean, silent: Boolean, withMacrosDisabled: Boolean, pos: u.Position): u.Tree = withCompilerApi { compilerApi => + import compilerApi._ + if (compiler.settings.verbose) println(s"importing pt=$pt, tree=$tree, pos=$pos") val ctree: compiler.Tree = importer.importTree(tree) val cpt: compiler.Type = importer.importType(pt) @@ -366,28 +382,33 @@ abstract class ToolBoxFactory[U <: JavaUniverse](val u: U) { factorySelf => uitree } - def resetAllAttrs(tree: u.Tree): u.Tree = { + def resetAllAttrs(tree: u.Tree): u.Tree = withCompilerApi { compilerApi => + import compilerApi._ val ctree: compiler.Tree = importer.importTree(tree) val ttree: compiler.Tree = compiler.resetAllAttrs(ctree) val uttree = exporter.importTree(ttree) uttree } - def resetLocalAttrs(tree: u.Tree): u.Tree = { + def resetLocalAttrs(tree: u.Tree): u.Tree = withCompilerApi { compilerApi => + import compilerApi._ val ctree: compiler.Tree = importer.importTree(tree) val ttree: compiler.Tree = compiler.resetLocalAttrs(ctree) val uttree = exporter.importTree(ttree) uttree } - def parse(code: String): u.Tree = { + def parse(code: String): u.Tree = withCompilerApi { compilerApi => + import compilerApi._ if (compiler.settings.verbose) println("parsing "+code) val ctree: compiler.Tree = compiler.parse(code) val utree = exporter.importTree(ctree) utree } - def compile(tree: u.Tree): () => Any = { + def compile(tree: u.Tree): () => Any = withCompilerApi { compilerApi => + import compilerApi._ + if (compiler.settings.verbose) println("importing "+tree) val ctree: compiler.Tree = importer.importTree(tree) diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index b1fc27f832..6ec542c103 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -1383,7 +1383,7 @@ trait Trees extends api.Trees { self: SymbolTable => case Star(elem) => treeCopy.Star(tree, transform(elem)) case UnApply(fun, args) => - treeCopy.UnApply(tree, fun, transformTrees(args)) // bq: see test/.../unapplyContexts2.scala + treeCopy.UnApply(tree, transform(fun), transformTrees(args)) // bq: see test/.../unapplyContexts2.scala case ArrayValue(elemtpt, trees) => treeCopy.ArrayValue(tree, transform(elemtpt), transformTrees(trees)) case ApplyDynamic(qual, args) => diff --git a/test/files/run/t7871.check b/test/files/run/t7871.check new file mode 100644 index 0000000000..ce6efd812d --- /dev/null +++ b/test/files/run/t7871.check @@ -0,0 +1 @@ +(SomeTree,SomeTree) diff --git a/test/files/run/t7871/Macros_1.scala b/test/files/run/t7871/Macros_1.scala new file mode 100644 index 0000000000..778068deb3 --- /dev/null +++ b/test/files/run/t7871/Macros_1.scala @@ -0,0 +1,27 @@ +import scala.reflect.macros.Context +import language.experimental.macros + +trait Tree +case object SomeTree extends Tree + +object NewQuasiquotes { + implicit class QuasiquoteInterpolation(c: StringContext) { + object nq { + def unapply(t: Tree) = macro QuasiquoteMacros.unapplyImpl + } + } +} + +object QuasiquoteMacros { + def unapplyImpl(c: Context)(t: c.Tree) = { + import c.universe._ + q""" + new { + def unapply(t: Tree) = t match { + case SomeTree => Some((SomeTree, SomeTree)) + case _ => None + } + }.unapply($t) + """ + } +} diff --git a/test/files/run/t7871/Test_2.scala b/test/files/run/t7871/Test_2.scala new file mode 100644 index 0000000000..3a0b68b568 --- /dev/null +++ b/test/files/run/t7871/Test_2.scala @@ -0,0 +1,6 @@ +object Test extends App { + import NewQuasiquotes._ + SomeTree match { + case nq"$x + $y" => println((x, y)) + } +} |