122
122
import com .sun .tools .classfile .InnerClasses_attribute ;
123
123
import com .sun .tools .classfile .InnerClasses_attribute .Info ;
124
124
import com .sun .tools .classfile .Method ;
125
+ import com .sun .tools .classfile .MethodParameters_attribute ;
125
126
import com .sun .tools .classfile .ModuleResolution_attribute ;
126
127
import com .sun .tools .classfile .ModuleTarget_attribute ;
127
128
import com .sun .tools .classfile .Module_attribute ;
131
132
import com .sun .tools .classfile .Module_attribute .RequiresEntry ;
132
133
import com .sun .tools .classfile .NestHost_attribute ;
133
134
import com .sun .tools .classfile .NestMembers_attribute ;
135
+ import com .sun .tools .classfile .Record_attribute ;
136
+ import com .sun .tools .classfile .Record_attribute .ComponentInfo ;
134
137
import com .sun .tools .classfile .RuntimeAnnotations_attribute ;
135
138
import com .sun .tools .classfile .RuntimeInvisibleAnnotations_attribute ;
136
139
import com .sun .tools .classfile .RuntimeInvisibleParameterAnnotations_attribute ;
@@ -959,6 +962,22 @@ private void addAttributes(ClassHeaderDescription header,
959
962
attributes .put (Attribute .NestMembers ,
960
963
new NestMembers_attribute (attributeString , nestMembers ));
961
964
}
965
+ if (header .isRecord ) {
966
+ assert header .recordComponents != null ;
967
+ int attributeString = addString (constantPool , Attribute .Record );
968
+ ComponentInfo [] recordComponents = new ComponentInfo [header .recordComponents .size ()];
969
+ int i = 0 ;
970
+ for (RecordComponentDescription rcd : header .recordComponents ) {
971
+ int name = addString (constantPool , rcd .name );
972
+ Descriptor desc = new Descriptor (addString (constantPool , rcd .descriptor ));
973
+ Map <String , Attribute > nestedAttrs = new HashMap <>();
974
+ addGenericAttributes (rcd , constantPool , nestedAttrs );
975
+ Attributes attrs = new Attributes (nestedAttrs );
976
+ recordComponents [i ++] = new ComponentInfo (name , desc , attrs );
977
+ }
978
+ attributes .put (Attribute .Record ,
979
+ new Record_attribute (attributeString , recordComponents ));
980
+ }
962
981
addInnerClassesAttribute (header , constantPool , attributes );
963
982
}
964
983
@@ -1017,6 +1036,18 @@ private void addAttributes(MethodDescription desc, List<CPInfo> constantPool, Ma
1017
1036
new RuntimeVisibleParameterAnnotations_attribute (attributeString ,
1018
1037
annotations ));
1019
1038
}
1039
+ if (desc .methodParameters != null && !desc .methodParameters .isEmpty ()) {
1040
+ int attributeString =
1041
+ addString (constantPool , Attribute .MethodParameters );
1042
+ MethodParameters_attribute .Entry [] entries =
1043
+ desc .methodParameters
1044
+ .stream ()
1045
+ .map (p -> new MethodParameters_attribute .Entry (addString (constantPool , p .name ),
1046
+ p .flags ))
1047
+ .toArray (s -> new MethodParameters_attribute .Entry [s ]);
1048
+ attributes .put (Attribute .MethodParameters ,
1049
+ new MethodParameters_attribute (attributeString , entries ));
1050
+ }
1020
1051
}
1021
1052
1022
1053
private void addAttributes (FieldDescription desc , List <CPInfo > constantPool , Map <String , Attribute > attributes ) {
@@ -1595,7 +1626,9 @@ private void dumpDescriptions(ClassList classes,
1595
1626
StringWriter data = new StringWriter ();
1596
1627
ModuleDescription module = modules .get (e .getKey ());
1597
1628
1598
- module .write (data , desc .basePlatform , desc .version );
1629
+ if (module != null ) { //module == null should only be in tests.
1630
+ module .write (data , desc .basePlatform , desc .version );
1631
+ }
1599
1632
1600
1633
for (ClassDescription clazz : e .getValue ()) {
1601
1634
clazz .write (data , desc .basePlatform , desc .version );
@@ -2153,6 +2186,37 @@ private boolean readAttribute(ClassFile cf, FeatureDescription feature, Attribut
2153
2186
.collect (Collectors .toList ());
2154
2187
break ;
2155
2188
}
2189
+ case Attribute .Record : {
2190
+ assert feature instanceof ClassHeaderDescription ;
2191
+ Record_attribute record = (Record_attribute ) attr ;
2192
+ List <RecordComponentDescription > components = new ArrayList <>();
2193
+ for (ComponentInfo info : record .component_info_arr ) {
2194
+ RecordComponentDescription rcd = new RecordComponentDescription ();
2195
+ rcd .name = info .getName (cf .constant_pool );
2196
+ rcd .descriptor = info .descriptor .getValue (cf .constant_pool );
2197
+ for (Attribute nestedAttr : info .attributes ) {
2198
+ readAttribute (cf , rcd , nestedAttr );
2199
+ }
2200
+ components .add (rcd );
2201
+ }
2202
+ ClassHeaderDescription chd = (ClassHeaderDescription ) feature ;
2203
+ chd .isRecord = true ;
2204
+ chd .recordComponents = components ;
2205
+ break ;
2206
+ }
2207
+ case Attribute .MethodParameters : {
2208
+ assert feature instanceof MethodDescription ;
2209
+ MethodParameters_attribute params = (MethodParameters_attribute ) attr ;
2210
+ MethodDescription method = (MethodDescription ) feature ;
2211
+ method .methodParameters = new ArrayList <>();
2212
+ for (MethodParameters_attribute .Entry e : params .method_parameter_table ) {
2213
+ String name = cf .constant_pool .getUTF8Value (e .name_index );
2214
+ MethodDescription .MethodParam param =
2215
+ new MethodDescription .MethodParam (e .flags , name );
2216
+ method .methodParameters .add (param );
2217
+ }
2218
+ break ;
2219
+ }
2156
2220
default :
2157
2221
throw new IllegalStateException ("Unhandled attribute: " +
2158
2222
attrName );
@@ -2999,6 +3063,8 @@ static class ClassHeaderDescription extends HeaderDescription {
2999
3063
List <String > implementsAttr ;
3000
3064
String nestHost ;
3001
3065
List <String > nestMembers ;
3066
+ boolean isRecord ;
3067
+ List <RecordComponentDescription > recordComponents ;
3002
3068
3003
3069
@ Override
3004
3070
public int hashCode () {
@@ -3007,6 +3073,8 @@ public int hashCode() {
3007
3073
hash = 17 * hash + Objects .hashCode (this .implementsAttr );
3008
3074
hash = 17 * hash + Objects .hashCode (this .nestHost );
3009
3075
hash = 17 * hash + Objects .hashCode (this .nestMembers );
3076
+ hash = 17 * hash + Objects .hashCode (this .isRecord );
3077
+ hash = 17 * hash + Objects .hashCode (this .recordComponents );
3010
3078
return hash ;
3011
3079
}
3012
3080
@@ -3031,6 +3099,12 @@ public boolean equals(Object obj) {
3031
3099
if (!listEquals (this .nestMembers , other .nestMembers )) {
3032
3100
return false ;
3033
3101
}
3102
+ if (this .isRecord != other .isRecord ) {
3103
+ return false ;
3104
+ }
3105
+ if (!listEquals (this .recordComponents , other .recordComponents )) {
3106
+ return false ;
3107
+ }
3034
3108
return true ;
3035
3109
}
3036
3110
@@ -3048,8 +3122,12 @@ public void write(Appendable output, String baselineVersion, String version) thr
3048
3122
output .append (" nestHost " + nestHost );
3049
3123
if (nestMembers != null && !nestMembers .isEmpty ())
3050
3124
output .append (" nestMembers " + serializeList (nestMembers ));
3125
+ if (isRecord ) {
3126
+ output .append (" record true" );
3127
+ }
3051
3128
writeAttributes (output );
3052
3129
output .append ("\n " );
3130
+ writeRecordComponents (output , baselineVersion , version );
3053
3131
writeInnerClasses (output , baselineVersion , version );
3054
3132
}
3055
3133
@@ -3065,14 +3143,37 @@ public boolean read(LineBasedReader reader) throws IOException {
3065
3143
nestHost = reader .attributes .get ("nestHost" );
3066
3144
String nestMembersList = reader .attributes .get ("nestMembers" );
3067
3145
nestMembers = deserializeList (nestMembersList );
3146
+ isRecord = reader .attributes .containsKey ("record" );
3068
3147
3069
3148
readAttributes (reader );
3070
3149
reader .moveNext ();
3150
+ if (isRecord ) {
3151
+ readRecordComponents (reader );
3152
+ }
3071
3153
readInnerClasses (reader );
3072
3154
3073
3155
return true ;
3074
3156
}
3075
3157
3158
+ protected void writeRecordComponents (Appendable output ,
3159
+ String baselineVersion ,
3160
+ String version ) throws IOException {
3161
+ if (recordComponents != null ) {
3162
+ for (RecordComponentDescription rcd : recordComponents ) {
3163
+ rcd .write (output , "" , "" );
3164
+ }
3165
+ }
3166
+ }
3167
+
3168
+ protected void readRecordComponents (LineBasedReader reader ) throws IOException {
3169
+ recordComponents = new ArrayList <>();
3170
+
3171
+ while ("recordcomponent" .equals (reader .lineKey )) {
3172
+ RecordComponentDescription rcd = new RecordComponentDescription ();
3173
+ rcd .read (reader );
3174
+ recordComponents .add (rcd );
3175
+ }
3176
+ }
3076
3177
}
3077
3178
3078
3179
static abstract class HeaderDescription extends FeatureDescription {
@@ -3145,6 +3246,7 @@ static class MethodDescription extends FeatureDescription {
3145
3246
Object annotationDefaultValue ;
3146
3247
List <List <AnnotationDescription >> classParameterAnnotations ;
3147
3248
List <List <AnnotationDescription >> runtimeParameterAnnotations ;
3249
+ List <MethodParam > methodParameters ;
3148
3250
3149
3251
public MethodDescription () {
3150
3252
flagsNormalization = METHODS_FLAGS_NORMALIZATION ;
@@ -3221,6 +3323,15 @@ public void write(Appendable output, String baselineVersion, String version) thr
3221
3323
output .append (";" );
3222
3324
}
3223
3325
}
3326
+ if (methodParameters != null && !methodParameters .isEmpty ()) {
3327
+ Function <MethodParam , String > param2String =
3328
+ p -> Integer .toHexString (p .flags ) + ":" + p .name ;
3329
+ List <String > paramsAsStrings =
3330
+ methodParameters .stream ()
3331
+ .map (param2String )
3332
+ .collect (Collectors .toList ());
3333
+ output .append (" methodParameters " + serializeList (paramsAsStrings ));
3334
+ }
3224
3335
output .append ("\n " );
3225
3336
}
3226
3337
@@ -3268,17 +3379,41 @@ public boolean read(LineBasedReader reader) throws IOException {
3268
3379
runtimeParameterAnnotations = annos ;
3269
3380
}
3270
3381
3382
+ String inMethodParameters = reader .attributes .get ("methodParameters" );
3383
+ if (inMethodParameters != null ) {
3384
+ Function <String , MethodParam > string2Param =
3385
+ p -> {
3386
+ int sep = p .indexOf (':' );
3387
+ return new MethodParam (Integer .parseInt (p .substring (0 , sep )),
3388
+ p .substring (sep + 1 ));
3389
+ };
3390
+ methodParameters =
3391
+ deserializeList (inMethodParameters ).stream ()
3392
+ .map (string2Param )
3393
+ .collect (Collectors .toList ());
3394
+ }
3395
+
3271
3396
reader .moveNext ();
3272
3397
3273
3398
return true ;
3274
3399
}
3275
3400
3401
+ public static class MethodParam {
3402
+ public final int flags ;
3403
+ public final String name ;
3404
+
3405
+ public MethodParam (int flags , String name ) {
3406
+ this .flags = flags ;
3407
+ this .name = name ;
3408
+ }
3409
+ }
3276
3410
}
3277
3411
3278
3412
static class FieldDescription extends FeatureDescription {
3279
3413
String name ;
3280
3414
String descriptor ;
3281
3415
Object constantValue ;
3416
+ String keyName = "field" ;
3282
3417
3283
3418
@ Override
3284
3419
public int hashCode () {
@@ -3315,13 +3450,13 @@ public void write(Appendable output, String baselineVersion, String version) thr
3315
3450
if (shouldIgnore (baselineVersion , version ))
3316
3451
return ;
3317
3452
if (!versions .contains (version )) {
3318
- output .append ("-field" );
3453
+ output .append ("-" + keyName );
3319
3454
output .append (" name " + quote (name , false ));
3320
3455
output .append (" descriptor " + quote (descriptor , false ));
3321
3456
output .append ("\n " );
3322
3457
return ;
3323
3458
}
3324
- output .append ("field" );
3459
+ output .append (keyName );
3325
3460
output .append (" name " + name );
3326
3461
output .append (" descriptor " + descriptor );
3327
3462
if (constantValue != null ) {
@@ -3333,7 +3468,7 @@ public void write(Appendable output, String baselineVersion, String version) thr
3333
3468
3334
3469
@ Override
3335
3470
public boolean read (LineBasedReader reader ) throws IOException {
3336
- if (!"field" .equals (reader .lineKey ))
3471
+ if (!keyName .equals (reader .lineKey ))
3337
3472
return false ;
3338
3473
3339
3474
name = reader .attributes .get ("name" );
@@ -3366,6 +3501,19 @@ public boolean read(LineBasedReader reader) throws IOException {
3366
3501
3367
3502
}
3368
3503
3504
+ static final class RecordComponentDescription extends FieldDescription {
3505
+
3506
+ public RecordComponentDescription () {
3507
+ this .keyName = "recordcomponent" ;
3508
+ }
3509
+
3510
+ @ Override
3511
+ protected boolean shouldIgnore (String baselineVersion , String version ) {
3512
+ return false ;
3513
+ }
3514
+
3515
+ }
3516
+
3369
3517
static final class AnnotationDescription {
3370
3518
String annotationType ;
3371
3519
Map <String , Object > values ;
0 commit comments