Skip to content

Commit 6097fe5

Browse files
committed
SI-8679 Add support for ScalaLongSignature attribute in scalap
scalap didn't support really big class files. It was returning an empty String for such files. The reason was that there were only ScalaSignatures taken into account. This commit adds support for ScalaLongSignature. We try to get such an attribute when we didn't find ScalaSignature. Also there's added an additional case to the logic retrieving bytes for a signature. Since ScalaLongSignature can contain many parts, we have to merge their byte arrays. Changes are tested by a new partest-based test. These two files are really big, but it was required (t8679.scala is a reduced version of BigScalaClass - an example attached to JIRA). There are also added TODOs with a JIRA ticket: We have three places, where we process Scala signatures. In the future it would be better to reuse some common logic, if it's possible.
1 parent 454a1dc commit 6097fe5

File tree

6 files changed

+7025
-5
lines changed

6 files changed

+7025
-5
lines changed

src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,7 @@ abstract class ClassfileParser {
923923
Some(ScalaSigBytes(pool.getBytes(entries.toList)))
924924
}
925925

926+
// TODO SI-9296 duplicated code, refactor
926927
/* Parse and return a single annotation. If it is malformed,
927928
* return None.
928929
*/

src/reflect/scala/reflect/runtime/JavaMirrors.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,7 @@ private[scala] trait JavaMirrors extends internal.SymbolTable with api.JavaUnive
591591
// don't use classOf[scala.reflect.ScalaSignature] here, because it will use getClass.getClassLoader, not mirror's classLoader
592592
// don't use asInstanceOf either because of the same reason (lol, I cannot believe I fell for it)
593593
// don't use structural types to simplify reflective invocations because of the same reason
594+
// TODO SI-9296 duplicated code, refactor
594595
def loadAnnotation(name: String): Option[java.lang.annotation.Annotation] =
595596
tryJavaClass(name) flatMap { annotClass =>
596597
val anns = jclazz.getAnnotations

src/scalap/scala/tools/scalap/Main.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import scalax.rules.scalasig._
2828
class Main {
2929
val SCALA_SIG = "ScalaSig"
3030
val SCALA_SIG_ANNOTATION = "Lscala/reflect/ScalaSignature;"
31+
val SCALA_LONG_SIG_ANNOTATION = "Lscala/reflect/ScalaLongSignature;"
3132
val BYTES_VALUE = "bytes"
3233

3334
val versionMsg = "Scala classfile decoder %s -- %s\n".format(Properties.versionString, Properties.copyrightString)

src/scalap/scala/tools/scalap/scalax/rules/scalasig/ScalaSig.scala

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,32 @@ package scalasig
1414
import scala.language.postfixOps
1515
import scala.language.implicitConversions
1616

17-
import ClassFileParser.{ ConstValueIndex, Annotation }
17+
import ClassFileParser._
1818
import scala.reflect.internal.pickling.ByteCodecs
1919

2020
object ScalaSigParser {
21-
import Main.{ SCALA_SIG, SCALA_SIG_ANNOTATION, BYTES_VALUE }
21+
import Main.{ BYTES_VALUE, SCALA_LONG_SIG_ANNOTATION, SCALA_SIG, SCALA_SIG_ANNOTATION }
2222

23+
// TODO SI-9296 duplicated code, refactor
2324
def scalaSigFromAnnotation(classFile: ClassFile): Option[ScalaSig] = {
2425
import classFile._
2526

26-
classFile.annotation(SCALA_SIG_ANNOTATION) map {
27+
def getBytes(bytesElem: AnnotationElement): Array[Byte] = bytesElem.elementValue match {
28+
case ConstValueIndex(index) => bytesForIndex(index)
29+
case ArrayValue(signatureParts) => mergedLongSignatureBytes(signatureParts)
30+
}
31+
32+
def mergedLongSignatureBytes(signatureParts: Seq[ElementValue]): Array[Byte] = signatureParts.flatMap {
33+
case ConstValueIndex(index) => bytesForIndex(index)
34+
}(collection.breakOut)
35+
36+
def bytesForIndex(index: Int) = constantWrapped(index).asInstanceOf[StringBytesPair].bytes
37+
38+
classFile.annotation(SCALA_SIG_ANNOTATION)
39+
.orElse(classFile.annotation(SCALA_LONG_SIG_ANNOTATION)).map {
2740
case Annotation(_, elements) =>
2841
val bytesElem = elements.find(elem => constant(elem.elementNameIndex) == BYTES_VALUE).get
29-
val bytes = ((bytesElem.elementValue match {case ConstValueIndex(index) => constantWrapped(index)})
30-
.asInstanceOf[StringBytesPair].bytes)
42+
val bytes = getBytes(bytesElem)
3143
val length = ByteCodecs.decode(bytes)
3244

3345
ScalaSigAttributeParsers.parse(ByteCode(bytes.take(length)))

0 commit comments

Comments
 (0)