summaryrefslogtreecommitdiff
path: root/src/scalap/scala/tools/scalap/Main.scala
diff options
context:
space:
mode:
authorGilles Dubochet <gilles.dubochet@epfl.ch>2010-03-23 14:38:11 +0000
committerGilles Dubochet <gilles.dubochet@epfl.ch>2010-03-23 14:38:11 +0000
commitef1577a9c5a9f2905e9b89b1508f97127d941bd7 (patch)
tree009b8393710f33c0c4f8d6560a36d270a3c0cab7 /src/scalap/scala/tools/scalap/Main.scala
parentfb8c14ea43d273466b7d01bb00ce4185d9a91091 (diff)
downloadscala-ef1577a9c5a9f2905e9b89b1508f97127d941bd7.tar.gz
scala-ef1577a9c5a9f2905e9b89b1508f97127d941bd7.tar.bz2
scala-ef1577a9c5a9f2905e9b89b1508f97127d941bd7.zip
Scala signature is generated as an annotation (...
Scala signature is generated as an annotation (that is accessible through Java reflection). - compiler generates all pickled Scala signatures as annotations to class files. - compiler can read class files with signature as annotations or old-style signatures as attributes. - Scalap has also been updated to new signatures (contributed by Ilya Sergey: thanks a lot). - FJBG updated to allow entering constant pool strings as byte arrays. - ByteCodecs decode method returns the length of the decoded array. Review by ilyas. Already mostly reviewed by odersky.
Diffstat (limited to 'src/scalap/scala/tools/scalap/Main.scala')
-rw-r--r--src/scalap/scala/tools/scalap/Main.scala38
1 files changed, 30 insertions, 8 deletions
diff --git a/src/scalap/scala/tools/scalap/Main.scala b/src/scalap/scala/tools/scalap/Main.scala
index d386e7a08f..7ac3955d45 100644
--- a/src/scalap/scala/tools/scalap/Main.scala
+++ b/src/scalap/scala/tools/scalap/Main.scala
@@ -9,12 +9,14 @@
package scala.tools.scalap
-import java.io.{File, PrintStream, OutputStreamWriter, ByteArrayOutputStream}
+import java.io.{PrintStream, OutputStreamWriter, ByteArrayOutputStream}
import scalax.rules.scalasig._
-import tools.nsc.io.AbstractFile
+import scalax.rules.scalasig.ClassFileParser.{ConstValueIndex, Annotation}
import tools.nsc.util.{ ClassPath }
import tools.util.PathResolver
import ClassPath.DefaultJavaContext
+import tools.nsc.io.{PlainFile, AbstractFile}
+import scala.reflect.generic.ByteCodecs
/**The main object used to execute scalap on the command-line.
*
@@ -22,6 +24,9 @@ import ClassPath.DefaultJavaContext
*/
object Main {
val SCALA_SIG = "ScalaSig"
+ val SCALA_SIG_ANNOTATION = "Lscala/reflect/ScalaSignature;"
+ val BYTES_VALUE = "bytes"
+
val versionMsg = "Scala classfile decoder " +
Properties.versionString + " -- " +
Properties.copyrightString + "\n"
@@ -97,16 +102,33 @@ object Main {
baos.toString
}
- def getDecompiledScala(bytes: Array[Byte], isPackageObject: Boolean) = {
+ def decompileScala(bytes: Array[Byte], isPackageObject: Boolean): String = {
val byteCode = ByteCode(bytes)
val classFile = ClassFileParser.parse(byteCode)
- val sig = classFile.attribute(SCALA_SIG).map(_.byteCode).map(ScalaSigAttributeParsers.parse)
+ classFile.attribute(SCALA_SIG).map(_.byteCode).map(ScalaSigAttributeParsers.parse) match {
+ // No entries in ScalaSig attribute implies that the signature is stored in the annotation
+ case Some(ScalaSig(_, _, entries)) if entries.length == 0 => unpickleFromAnnotation(classFile, isPackageObject)
+ case Some(scalaSig) => parseScalaSignature(scalaSig, isPackageObject)
+ case None => ""
+ }
+ }
- sig map (x => parseScalaSignature(x, isPackageObject))
+ def unpickleFromAnnotation(classFile: ClassFile, isPackageObject: Boolean): String = {
+ import classFile._
+ classFile.annotation(SCALA_SIG_ANNOTATION) match {
+ case None => ""
+ case Some(Annotation(_, elements)) =>
+ val bytesElem = elements.find(elem => constant(elem.elementNameIndex) == BYTES_VALUE).get
+ val sigString = (bytesElem.elementValue match {case ConstValueIndex(index) => constant(index)}).asInstanceOf[String]
+ val bytes = sigString.getBytes("UTF-8")
+ val length = ByteCodecs.decode(bytes)
+ val scalaSig = ScalaSigAttributeParsers.parse(ByteCode(bytes.take(length)))
+ parseScalaSignature(scalaSig, isPackageObject)
+ }
}
- def decompileScala(bytes: Array[Byte], isPackageObject: Boolean) =
- getDecompiledScala(bytes, isPackageObject) foreach (Console println _)
+
+
/**Executes scalap with the given arguments and classpath for the
* class denoted by <code>classname</code>.
@@ -128,7 +150,7 @@ object Main {
}
val bytes = cfile.toByteArray
if (isScalaFile(bytes)) {
- decompileScala(bytes, isPackageObjectFile(encName))
+ Console.println(decompileScala(bytes, isPackageObjectFile(encName)))
} else {
// construct a reader for the classfile content
val reader = new ByteArrayReader(cfile.toByteArray)