@@ -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 , paramNames)
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 , ListBuffer () )
580
581
addJavaFlagsAnnotations(sym, jflags)
581
582
getScope(jflags) enter sym
582
583
@@ -611,47 +612,14 @@ 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
+ var paramNames : ListBuffer [Name ] = ListBuffer (null )// null means we didn't find any
618
+ val lazyInfo = new JavaSignatureTypeCompleter (name, jflags, index = u2, paramNames)
619
+ sym.info = lazyInfo
649
620
propagatePackageBoundary(jflags, sym)
650
- parseAttributes(sym, info, removedOuterParameter )
621
+ parseAttributes(sym, jflags.isVarargs, paramNames )
651
622
addJavaFlagsAnnotations(sym, jflags)
652
- if (jflags.isVarargs)
653
- sym modifyInfo arrayToRepeated
654
-
655
623
getScope(jflags) enter sym
656
624
}
657
625
}
@@ -835,8 +803,7 @@ abstract class ClassfileParser {
835
803
/**
836
804
* Only invoked for java classfiles.
837
805
*/
838
- def parseAttributes (sym : Symbol , symtype : Type , removedOuterParameter : Boolean = false ): Unit = {
839
- var paramNames : ListBuffer [Name ] = null // null means we didn't find any
806
+ def parseAttributes (sym : Symbol , isVarargs : Boolean = false , paramNames : ListBuffer [Name ]): Unit = {
840
807
def convertTo (c : Constant , pt : Type ): Constant = {
841
808
if (pt.typeSymbol == BooleanClass && c.tag == IntTag )
842
809
Constant (c.value != 0 )
@@ -850,9 +817,12 @@ abstract class ClassfileParser {
850
817
attrName match {
851
818
case tpnme.SignatureATTR =>
852
819
val sig = pool.getExternalName(u2)
853
- val newType = sigToType(sym, sig.value)
854
- sym.setInfo(newType)
855
-
820
+ if (sym.isClass) {
821
+ sym.setInfo(sigToType(sym, sig.value))
822
+ } else {
823
+ val lazyType = new JavaGenericSignatureTypeCompleter (sig.value, isVarargs, paramNames)
824
+ sym.setInfo(lazyType)
825
+ }
856
826
case tpnme.SyntheticATTR =>
857
827
sym.setFlag(SYNTHETIC | ARTIFACT )
858
828
in.skip(attrLen)
@@ -868,20 +838,16 @@ abstract class ClassfileParser {
868
838
869
839
case tpnme.ConstantValueATTR =>
870
840
val c = pool.getConstant(u2)
871
- val c1 = convertTo(c, symtype )
841
+ val c1 = convertTo(c, sym.initialize.info.resultType )
872
842
if (c1 ne null ) sym.setInfo(ConstantType (c1))
873
- else devWarning(s " failure to convert $c to $symtype " )
843
+ else devWarning(s " failure to convert $c to ${sym.initialize.info.resultType} " )
874
844
875
845
case tpnme.MethodParametersATTR =>
876
846
def readParamNames (): Unit = {
847
+ paramNames.clear()
877
848
import scala .tools .asm .Opcodes .ACC_SYNTHETIC
878
849
val paramCount = u1
879
850
var i = 0
880
- if (removedOuterParameter && i < paramCount) {
881
- in.skip(4 )
882
- i += 1
883
- }
884
- paramNames = new ListBuffer ()
885
851
while (i < paramCount) {
886
852
val rawname = pool.getName(u2)
887
853
val access = u2
@@ -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,71 @@ 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 , paramNames : ListBuffer [Name ]) extends LazyType {
1265
+ override def complete (sym : symbolTable.Symbol ): Unit = {
1266
+ var removedOuterParameter = false
1267
+ var info = pool.getType(sym, index)
1268
+ if (name == nme.CONSTRUCTOR )
1269
+ info match {
1270
+ case MethodType (params, restpe) =>
1271
+ // if this is a non-static inner class, remove the explicit outer parameter
1272
+ val paramsNoOuter = innerClasses getEntry currentClass match {
1273
+ case Some (entry) if ! entry.jflags.isStatic =>
1274
+ /* About `clazz.owner.hasPackageFlag` below: scala/bug#5957
1275
+ * For every nested java class A$B, there are two symbols in the scala compiler.
1276
+ * 1. created by SymbolLoader, because of the existence of the A$B.class file, owner: package
1277
+ * 2. created by ClassfileParser of A when reading the inner classes, owner: A
1278
+ * If symbol 1 gets completed (e.g. because the compiled source mentions `A$B`, not `A#B`), the
1279
+ * ClassfileParser for 1 executes, and clazz.owner is the package.
1280
+ */
1281
+ assert(params.head.tpe.typeSymbol == clazz.owner || clazz.owner.hasPackageFlag, params.head.tpe.typeSymbol + " : " + clazz.owner)
1282
+ removedOuterParameter = true
1283
+ params.tail
1284
+ case _ =>
1285
+ params
1286
+ }
1287
+ val newParams = paramsNoOuter match {
1288
+ case (init :+ tail) if jflags.isSynthetic =>
1289
+ // scala/bug#7455 strip trailing dummy argument ("access constructor tag") from synthetic constructors which
1290
+ // are added when an inner class needs to access a private constructor.
1291
+ init
1292
+ case _ =>
1293
+ paramsNoOuter
1294
+ }
1295
+
1296
+ info = MethodType (newParams, clazz.tpe)
1297
+ }
1298
+ // Note: the info may be overwritten later with a generic signature
1299
+ // parsed from SignatureATTR
1300
+ sym.setInfo(if (jflags.isVarargs) arrayToRepeated(info) else info)
1301
+ addParamNames(sym, removedOuterParameter)
1302
+ }
1303
+
1304
+ private def addParamNames (sym : Symbol , removedOuterParameter : Boolean ): Unit =
1305
+ if ((paramNames ne null ) && paramNames.headOption != Some (null ) && sym.hasRawInfo && sym.isMethod) {
1306
+ val params = sym.rawInfo.params.drop(if (removedOuterParameter) 1 else 0 )
1307
+ (paramNames zip params).foreach {
1308
+ case (nme.NO_NAME , _) => // param was ACC_SYNTHETIC; ignore
1309
+ case (name, param) =>
1310
+ param.resetFlag(SYNTHETIC )
1311
+ param.name = name
1312
+ }
1313
+ if (isDeveloper && ! sameLength(paramNames.toList, params)) {
1314
+ // there's not anything we can do, but it's slightly worrisome
1315
+ devWarning(
1316
+ sm """ MethodParameters length mismatch while parsing $sym:
1317
+ | rawInfo.params: ${sym.rawInfo.params}
1318
+ | MethodParameters: ${paramNames.toList}""" )
1319
+ }
1320
+ }
1321
+
1322
+ }
1323
+ final class JavaGenericSignatureTypeCompleter (sig : String , isVarargs : Boolean , paramNames : ListBuffer [Name ]) extends LazyType {
1324
+ override def complete (sym : symbolTable.Symbol ): Unit = {
1325
+ var info = sigToType(sym, sig)
1326
+ sym.setInfo(if (isVarargs) arrayToRepeated(info) else info)
1327
+ }
1328
+ }
1316
1329
1317
1330
def skipAttributes (): Unit = {
1318
1331
var attrCount : Int = u2
0 commit comments