@@ -114,7 +114,7 @@ class ClassfileParser(
114
114
}
115
115
116
116
/** Return the class symbol of the given name. */
117
- def classNameToSymbol (name : Name )(using Context , DataReader ): Symbol = innerClasses.get(name) match {
117
+ def classNameToSymbol (name : Name )(using Context ): Symbol = innerClasses.get(name.toString ) match {
118
118
case Some (entry) => innerClasses.classSymbol(entry)
119
119
case None => requiredClass(name)
120
120
}
@@ -191,7 +191,7 @@ class ClassfileParser(
191
191
192
192
setClassInfo(moduleRoot, staticInfo, fromScala2 = false )
193
193
194
- classInfo = parseAttributes(classRoot.symbol, classInfo)
194
+ classInfo = parseAttributes(classRoot.symbol).complete( classInfo)
195
195
if (isAnnotation)
196
196
// classInfo must be a TempClassInfoType and not a TempPolyType,
197
197
// because Java annotations cannot have type parameters.
@@ -227,32 +227,37 @@ class ClassfileParser(
227
227
val sflags =
228
228
if (method) Flags .Method | methodTranslation.flags(jflags)
229
229
else fieldTranslation.flags(jflags)
230
- val name = pool.getName(in.nextChar)
231
- if (! sflags.isOneOf(Flags .PrivateOrArtifact ) || name.name == nme.CONSTRUCTOR ) {
230
+ val preName = pool.getName(in.nextChar)
231
+ if (! sflags.isOneOf(Flags .PrivateOrArtifact ) || preName.name == nme.CONSTRUCTOR ) {
232
+ val sig = pool.getExternalName(in.nextChar).value
233
+ val completer = MemberCompleter (preName.name, jflags, sig)
232
234
val member = newSymbol(
233
- getOwner(jflags), name .name, sflags, memberCompleter ,
235
+ getOwner(jflags), preName .name, sflags, completer ,
234
236
getPrivateWithin(jflags), coord = start)
235
237
getScope(jflags).enter(member)
238
+
239
+ val pt = if sig.size == 1 then constantTagToType(sig(0 )) else WildcardType
240
+ val isVarargs = sflags.is(Flags .Method ) && (jflags & JAVA_ACC_VARARGS ) != 0
241
+ completer.attrCompleter = parseAttributes(member, pt, isVarargs)
242
+ }
243
+ else {
244
+ in.nextChar // info
245
+ skipAttributes()
236
246
}
237
- // skip rest of member for now
238
- in.nextChar // info
239
- skipAttributes()
240
247
}
241
248
242
- val memberCompleter : LazyType = new LazyType {
249
+ class MemberCompleter (name : SimpleName , jflags : Int , sig : String ) extends LazyType {
250
+ var attrCompleter : AttributeCompleter = null
243
251
244
- def complete (denot : SymDenotation )(using Context ): Unit = withReader(classfile) { (using in) =>
245
- in.bp = denot.symbol.coord.toIndex
252
+ def complete (denot : SymDenotation )(using Context ): Unit = {
246
253
val sym = denot.symbol
247
- val jflags = in.nextChar
248
254
val isEnum = (jflags & JAVA_ACC_ENUM ) != 0
249
- val name = pool.getName(in.nextChar).name
250
255
val isConstructor = name eq nme.CONSTRUCTOR
251
256
252
257
/** Strip leading outer param from constructor and trailing access tag for
253
258
* private inner constructors.
254
259
*/
255
- def normalizeConstructorParams () = innerClasses.get(currentClassName) match {
260
+ def normalizeConstructorParams () = innerClasses.get(currentClassName.toString ) match {
256
261
case Some (entry) if ! isStatic(entry.jflags) =>
257
262
val mt @ MethodTpe (paramNames, paramTypes, resultType) = denot.info
258
263
var normalizedParamNames = paramNames.tail
@@ -283,9 +288,9 @@ class ClassfileParser(
283
288
}
284
289
285
290
val isVarargs = denot.is(Flags .Method ) && (jflags & JAVA_ACC_VARARGS ) != 0
286
- denot.info = pool.getType(in.nextChar, isVarargs)
291
+ denot.info = sigToType(sig, isVarargs = isVarargs)
287
292
if (isConstructor) normalizeConstructorParams()
288
- denot.info = translateTempPoly(parseAttributes(sym, denot.info, isVarargs ))
293
+ denot.info = translateTempPoly(attrCompleter.complete( denot.info))
289
294
if (isConstructor) normalizeConstructorInfo()
290
295
291
296
if (ctx.explicitNulls) denot.info = JavaNullInterop .nullifyMember(denot.symbol, denot.info, isEnum)
@@ -317,7 +322,7 @@ class ClassfileParser(
317
322
case BOOL_TAG => defn.BooleanType
318
323
}
319
324
320
- private def sigToType (sig : String , owner : Symbol = null , isVarargs : Boolean = false )(using Context , DataReader ): Type = {
325
+ private def sigToType (sig : String , owner : Symbol = null , isVarargs : Boolean = false )(using Context ): Type = {
321
326
var index = 0
322
327
val end = sig.length
323
328
def accept (ch : Char ): Unit = {
@@ -604,8 +609,20 @@ class ClassfileParser(
604
609
None // ignore malformed annotations
605
610
}
606
611
607
- def parseAttributes (sym : Symbol , symtype : Type , isVarargs : Boolean = false )(using ctx : Context , in : DataReader ): Type = {
608
- var newType = symtype
612
+ abstract class AttributeCompleter {
613
+ def complete (tp : Type )(using Context ): Type
614
+ }
615
+
616
+ // invariant: `in` and `ctx` should not be captured inside the result function
617
+ def parseAttributes (sym : Symbol , pt : Type = WildcardType , isVarargs : Boolean = false )(using ctx : Context , in : DataReader ): AttributeCompleter = {
618
+ var typeUpdate : Option [Context ?=> Type ] = None
619
+
620
+ val res = new AttributeCompleter {
621
+ def complete (tp : Type )(using Context ): Type = {
622
+ val newType = if (typeUpdate.isEmpty) tp else typeUpdate.get
623
+ cook.apply(newType)
624
+ }
625
+ }
609
626
610
627
def parseAttribute (): Unit = {
611
628
val attrName = pool.getName(in.nextChar).name.toTypeName
@@ -614,9 +631,12 @@ class ClassfileParser(
614
631
attrName match {
615
632
case tpnme.SignatureATTR =>
616
633
val sig = pool.getExternalName(in.nextChar)
617
- newType = sigToType(sig.value, sym, isVarargs)
618
- if (ctx.debug && ctx.verbose)
619
- println(" " + sym + " ; signature = " + sig + " type = " + newType)
634
+ typeUpdate = Some {
635
+ val newType = sigToType(sig.value, sym, isVarargs)
636
+ if (ctx.debug && ctx.verbose)
637
+ println(" " + sym + " ; signature = " + sig + " type = " + newType)
638
+ newType
639
+ }
620
640
621
641
case tpnme.SyntheticATTR =>
622
642
sym.setFlag(Flags .SyntheticArtifact )
@@ -630,8 +650,8 @@ class ClassfileParser(
630
650
sym.addAnnotation(Annotation (defn.DeprecatedAnnot , msg, since))
631
651
632
652
case tpnme.ConstantValueATTR =>
633
- val c = pool.getConstant(in.nextChar, symtype )
634
- if (c ne null ) newType = ConstantType (c)
653
+ val c = pool.getConstant(in.nextChar, pt )
654
+ if (c ne null ) typeUpdate = Some { ConstantType (c) }
635
655
else report.warning(s " Invalid constant in attribute of ${sym.showLocated} while parsing ${classfile}" )
636
656
637
657
case tpnme.AnnotationDefaultATTR =>
@@ -652,12 +672,12 @@ class ClassfileParser(
652
672
parseExceptions(attrLen)
653
673
654
674
case tpnme.CodeATTR =>
675
+ in.skip(attrLen)
655
676
if (sym.owner.isAllOf(Flags .JavaInterface )) {
656
677
sym.resetFlag(Flags .Deferred )
657
678
sym.owner.resetFlag(Flags .PureInterface )
658
679
report.log(s " $sym in ${sym.owner} is a java8+ default method. " )
659
680
}
660
- in.skip(attrLen)
661
681
662
682
case _ =>
663
683
}
@@ -677,6 +697,7 @@ class ClassfileParser(
677
697
}
678
698
}
679
699
700
+
680
701
/** Parse a sequence of annotations and attaches them to the
681
702
* current symbol sym, except for the ScalaSignature annotation that it returns, if it is available. */
682
703
def parseAnnotations (len : Int ): Unit = {
@@ -693,7 +714,7 @@ class ClassfileParser(
693
714
for (i <- 0 until in.nextChar)
694
715
parseAttribute()
695
716
696
- cook.apply(newType)
717
+ res
697
718
}
698
719
699
720
/** Annotations in Scala are assumed to get all their arguments as constructor
@@ -730,7 +751,7 @@ class ClassfileParser(
730
751
731
752
for entry <- innerClasses.valuesIterator do
732
753
// create a new class member for immediate inner classes
733
- if entry.outerName == currentClassName then
754
+ if entry.outer.name == currentClassName then
734
755
val file = ctx.platform.classPath.findClassFile(entry.externalName.toString) getOrElse {
735
756
throw new AssertionError (entry.externalName)
736
757
}
@@ -911,8 +932,11 @@ class ClassfileParser(
911
932
val nameIndex = in.nextChar
912
933
val jflags = in.nextChar
913
934
if (innerIndex != 0 && outerIndex != 0 && nameIndex != 0 ) {
914
- val entry = InnerClassEntry (innerIndex, outerIndex, nameIndex, jflags)
915
- innerClasses(pool.getClassName(innerIndex).name) = entry
935
+ val inner = pool.getClassName(innerIndex)
936
+ val outer = pool.getClassName(outerIndex)
937
+ val name = pool.getClassName(nameIndex)
938
+ val entry = InnerClassEntry (inner, outer, name, jflags)
939
+ innerClasses(pool.getClassName(innerIndex).value) = entry
916
940
}
917
941
}
918
942
}
@@ -922,20 +946,20 @@ class ClassfileParser(
922
946
}
923
947
924
948
/** An entry in the InnerClasses attribute of this class file. */
925
- private case class InnerClassEntry (external : Int , outer : Int , name : Int , jflags : Int ) {
926
- def externalName ( using DataReader ) : SimpleName = pool.getClassName( external).name
927
- def outerName ( using DataReader ) : SimpleName = pool.getClassName( outer).name
928
- def originalName ( using DataReader ) : SimpleName = pool.getName( name) .name
949
+ case class InnerClassEntry (external : NameOrString , outer : NameOrString , name : NameOrString , jflags : Int ) {
950
+ def externalName = external.value
951
+ def outerName = outer.value
952
+ def originalName = name.name
929
953
930
- def show ( using DataReader ) : String =
931
- s " $originalName in $outerName ( $externalName ) "
954
+ // The name of the outer class, without its trailing $ if it has one.
955
+ def strippedOuter = outer.name.stripModuleClassSuffix
932
956
}
933
957
934
- private object innerClasses extends util.HashMap [Name , InnerClassEntry ] {
958
+ private object innerClasses extends util.HashMap [String , InnerClassEntry ] {
935
959
/** Return the Symbol of the top level class enclosing `name`,
936
960
* or 'name's symbol if no entry found for `name`.
937
961
*/
938
- def topLevelClass (name : Name )(using Context , DataReader ): Symbol = {
962
+ def topLevelClass (name : String )(using Context ): Symbol = {
939
963
val tlName = if (contains(name)) {
940
964
var entry = this (name)
941
965
while (contains(entry.outerName))
@@ -944,13 +968,13 @@ class ClassfileParser(
944
968
}
945
969
else
946
970
name
947
- classNameToSymbol(tlName)
971
+ classNameToSymbol(tlName.toTypeName )
948
972
}
949
973
950
974
/** Return the class symbol for `entry`. It looks it up in its outer class.
951
975
* This might force outer class symbols.
952
976
*/
953
- def classSymbol (entry : InnerClassEntry )(using Context , DataReader ): Symbol = {
977
+ def classSymbol (entry : InnerClassEntry )(using Context ): Symbol = {
954
978
def getMember (sym : Symbol , name : Name )(using Context ): Symbol =
955
979
if (isStatic(entry.jflags))
956
980
if (sym == classRoot.symbol)
@@ -966,7 +990,7 @@ class ClassfileParser(
966
990
else
967
991
sym.info.member(name).symbol
968
992
969
- val outerName = entry.outerName.stripModuleClassSuffix
993
+ val outerName = entry.strippedOuter
970
994
val innerName = entry.originalName
971
995
val owner = classNameToSymbol(outerName)
972
996
val result = atPhase(typerPhase)(getMember(owner, innerName.toTypeName))
@@ -1025,7 +1049,7 @@ class ClassfileParser(
1025
1049
}
1026
1050
}
1027
1051
1028
- def getClassSymbol (name : SimpleName )(using Context , DataReader ): Symbol =
1052
+ def getClassSymbol (name : SimpleName )(using Context ): Symbol =
1029
1053
if (name.endsWith(" $" ) && (name ne nme.nothingRuntimeClass) && (name ne nme.nullRuntimeClass))
1030
1054
// Null$ and Nothing$ ARE classes
1031
1055
requiredModule(name.dropRight(1 ))
0 commit comments