From 958fb1c6f48aeecf5fc56ad9debbfad8d6d0fc66 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Tue, 3 Aug 2010 18:02:00 +0000 Subject: Generalized the scala sig "look in both attribu... Generalized the scala sig "look in both attribute and annotation" code so it can be reused outside of scalap main. Closes #3717, review by ilyas. --- src/scalap/scala/tools/scalap/Main.scala | 23 ++-------- .../scalap/scalax/rules/scalasig/ScalaSig.scala | 50 +++++++++++++++------- 2 files changed, 37 insertions(+), 36 deletions(-) diff --git a/src/scalap/scala/tools/scalap/Main.scala b/src/scalap/scala/tools/scalap/Main.scala index 88b6c53c46..c2b9324ba9 100644 --- a/src/scalap/scala/tools/scalap/Main.scala +++ b/src/scalap/scala/tools/scalap/Main.scala @@ -10,12 +10,10 @@ package scala.tools.scalap import java.io.{PrintStream, OutputStreamWriter, ByteArrayOutputStream} import scalax.rules.scalasig._ -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. * @@ -104,25 +102,10 @@ object Main { def decompileScala(bytes: Array[Byte], isPackageObject: Boolean): String = { val byteCode = ByteCode(bytes) val classFile = ClassFileParser.parse(byteCode) - 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 => "" - } - } - 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 bytes = ((bytesElem.elementValue match {case ConstValueIndex(index) => constantWrapped(index)}) - .asInstanceOf[StringBytesPair].bytes) - val length = ByteCodecs.decode(bytes) - val scalaSig = ScalaSigAttributeParsers.parse(ByteCode(bytes.take(length))) - parseScalaSignature(scalaSig, isPackageObject) + ScalaSigParser.parse(classFile) match { + case Some(scalaSig) => parseScalaSignature(scalaSig, isPackageObject) + case None => "" } } diff --git a/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala b/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala index d2e50deae3..4614d27727 100644 --- a/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala +++ b/src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala @@ -11,27 +11,45 @@ package scalax package rules package scalasig +import ClassFileParser.{ ConstValueIndex, Annotation } +import scala.reflect.generic.ByteCodecs + object ScalaSigParser { + import Main.{ SCALA_SIG, SCALA_SIG_ANNOTATION, BYTES_VALUE } - def getScalaSig(clazz : Class[_]) : Option[ByteCode] = { - val byteCode = ByteCode.forClass(clazz) - val classFile = ClassFileParser.parse(byteCode) + def scalaSigFromAnnotation(classFile: ClassFile): Option[ScalaSig] = { + import classFile._ + + classFile.annotation(SCALA_SIG_ANNOTATION) map { + case Annotation(_, elements) => + val bytesElem = elements.find(elem => constant(elem.elementNameIndex) == BYTES_VALUE).get + val bytes = ((bytesElem.elementValue match {case ConstValueIndex(index) => constantWrapped(index)}) + .asInstanceOf[StringBytesPair].bytes) + val length = ByteCodecs.decode(bytes) - /* - println("ClassFile version: " + classFile.majorVersion + "." + classFile.minorVersion) - println("Class: " + classFile.className) - println("Superclass: " + classFile.superClass) - println("Interfaces: " + classFile.interfaces.mkString(", ")) - println("Constant pool:") - val constantPool = classFile.header.constants - for (i <- 1 to constantPool.size) println(i + "\t" + constantPool(i)) - */ - - classFile.attribute("ScalaSig").map(_.byteCode) + ScalaSigAttributeParsers.parse(ByteCode(bytes.take(length))) + } } - def parse(clazz : Class[_]) : Option[ScalaSig] = { - getScalaSig(clazz).map(ScalaSigAttributeParsers.parse) + def scalaSigFromAttribute(classFile: ClassFile) : Option[ScalaSig] = + classFile.attribute(SCALA_SIG).map(_.byteCode).map(ScalaSigAttributeParsers.parse) + + def parse(classFile: ClassFile): Option[ScalaSig] = { + val scalaSig = scalaSigFromAttribute(classFile) + + scalaSig match { + // No entries in ScalaSig attribute implies that the signature is stored in the annotation + case Some(ScalaSig(_, _, entries)) if entries.length == 0 => + scalaSigFromAnnotation(classFile) + case x => x + } + } + + def parse(clazz : Class[_]): Option[ScalaSig] = { + val byteCode = ByteCode.forClass(clazz) + val classFile = ClassFileParser.parse(byteCode) + + parse(classFile) } } -- cgit v1.2.3