diff options
author | Gilles Dubochet <gilles.dubochet@epfl.ch> | 2010-03-23 14:38:11 +0000 |
---|---|---|
committer | Gilles Dubochet <gilles.dubochet@epfl.ch> | 2010-03-23 14:38:11 +0000 |
commit | ef1577a9c5a9f2905e9b89b1508f97127d941bd7 (patch) | |
tree | 009b8393710f33c0c4f8d6560a36d270a3c0cab7 /src/scalap/scala/tools/scalap/Main.scala | |
parent | fb8c14ea43d273466b7d01bb00ce4185d9a91091 (diff) | |
download | scala-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.scala | 38 |
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) |