@@ -235,9 +235,8 @@ class ClassfileParser(
235
235
getOwner(jflags), preName.name, sflags, completer,
236
236
getPrivateWithin(jflags), coord = start)
237
237
238
- val pt = if sig.size == 1 then constantTagToType(sig(0 )) else WildcardType
239
238
val isVarargs = sflags.is(Flags .Method ) && (jflags & JAVA_ACC_VARARGS ) != 0
240
- completer.attrCompleter = parseAttributes(member, pt, isVarargs)
239
+ completer.attrCompleter = parseAttributes(member, isVarargs)
241
240
242
241
getScope(jflags).enter(member)
243
242
@@ -324,6 +323,21 @@ class ClassfileParser(
324
323
case BOOL_TAG => defn.BooleanType
325
324
}
326
325
326
+ /** As specified in https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.16.1,
327
+ * an annotation argument of type boolean, byte, char or short will
328
+ * be represented as a CONSTANT_INTEGER, so we need to convert it to
329
+ * produce a correctly-typed tree. We need to do this each time the
330
+ * constant is accessed instead of storing the result of the
331
+ * conversion in the `values` cache, because the same constant might
332
+ * be used for annotation arguments of different type.
333
+ */
334
+ def convertTo (ct : Constant , pt : Type )(using Context ): Constant = {
335
+ if (pt eq defn.BooleanType ) && ct.tag == IntTag then
336
+ Constant (ct.value != 0 )
337
+ else
338
+ ct.convertTo(pt)
339
+ }
340
+
327
341
private def sigToType (sig : String , owner : Symbol = null , isVarargs : Boolean = false )(using Context ): Type = {
328
342
var index = 0
329
343
val end = sig.length
@@ -525,7 +539,10 @@ class ClassfileParser(
525
539
case STRING_TAG =>
526
540
if (skip) None else Some (lit(Constant (pool.getName(index).value)))
527
541
case BOOL_TAG | BYTE_TAG | CHAR_TAG | SHORT_TAG =>
528
- if (skip) None else Some (lit(pool.getConstant(index, constantTagToType(tag))))
542
+ if (skip) None else {
543
+ val constant = convertTo(pool.getConstant(index), constantTagToType(tag))
544
+ Some (lit(constant))
545
+ }
529
546
case INT_TAG | LONG_TAG | FLOAT_TAG | DOUBLE_TAG =>
530
547
if (skip) None else Some (lit(pool.getConstant(index)))
531
548
case CLASS_TAG =>
@@ -612,17 +629,27 @@ class ClassfileParser(
612
629
}
613
630
614
631
abstract class AttributeCompleter {
632
+ var constant : Constant = null
615
633
var exceptions : List [NameOrString ] = Nil
616
634
def complete (tp : Type )(using Context ): Type
617
635
}
618
636
619
637
// invariant: `in` and `ctx` should not be captured inside the result function
620
- def parseAttributes (sym : Symbol , pt : Type = WildcardType , isVarargs : Boolean = false )(using ctx : Context , in : DataReader ): AttributeCompleter = {
638
+ def parseAttributes (sym : Symbol , isVarargs : Boolean = false )(using ctx : Context , in : DataReader ): AttributeCompleter = {
621
639
var typeUpdate : Option [Context ?=> Type ] = None
622
640
var delayedWork : List [Context ?=> Unit ] = Nil
623
641
val res = new AttributeCompleter {
624
642
def complete (tp : Type )(using Context ): Type = {
625
- val newType = if (typeUpdate.isEmpty) tp else typeUpdate.get
643
+ val updatedType =
644
+ if typeUpdate.isEmpty then tp
645
+ else typeUpdate.get
646
+
647
+ val newType =
648
+ if this .constant != null then
649
+ val ct = convertTo(this .constant, updatedType)
650
+ if ct != null then ConstantType (ct) else updatedType
651
+ else updatedType
652
+
626
653
exceptions.foreach { ex =>
627
654
val cls = getClassSymbol(ex.name)
628
655
sym.addAnnotation(ThrowsAnnotation (cls.asClass))
@@ -658,8 +685,8 @@ class ClassfileParser(
658
685
sym.addAnnotation(Annotation (defn.DeprecatedAnnot , msg, since))
659
686
660
687
case tpnme.ConstantValueATTR =>
661
- val c = pool.getConstant(in.nextChar, pt )
662
- if (c ne null ) typeUpdate = Some { ConstantType (c) }
688
+ val c = pool.getConstant(in.nextChar)
689
+ if (c ne null ) res.constant = c
663
690
else report.warning(s " Invalid constant in attribute of ${sym.showLocated} while parsing ${classfile}" )
664
691
665
692
case tpnme.AnnotationDefaultATTR =>
@@ -1183,7 +1210,7 @@ class ClassfileParser(
1183
1210
getClassSymbol(index)
1184
1211
}
1185
1212
1186
- def getConstant (index : Int , pt : Type = WildcardType )(using ctx : Context , in : DataReader ): Constant = {
1213
+ def getConstant (index : Int )(using ctx : Context , in : DataReader ): Constant = {
1187
1214
if (index <= 0 || len <= index) errorBadIndex(index)
1188
1215
var value = values(index)
1189
1216
if (value eq null ) {
@@ -1207,21 +1234,7 @@ class ClassfileParser(
1207
1234
values(index) = value
1208
1235
}
1209
1236
value match {
1210
- case ct : Constant =>
1211
- if pt ne WildcardType then
1212
- // As specified in https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.16.1,
1213
- // an annotation argument of type boolean, byte, char or short will
1214
- // be represented as a CONSTANT_INTEGER, so we need to convert it to
1215
- // produce a correctly-typed tree. We need to do this each time the
1216
- // constant is accessed instead of storing the result of the
1217
- // conversion in the `values` cache, because the same constant might
1218
- // be used for annotation arguments of different type.
1219
- if (pt eq defn.BooleanType ) && ct.tag == IntTag then
1220
- Constant (ct.value != 0 )
1221
- else
1222
- ct.convertTo(pt)
1223
- else
1224
- ct
1237
+ case ct : Constant => ct
1225
1238
case cls : Symbol => Constant (cls.typeRef)
1226
1239
case arr : Type => Constant (arr)
1227
1240
}
0 commit comments