From 7707a763fc09f38c760d10454696ca294fd1c0ec Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 28 Feb 2019 11:27:38 +1000 Subject: [PATCH] [nomerge] Restore findMacroClassloader into Analyzer for the 2.12.x series --- .../scala/tools/nsc/plugins/Plugins.scala | 2 +- .../scala/tools/nsc/typechecker/Macros.scala | 37 +++++++++++++++++++ .../scala/tools/reflect/ReflectGlobal.scala | 20 ++++++---- .../tools/nsc/interpreter/ReplGlobal.scala | 14 ++++--- 4 files changed, 59 insertions(+), 14 deletions(-) diff --git a/src/compiler/scala/tools/nsc/plugins/Plugins.scala b/src/compiler/scala/tools/nsc/plugins/Plugins.scala index 386bdc4ab1a8..d30cf712f8ac 100644 --- a/src/compiler/scala/tools/nsc/plugins/Plugins.scala +++ b/src/compiler/scala/tools/nsc/plugins/Plugins.scala @@ -175,7 +175,7 @@ trait Plugins { global: Global => * * Mirrors with runtime definitions (e.g. Repl) need to adjust this method. */ - protected[scala] def findMacroClassLoader(): ClassLoader = { + protected def findMacroClassLoader(): ClassLoader = { val classpath: Seq[URL] = if (settings.YmacroClasspath.isSetByUser) { for { file <- scala.tools.nsc.util.ClassPath.expandPath(settings.YmacroClasspath.value, true) diff --git a/src/compiler/scala/tools/nsc/typechecker/Macros.scala b/src/compiler/scala/tools/nsc/typechecker/Macros.scala index 5d0e51cd2ea9..6d8d87b8ef7d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Macros.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Macros.scala @@ -64,6 +64,43 @@ trait Macros extends MacroRuntimes with Traces with Helpers { def globalSettings = global.settings + /** Obtains a `ClassLoader` instance used for macro expansion. + * + * By default a new `ScalaClassLoader` is created using the classpath + * from global and the classloader of self as parent. + * + * Mirrors with runtime definitions (e.g. Repl) need to adjust this method. + */ + protected def findMacroClassLoader(): ClassLoader = { + import java.net.URL + import scala.tools.nsc.io.AbstractFile + + val classpath: Seq[URL] = if (settings.YmacroClasspath.isSetByUser) { + for { + file <- scala.tools.nsc.util.ClassPath.expandPath(settings.YmacroClasspath.value, true) + af <- Option(AbstractFile getDirectory file) + } yield af.file.toURI.toURL + } else global.classPath.asURLs + def newLoader: () => ScalaClassLoader.URLClassLoader = () => { + analyzer.macroLogVerbose("macro classloader: initializing from -cp: %s".format(classpath)) + ScalaClassLoader.fromURLs(classpath, getClass.getClassLoader) + } + + val policy = settings.YcacheMacroClassLoader.value + val cache = Macros.macroClassLoadersCache + val disableCache = policy == settings.CachePolicy.None.name + val checkStamps = policy == settings.CachePolicy.LastModified.name + cache.checkCacheability(classpath, checkStamps, disableCache) match { + case Left(msg) => + analyzer.macroLogVerbose(s"macro classloader: $msg.") + val loader = newLoader() + closeableRegistry.registerClosable(loader) + loader + case Right(paths) => + cache.getOrCreate(paths, newLoader, closeableRegistry, checkStamps) + } + } + /** `MacroImplBinding` and its companion module are responsible for * serialization/deserialization of macro def -> impl bindings. * diff --git a/src/compiler/scala/tools/reflect/ReflectGlobal.scala b/src/compiler/scala/tools/reflect/ReflectGlobal.scala index 2efd699e9f44..9fea65d111ee 100644 --- a/src/compiler/scala/tools/reflect/ReflectGlobal.scala +++ b/src/compiler/scala/tools/reflect/ReflectGlobal.scala @@ -25,14 +25,18 @@ import scala.tools.nsc.typechecker.Analyzer class ReflectGlobal(currentSettings: Settings, reporter: Reporter, override val rootClassLoader: ClassLoader) extends Global(currentSettings, reporter) with scala.tools.reflect.ReflectSetup with scala.reflect.runtime.SymbolTable { - /** Obtains the classLoader used for runtime macro expansion. - * - * Macro expansion can use everything available in `global.classPath` or `rootClassLoader`. - * The `rootClassLoader` is used to obtain runtime defined macros. - */ - override protected[scala] def findMacroClassLoader(): ClassLoader = { - val classpath = classPath.asURLs - perRunCaches.recordClassloader(ScalaClassLoader.fromURLs(classpath, rootClassLoader)) + override lazy val analyzer = new { + val global: ReflectGlobal.this.type = ReflectGlobal.this + } with Analyzer { + /** Obtains the classLoader used for runtime macro expansion. + * + * Macro expansion can use everything available in [[global.classPath]] or [[rootClassLoader]]. + * The [[rootClassLoader]] is used to obtain runtime defined macros. + */ + override protected def findMacroClassLoader(): ClassLoader = { + val classpath = global.classPath.asURLs + ScalaClassLoader.fromURLs(classpath, rootClassLoader) + } } override def transformedType(sym: Symbol) = diff --git a/src/repl/scala/tools/nsc/interpreter/ReplGlobal.scala b/src/repl/scala/tools/nsc/interpreter/ReplGlobal.scala index 72b5a7424ceb..f3455a2b094a 100644 --- a/src/repl/scala/tools/nsc/interpreter/ReplGlobal.scala +++ b/src/repl/scala/tools/nsc/interpreter/ReplGlobal.scala @@ -30,11 +30,15 @@ trait ReplGlobal extends Global { super.abort(msg) } - override protected[scala] def findMacroClassLoader(): ClassLoader = { - val loader = super.findMacroClassLoader - analyzer.macroLogVerbose("macro classloader: initializing from a REPL classloader: %s".format(classPath.asURLs)) - val virtualDirectory = analyzer.globalSettings.outputDirs.getSingleOutput.get - new util.AbstractFileClassLoader(virtualDirectory, loader) {} + override lazy val analyzer = new { + val global: ReplGlobal.this.type = ReplGlobal.this + } with Analyzer { + override protected def findMacroClassLoader(): ClassLoader = { + val loader = super.findMacroClassLoader + macroLogVerbose("macro classloader: initializing from a REPL classloader: %s".format(global.classPath.asURLs)) + val virtualDirectory = globalSettings.outputDirs.getSingleOutput.get + new util.AbstractFileClassLoader(virtualDirectory, loader) {} + } } override def optimizerClassPath(base: ClassPath): ClassPath = {