@@ -519,7 +519,8 @@ abstract class ClassfileParser {
519
519
skipMembers() // methods
520
520
521
521
// attributes now depend on having infos set already
522
- parseAttributes(clazz, classInfo)
522
+ val paramNames = ListBuffer [Name ](null )
523
+ parseAttributes(clazz, isVarargs = false )
523
524
524
525
def queueLoad (): Unit = {
525
526
in.bp = fieldsStartBp
@@ -576,7 +577,7 @@ abstract class ClassfileParser {
576
577
else info
577
578
}
578
579
propagatePackageBoundary(jflags, sym)
579
- parseAttributes(sym, info )
580
+ parseAttributes(sym, isVarargs = false )
580
581
addJavaFlagsAnnotations(sym, jflags)
581
582
getScope(jflags) enter sym
582
583
@@ -611,47 +612,13 @@ abstract class ClassfileParser {
611
612
} else {
612
613
val name = readName()
613
614
val sym = ownerForFlags(jflags).newMethod(name.toTermName, NoPosition , sflags)
614
- var info = pool.getType(sym, u2)
615
- var removedOuterParameter = false
616
- if (name == nme.CONSTRUCTOR )
617
- info match {
618
- case MethodType (params, restpe) =>
619
- // if this is a non-static inner class, remove the explicit outer parameter
620
- val paramsNoOuter = innerClasses getEntry currentClass match {
621
- case Some (entry) if ! entry.jflags.isStatic =>
622
- /* About `clazz.owner.hasPackageFlag` below: scala/bug#5957
623
- * For every nested java class A$B, there are two symbols in the scala compiler.
624
- * 1. created by SymbolLoader, because of the existence of the A$B.class file, owner: package
625
- * 2. created by ClassfileParser of A when reading the inner classes, owner: A
626
- * If symbol 1 gets completed (e.g. because the compiled source mentions `A$B`, not `A#B`), the
627
- * ClassfileParser for 1 executes, and clazz.owner is the package.
628
- */
629
- assert(params.head.tpe.typeSymbol == clazz.owner || clazz.owner.hasPackageFlag, params.head.tpe.typeSymbol + " : " + clazz.owner)
630
- removedOuterParameter = true
631
- params.tail
632
- case _ =>
633
- params
634
- }
635
- val newParams = paramsNoOuter match {
636
- case (init :+ tail) if jflags.isSynthetic =>
637
- // scala/bug#7455 strip trailing dummy argument ("access constructor tag") from synthetic constructors which
638
- // are added when an inner class needs to access a private constructor.
639
- init
640
- case _ =>
641
- paramsNoOuter
642
- }
643
-
644
- info = MethodType (newParams, clazz.tpe)
645
- }
646
615
// Note: the info may be overwritten later with a generic signature
647
616
// parsed from SignatureATTR
648
- sym setInfo info
617
+ val lazyInfo = new JavaSignatureTypeCompleter (name, jflags, index = u2)
618
+ sym.info = lazyInfo
649
619
propagatePackageBoundary(jflags, sym)
650
- parseAttributes(sym, info, removedOuterParameter )
620
+ parseAttributes(sym, jflags.isVarargs )
651
621
addJavaFlagsAnnotations(sym, jflags)
652
- if (jflags.isVarargs)
653
- sym modifyInfo arrayToRepeated
654
-
655
622
getScope(jflags) enter sym
656
623
}
657
624
}
@@ -835,8 +802,7 @@ abstract class ClassfileParser {
835
802
/**
836
803
* Only invoked for java classfiles.
837
804
*/
838
- def parseAttributes (sym : Symbol , symtype : Type , removedOuterParameter : Boolean = false ): Unit = {
839
- var paramNames : ListBuffer [Name ] = null // null means we didn't find any
805
+ def parseAttributes (sym : symbolTable.Symbol , isVarargs : Boolean = false ): Unit = {
840
806
def convertTo (c : Constant , pt : Type ): Constant = {
841
807
if (pt.typeSymbol == BooleanClass && c.tag == IntTag )
842
808
Constant (c.value != 0 )
@@ -850,9 +816,12 @@ abstract class ClassfileParser {
850
816
attrName match {
851
817
case tpnme.SignatureATTR =>
852
818
val sig = pool.getExternalName(u2)
853
- val newType = sigToType(sym, sig.value)
854
- sym.setInfo(newType)
855
-
819
+ if (sym.isClass) {
820
+ sym.setInfo(sigToType(sym, sig.value))
821
+ } else {
822
+ val lazyType = new JavaGenericSignatureTypeCompleter (sig.value, isVarargs)
823
+ sym.setInfo(lazyType)
824
+ }
856
825
case tpnme.SyntheticATTR =>
857
826
sym.setFlag(SYNTHETIC | ARTIFACT )
858
827
in.skip(attrLen)
@@ -868,20 +837,16 @@ abstract class ClassfileParser {
868
837
869
838
case tpnme.ConstantValueATTR =>
870
839
val c = pool.getConstant(u2)
871
- val c1 = convertTo(c, symtype )
840
+ val c1 = convertTo(c, sym.initialize.info.resultType )
872
841
if (c1 ne null ) sym.setInfo(ConstantType (c1))
873
- else devWarning(s " failure to convert $c to $symtype " )
842
+ else devWarning(s " failure to convert $c to ${sym.initialize.info.resultType} " )
874
843
875
844
case tpnme.MethodParametersATTR =>
876
845
def readParamNames (): Unit = {
877
846
import scala .tools .asm .Opcodes .ACC_SYNTHETIC
847
+ val paramNames = ListBuffer [Name ]()
878
848
val paramCount = u1
879
849
var i = 0
880
- if (removedOuterParameter && i < paramCount) {
881
- in.skip(4 )
882
- i += 1
883
- }
884
- paramNames = new ListBuffer ()
885
850
while (i < paramCount) {
886
851
val rawname = pool.getName(u2)
887
852
val access = u2
@@ -893,6 +858,7 @@ abstract class ClassfileParser {
893
858
paramNames += name
894
859
i += 1
895
860
}
861
+ sym.updateAttachment(new ParamNames (paramNames.toList))
896
862
}
897
863
readParamNames()
898
864
@@ -963,26 +929,8 @@ abstract class ClassfileParser {
963
929
sym.addThrowsAnnotation(cls)
964
930
}
965
931
}
966
- def addParamNames (): Unit =
967
- if ((paramNames ne null ) && sym.hasRawInfo && sym.isMethod) {
968
- val params = sym.rawInfo.params
969
- (paramNames zip params).foreach {
970
- case (nme.NO_NAME , _) => // param was ACC_SYNTHETIC; ignore
971
- case (name, param) =>
972
- param.resetFlag(SYNTHETIC )
973
- param.name = name
974
- }
975
- if (isDeveloper && ! sameLength(paramNames.toList, params)) {
976
- // there's not anything we can do, but it's slightly worrisome
977
- devWarning(
978
- sm """ MethodParameters length mismatch while parsing $sym:
979
- | rawInfo.params: ${sym.rawInfo.params}
980
- | MethodParameters: ${paramNames.toList}""" )
981
- }
982
- }
983
932
// begin parseAttributes
984
933
for (i <- 0 until u2) parseAttribute()
985
- addParamNames()
986
934
}
987
935
988
936
@@ -1313,6 +1261,76 @@ abstract class ClassfileParser {
1313
1261
sym setInfo createFromClonedSymbols(alias.initialize.typeParams, alias.tpe)(typeFun)
1314
1262
}
1315
1263
}
1264
+ final class JavaSignatureTypeCompleter (name : Name , jflags : JavaAccFlags , index : Int ) extends LazyType {
1265
+ override def complete (sym : symbolTable.Symbol ): Unit = {
1266
+ var info = pool.getType(sym, index)
1267
+ if (name == nme.CONSTRUCTOR )
1268
+ info match {
1269
+ case MethodType (params, restpe) =>
1270
+ // if this is a non-static inner class, remove the explicit outer parameter
1271
+ val paramsNoOuter = innerClasses getEntry currentClass match {
1272
+ case Some (entry) if ! entry.jflags.isStatic =>
1273
+ /* About `clazz.owner.hasPackageFlag` below: scala/bug#5957
1274
+ * For every nested java class A$B, there are two symbols in the scala compiler.
1275
+ * 1. created by SymbolLoader, because of the existence of the A$B.class file, owner: package
1276
+ * 2. created by ClassfileParser of A when reading the inner classes, owner: A
1277
+ * If symbol 1 gets completed (e.g. because the compiled source mentions `A$B`, not `A#B`), the
1278
+ * ClassfileParser for 1 executes, and clazz.owner is the package.
1279
+ */
1280
+ assert(params.head.tpe.typeSymbol == clazz.owner || clazz.owner.hasPackageFlag, params.head.tpe.typeSymbol + " : " + clazz.owner)
1281
+ params.tail
1282
+ case _ =>
1283
+ params
1284
+ }
1285
+ val newParams = paramsNoOuter match {
1286
+ case (init :+ tail) if jflags.isSynthetic =>
1287
+ // scala/bug#7455 strip trailing dummy argument ("access constructor tag") from synthetic constructors which
1288
+ // are added when an inner class needs to access a private constructor.
1289
+ init
1290
+ case _ =>
1291
+ paramsNoOuter
1292
+ }
1293
+
1294
+ info = MethodType (newParams, clazz.tpe)
1295
+ }
1296
+ // Note: the info may be overwritten later with a generic signature
1297
+ // parsed from SignatureATTR
1298
+ sym.setInfo(if (jflags.isVarargs) arrayToRepeated(info) else info)
1299
+ addParamNames(sym)
1300
+ }
1301
+ }
1302
+
1303
+ private def addParamNames (sym : Symbol ): Unit = {
1304
+ sym.getAndRemoveAttachment[ParamNames ] match {
1305
+ case Some (ParamNames (paramNames)) =>
1306
+ if (sym.hasRawInfo && sym.isMethod) {
1307
+ val params = sym.rawInfo.params
1308
+ val paramNames1 = paramNames.takeRight(params.length)
1309
+ (paramNames1 zip params).foreach {
1310
+ case (nme.NO_NAME , _) => // param was ACC_SYNTHETIC; ignore
1311
+ case (name, param) =>
1312
+ param.resetFlag(SYNTHETIC )
1313
+ param.name = name
1314
+ }
1315
+ if (isDeveloper && ! sameLength(paramNames.toList, params)) {
1316
+ // there's not anything we can do, but it's slightly worrisome
1317
+ devWarning(
1318
+ sm """ MethodParameters length mismatch while parsing $sym:
1319
+ | rawInfo.params: ${sym.rawInfo.params}
1320
+ | MethodParameters: ${paramNames.toList}""" )
1321
+ }
1322
+ }
1323
+ case _ =>
1324
+ }
1325
+ }
1326
+
1327
+ final class JavaGenericSignatureTypeCompleter (sig : String , isVarargs : Boolean ) extends LazyType {
1328
+ override def complete (sym : symbolTable.Symbol ): Unit = {
1329
+ var info = sigToType(sym, sig)
1330
+ sym.setInfo(if (isVarargs) arrayToRepeated(info) else info)
1331
+ addParamNames(sym)
1332
+ }
1333
+ }
1316
1334
1317
1335
def skipAttributes (): Unit = {
1318
1336
var attrCount : Int = u2
@@ -1340,4 +1358,7 @@ abstract class ClassfileParser {
1340
1358
1341
1359
protected def getScope (flags : JavaAccFlags ): Scope =
1342
1360
if (flags.isStatic) staticScope else instanceScope
1361
+
1362
+ private case class ParamNames (names : Seq [Name ])
1343
1363
}
1364
+
0 commit comments