@@ -6,7 +6,7 @@ use crate::oomir::{self, DataTypeMethod, Signature, Type};
66use ristretto_classfile:: {
77 self as jvm, BaseType , ClassAccessFlags , ClassFile , ConstantPool , FieldAccessFlags ,
88 MethodAccessFlags , Version ,
9- attributes:: { Attribute , Instruction , MaxStack } ,
9+ attributes:: { Attribute , Instruction , MaxStack , InnerClass , NestedClassAccessFlags } ,
1010} ;
1111use std:: collections:: HashMap ;
1212
@@ -91,6 +91,7 @@ pub(super) fn create_data_type_classfile_for_class(
9191 super_class_name_jvm : & str ,
9292 implements_interfaces : Vec < String > ,
9393 module : & oomir:: Module ,
94+ subclasses : Vec < String > ,
9495) -> jvm:: Result < Vec < u8 > > {
9596 let mut cp = ConstantPool :: default ( ) ;
9697
@@ -244,6 +245,51 @@ pub(super) fn create_data_type_classfile_for_class(
244245 }
245246 }
246247
248+ // --- Add InnerClasses Attribute (for nested/member classes) ---
249+ if !subclasses. is_empty ( ) {
250+ let mut inner_classes_vec: Vec < InnerClass > = Vec :: with_capacity ( subclasses. len ( ) ) ;
251+
252+ for subclass_name in & subclasses {
253+ // Ensure subclass class_info is in the constant pool
254+ let class_info_index = class_file. constant_pool . add_class ( subclass_name) ?;
255+
256+ // The outer class is this class
257+ let outer_class_info_index = class_file. this_class ;
258+
259+ // Derive simple name: part after last '$'. If there's no '$', treat as unnamed (0).
260+ let simple_name_part = subclass_name. rsplit ( '$' ) . next ( ) . unwrap_or ( subclass_name) ;
261+
262+ // If the simple name looks like an anonymous class (all digits), set name_index = 0
263+ let name_index = if simple_name_part. chars ( ) . all ( |c| c. is_ascii_digit ( ) ) {
264+ 0
265+ } else if simple_name_part == * subclass_name && !subclass_name. contains ( '$' ) {
266+ // No '$' present -> not an inner/member class; leave name_index = 0
267+ 0
268+ } else {
269+ class_file
270+ . constant_pool
271+ . add_utf8 ( simple_name_part) ?
272+ } ;
273+
274+ // Default to PUBLIC | STATIC for generated nested classes. This can be adjusted
275+ // if more precise access info becomes available.
276+ let access_flags = NestedClassAccessFlags :: PUBLIC | NestedClassAccessFlags :: STATIC ;
277+
278+ inner_classes_vec. push ( InnerClass {
279+ class_info_index,
280+ outer_class_info_index,
281+ name_index,
282+ access_flags,
283+ } ) ;
284+ }
285+
286+ let inner_classes_attr_name_index = class_file. constant_pool . add_utf8 ( "InnerClasses" ) ?;
287+ class_file. attributes . push ( Attribute :: InnerClasses {
288+ name_index : inner_classes_attr_name_index,
289+ classes : inner_classes_vec,
290+ } ) ;
291+ }
292+
247293 // --- Add SourceFile Attribute ---
248294 let simple_name = class_name_jvm. split ( '/' ) . last ( ) . unwrap_or ( class_name_jvm) ;
249295 let source_file_name = format ! ( "{}.rs" , simple_name) ;
0 commit comments