summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/reflect/scala/reflect/api/Symbols.scala1
-rw-r--r--src/reflect/scala/reflect/internal/Symbols.scala6
-rw-r--r--src/reflect/scala/reflect/io/NoAbstractFile.scala1
-rw-r--r--src/reflect/scala/reflect/runtime/JavaMirrors.scala9
-rw-r--r--src/reflect/scala/reflect/runtime/ReflectionUtils.scala71
-rw-r--r--test/files/run/t7044.check14
-rw-r--r--test/files/run/t7044/Macros_1.scala26
-rw-r--r--test/files/run/t7044/Test_2.scala19
8 files changed, 145 insertions, 2 deletions
diff --git a/src/reflect/scala/reflect/api/Symbols.scala b/src/reflect/scala/reflect/api/Symbols.scala
index 22039d22b6..ff7ac3f574 100644
--- a/src/reflect/scala/reflect/api/Symbols.scala
+++ b/src/reflect/scala/reflect/api/Symbols.scala
@@ -280,6 +280,7 @@ trait Symbols { self: Universe =>
*
* @group Basics
*/
+ @deprecated("Use `pos.source.file` instead", "2.11.0")
def associatedFile: scala.reflect.io.AbstractFile
/** A list of annotations attached to this Symbol.
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala
index 35c7a59683..5e81badfad 100644
--- a/src/reflect/scala/reflect/internal/Symbols.scala
+++ b/src/reflect/scala/reflect/internal/Symbols.scala
@@ -3166,8 +3166,10 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
override def associatedFile = (
if (!isTopLevel) super.associatedFile
- else if (_associatedFile eq null) NoAbstractFile // guarantee not null, but save cost of initializing the var
- else _associatedFile
+ else {
+ if (_associatedFile eq null) NoAbstractFile // guarantee not null, but save cost of initializing the var
+ else _associatedFile
+ }
)
override def associatedFile_=(f: AbstractFile) { _associatedFile = f }
diff --git a/src/reflect/scala/reflect/io/NoAbstractFile.scala b/src/reflect/scala/reflect/io/NoAbstractFile.scala
index a4e869ed41..18eca7698d 100644
--- a/src/reflect/scala/reflect/io/NoAbstractFile.scala
+++ b/src/reflect/scala/reflect/io/NoAbstractFile.scala
@@ -31,4 +31,5 @@ object NoAbstractFile extends AbstractFile {
def output: java.io.OutputStream = null
def path: String = ""
override def toByteArray = Array[Byte]()
+ override def toString = "<no file>"
}
diff --git a/src/reflect/scala/reflect/runtime/JavaMirrors.scala b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
index 1c942e8858..de0ad7161b 100644
--- a/src/reflect/scala/reflect/runtime/JavaMirrors.scala
+++ b/src/reflect/scala/reflect/runtime/JavaMirrors.scala
@@ -614,6 +614,7 @@ private[scala] trait JavaMirrors extends internal.SymbolTable with api.JavaUnive
info(s"unpickling Scala $clazz and $module, owner = ${clazz.owner}")
val bytes = ssig.getBytes
val len = ByteCodecs.decode(bytes)
+ assignAssociatedFile(clazz, module, jclazz)
unpickler.unpickle(bytes take len, 0, clazz, module, jclazz.getName)
markAllCompleted(clazz, module)
case None =>
@@ -623,6 +624,7 @@ private[scala] trait JavaMirrors extends internal.SymbolTable with api.JavaUnive
val encoded = slsig flatMap (_.getBytes)
val len = ByteCodecs.decode(encoded)
val decoded = encoded.take(len)
+ assignAssociatedFile(clazz, module, jclazz)
unpickler.unpickle(decoded, 0, clazz, module, jclazz.getName)
markAllCompleted(clazz, module)
case None =>
@@ -664,6 +666,12 @@ private[scala] trait JavaMirrors extends internal.SymbolTable with api.JavaUnive
}
}
+ private def assignAssociatedFile(clazz: Symbol, module: Symbol, jclazz: jClass[_]): Unit = {
+ val associatedFile = ReflectionUtils.associatedFile(jclazz)
+ clazz.associatedFile = associatedFile
+ if (module != NoSymbol) module.associatedFile = associatedFile
+ }
+
/**
* Copy all annotations of Java annotated element `jann` over to Scala symbol `sym`.
* Also creates `@throws` annotations if necessary.
@@ -719,6 +727,7 @@ private[scala] trait JavaMirrors extends internal.SymbolTable with api.JavaUnive
debugInfo("completing from Java " + sym + "/" + clazz.fullName)//debug
assert(sym == clazz || (module != NoSymbol && (sym == module || sym == module.moduleClass)), sym)
+ assignAssociatedFile(clazz, module, jclazz)
propagatePackageBoundary(jclazz, relatedSymbols: _*)
copyAnnotations(clazz, jclazz)
// to do: annotations to set also for module?
diff --git a/src/reflect/scala/reflect/runtime/ReflectionUtils.scala b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala
index d642b25127..a4bd698068 100644
--- a/src/reflect/scala/reflect/runtime/ReflectionUtils.scala
+++ b/src/reflect/scala/reflect/runtime/ReflectionUtils.scala
@@ -9,6 +9,8 @@ package reflect.runtime
import java.lang.{Class => jClass}
import java.lang.reflect.{ Method, InvocationTargetException, UndeclaredThrowableException }
import scala.reflect.internal.util.AbstractFileClassLoader
+import scala.reflect.io._
+import java.io.{File => JFile}
/** A few java-reflection oriented utility functions useful during reflection bootstrapping.
*/
@@ -97,5 +99,74 @@ object ReflectionUtils {
object EnclosedInConstructor extends EnclosedIn(_.getEnclosingConstructor)
object EnclosedInClass extends EnclosedIn(_.getEnclosingClass)
object EnclosedInPackage extends EnclosedIn(_.getPackage)
+
+ def associatedFile(clazz: Class[_]): AbstractFile = {
+ // TODO: I agree with Jason - this implementation isn't something that we'd like to support
+ // therefore I'm having it commented out and this function will now return NoAbstractFile
+ // I think we can keep the source code though, because it can be useful to the others
+ //
+ // def inferAssociatedFile(clazz: Class[_]): AbstractFile = {
+ // // http://stackoverflow.com/questions/227486/find-where-java-class-is-loaded-from
+ // try {
+ // var cl = clazz.getClassLoader()
+ // if (cl == null) {
+ // cl = ClassLoader.getSystemClassLoader()
+ // while (cl != null && cl.getParent != null) cl = cl.getParent
+ // }
+ // var result: AbstractFile = null
+ // if (cl != null) {
+ // val name = clazz.getCanonicalName()
+ // val resource = cl.getResource(name.replace(".", "/") + ".class")
+ // if (resource != null) {
+ // def fromFile(file: String) = AbstractFile.getFile(file)
+ // def fromJarEntry(jarfile: String, entrypath: String) = {
+ // val jar = fromFile(jarfile)
+ // new VirtualFile(clazz.getName, entrypath) {
+ // lazy val impl: AbstractFile = {
+ // def loop(root: AbstractFile, path: List[String]): AbstractFile = {
+ // def find(name: String) = root.iterator.find(_.name == name).getOrElse(NoAbstractFile)
+ // path match {
+ // case step :: Nil => find(step)
+ // case step :: rest => loop(find(step), rest)
+ // case Nil => NoAbstractFile
+ // }
+ // }
+ // loop(ZipArchive.fromFile(new JFile(jarfile)), entrypath.split("/").toList)
+ // }
+ // override def container = impl.container
+ // override def lastModified = impl.lastModified
+ // override def input = impl.input
+ // override def sizeOption = impl.sizeOption
+ // override def underlyingSource = Some(jar)
+ // override def toString = jarfile + "(" + entrypath + ")"
+ // }
+ // }
+ // def fallback() = new VirtualFile(clazz.getName, resource.toString)
+ // result = resource.getProtocol match {
+ // case "file" =>
+ // fromFile(resource.getFile)
+ // case "jar" =>
+ // val intrajarUrl = new java.net.URL(resource.getFile)
+ // intrajarUrl.getProtocol match {
+ // case "file" =>
+ // val file = intrajarUrl.getFile()
+ // val expectedSuffix = "!/" + name.replace(".", "/") + ".class"
+ // if (file.endsWith(expectedSuffix)) fromJarEntry(file.stripSuffix(expectedSuffix), expectedSuffix.substring(2))
+ // else fallback()
+ // case _ => fallback()
+ // }
+ // case _ =>
+ // fallback()
+ // }
+ // }
+ // }
+ // if (result != null) result else NoAbstractFile
+ // } catch {
+ // case _: Exception => NoAbstractFile
+ // }
+ // }
+ // inferAssociatedFile(clazz)
+ NoAbstractFile
+ }
}
diff --git a/test/files/run/t7044.check b/test/files/run/t7044.check
new file mode 100644
index 0000000000..ab523873bf
--- /dev/null
+++ b/test/files/run/t7044.check
@@ -0,0 +1,14 @@
+compile-time
+uninitialized File: <no file>
+initialized File: <no file>
+uninitialized BitSet: <no file>
+initialized BitSet: <no file>
+uninitialized C: Test_2.scala
+initialized C: Test_2.scala
+runtime
+autoinitialized File: <no file> true
+autoinitialized File: <no file> true
+autoinitialized BitSet: <no file> true
+autoinitialized BitSet: <no file> true
+autoinitialized C: <no file> true
+autoinitialized C: <no file> true
diff --git a/test/files/run/t7044/Macros_1.scala b/test/files/run/t7044/Macros_1.scala
new file mode 100644
index 0000000000..3b3f8c3385
--- /dev/null
+++ b/test/files/run/t7044/Macros_1.scala
@@ -0,0 +1,26 @@
+import scala.reflect.macros.whitebox._
+import scala.language.experimental.macros
+
+object Macros {
+ def impl(c: Context) = {
+ var messages = List[String]()
+ def println(msg: String) = messages :+= msg
+
+ import c.universe._
+ def test(tpe: Type): Unit = {
+ val sym = tpe.typeSymbol
+ println(s"uninitialized ${sym.name}: ${sym.pos.source.file.name}")
+ internal.initialize(sym)
+ println(s"initialized ${sym.name}: ${sym.pos.source.file.name}")
+ }
+
+ println("compile-time")
+ test(typeOf[java.io.File])
+ test(typeOf[scala.collection.BitSet])
+ test(c.mirror.staticClass("C").toType)
+
+ q"..${messages.map(msg => q"println($msg)")}"
+ }
+
+ def foo: Any = macro impl
+} \ No newline at end of file
diff --git a/test/files/run/t7044/Test_2.scala b/test/files/run/t7044/Test_2.scala
new file mode 100644
index 0000000000..8dfb349086
--- /dev/null
+++ b/test/files/run/t7044/Test_2.scala
@@ -0,0 +1,19 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{currentMirror => cm}
+
+class C
+
+object Test extends App {
+ def test(tpe: Type): Unit = {
+ val sym = tpe.typeSymbol
+ println(s"autoinitialized ${sym.name}: ${sym.pos.source.file.name} ${sym.pos.source.file.sizeOption.nonEmpty}")
+ internal.initialize(sym)
+ println(s"autoinitialized ${sym.name}: ${sym.pos.source.file.name} ${sym.pos.source.file.sizeOption.nonEmpty}")
+ }
+
+ Macros.foo
+ println("runtime")
+ test(typeOf[java.io.File])
+ test(typeOf[scala.collection.BitSet])
+ test(typeOf[C])
+}