33import com .palantir .javapoet .*;
44
55import javax .lang .model .element .*;
6+ import javax .lang .model .type .ArrayType ;
7+ import javax .lang .model .type .TypeMirror ;
68import java .lang .foreign .MemorySegment ;
9+ import java .util .ArrayList ;
710import java .util .List ;
811
9- import static com .github .elebras1 .flecs .processor .ComponentGenerator .LAYOUT_FIELD_CLASS ;
10-
1112public class ComponentViewGenerator extends AbstractGenerator {
13+
1214 private static final String COMPONENT_VIEW_INTERFACE = "com.github.elebras1.flecs.ComponentView" ;
1315
16+ private static final ClassName LAYOUT_FIELD_CLASS = ClassName .get ("com.github.elebras1.flecs.util" , "LayoutField" );
17+
1418 public JavaFile generate (TypeElement recordElement , List <VariableElement > fields ) {
1519 String packageName = this .getPackageName (recordElement );
1620 String recordName = recordElement .getSimpleName ().toString ();
1721 String componentViewClassName = recordName + "ComponentView" ;
1822
1923 String componentReference = packageName + "." + recordName + "Component" ;
2024
25+ ClassName viewType = ClassName .get (packageName , componentViewClassName );
26+
2127 TypeSpec componentClass = TypeSpec .classBuilder (componentViewClassName )
2228 .addModifiers (Modifier .PUBLIC , Modifier .FINAL )
2329 .addSuperinterface (ClassName .bestGuess (COMPONENT_VIEW_INTERFACE ))
2430 .addField (this .createField ())
25- .addMethod (this .createSetterMethod ())
26- .addMethods (this .createMethods (fields , componentReference ))
31+ .addMethod (this .createSetterMemorySegment ())
32+ .addMethods (this .createGetterFields (fields , componentReference , viewType ))
2733 .build ();
2834
29- return JavaFile .builder (packageName , componentClass ).addFileComment ("Generated by ComponentViewGenerator" ).indent (" " ).build ();
35+ return JavaFile .builder (packageName , componentClass )
36+ .addFileComment ("Generated by ComponentViewGenerator" )
37+ .indent (" " )
38+ .build ();
3039 }
3140
3241 private FieldSpec createField () {
3342 return FieldSpec .builder (MemorySegment .class , "memorySegment" , Modifier .PRIVATE ).build ();
3443 }
3544
36- private MethodSpec createSetterMethod () {
45+ private MethodSpec createSetterMemorySegment () {
3746 return MethodSpec .methodBuilder ("setMemorySegment" )
3847 .addAnnotation (Override .class )
3948 .addModifiers (Modifier .PUBLIC )
@@ -43,29 +52,79 @@ private MethodSpec createSetterMethod() {
4352 .build ();
4453 }
4554
46- private Iterable <MethodSpec > createMethods (List <VariableElement > fields , String componentReference ) {
47- return fields .stream ().map (field -> this .createMethod (field , componentReference )).toList ();
55+ private Iterable <MethodSpec > createGetterFields (List <VariableElement > fields , String componentReference , ClassName viewType ) {
56+ return fields .stream ()
57+ .flatMap (field -> this .createGetters (field , componentReference , viewType ).stream ())
58+ .toList ();
4859 }
4960
50- private MethodSpec createMethod (VariableElement field , String componentReference ) {
51- MethodSpec .Builder method = MethodSpec .methodBuilder (field .getSimpleName ().toString ()).addModifiers (Modifier .PUBLIC ).returns (TypeName .get (field .asType ()));
52-
61+ private List <MethodSpec > createGetters (VariableElement field , String componentReference , ClassName viewType ) {
62+ List <MethodSpec > methods = new ArrayList <>();
5363 String fieldName = field .getSimpleName ().toString ();
5464 String offsetName = "OFFSET_" + fieldName .toUpperCase ();
5565 String typeName = field .asType ().toString ();
56- String getterMethod = this .getGetterMethod (typeName );
57- if ("java.lang.String" .equals (typeName )) {
58- int size = this .getStringSize (field );
59- method .addStatement ("$T $L = $L.$L(memorySegment, $L.$L, $L)" , String .class , fieldName , LAYOUT_FIELD_CLASS , getterMethod , componentReference , offsetName , size );
60- } else if (typeName .endsWith ("[]" )) {
66+
67+ if (typeName .endsWith ("[]" )) {
6168 int length = this .getArrayLength (field );
62- method .addStatement ("$L $L = $L.$L(memorySegment, $L.$L, $L)" , typeName , fieldName , LAYOUT_FIELD_CLASS , getterMethod , componentReference , offsetName , length );
69+ TypeName elementType = this .getElementType (field );
70+ String rawType = elementType .toString ();
71+
72+ String suffix = Character .toUpperCase (rawType .charAt (0 )) + rawType .substring (1 );
73+ String methodAtIndex = "get" + suffix + "AtIndex" ;
74+ String setterAtIndex = "set" + suffix + "AtIndex" ;
75+
76+ methods .add (MethodSpec .methodBuilder (fieldName + "Length" )
77+ .addModifiers (Modifier .PUBLIC )
78+ .returns (int .class )
79+ .addStatement ("return $L" , length )
80+ .build ());
81+
82+ methods .add (MethodSpec .methodBuilder (fieldName )
83+ .addModifiers (Modifier .PUBLIC )
84+ .addParameter (int .class , "index" )
85+ .returns (elementType )
86+ .addStatement ("return $T.$L(memorySegment, $L.$L, index)" , LAYOUT_FIELD_CLASS , methodAtIndex , componentReference , offsetName )
87+ .build ());
88+
89+ methods .add (MethodSpec .methodBuilder (fieldName )
90+ .addModifiers (Modifier .PUBLIC )
91+ .addParameter (int .class , "index" )
92+ .addParameter (elementType , "value" )
93+ .returns (viewType )
94+ .addStatement ("$T.$L(memorySegment, $L.$L, index, value)" , LAYOUT_FIELD_CLASS , setterAtIndex , componentReference , offsetName )
95+ .addStatement ("return this" )
96+ .build ());
97+
6398 } else {
64- method .addStatement ("$L $L = $L.$L(memorySegment, $L.$L)" , typeName , fieldName , LAYOUT_FIELD_CLASS , getterMethod , componentReference , offsetName );
99+ MethodSpec .Builder getter = MethodSpec .methodBuilder (fieldName ).addModifiers (Modifier .PUBLIC ).returns (TypeName .get (field .asType ()));
100+ String getterHelper = this .getGetterMethod (typeName );
101+ if ("java.lang.String" .equals (typeName )) {
102+ int size = this .getStringSize (field );
103+ getter .addStatement ("return $T.$L(memorySegment, $L.$L, $L)" , LAYOUT_FIELD_CLASS , getterHelper , componentReference , offsetName , size );
104+ } else {
105+ getter .addStatement ("return $T.$L(memorySegment, $L.$L)" , LAYOUT_FIELD_CLASS , getterHelper , componentReference , offsetName );
106+ }
107+ methods .add (getter .build ());
108+
109+ MethodSpec .Builder setter = MethodSpec .methodBuilder (fieldName ).addModifiers (Modifier .PUBLIC ).addParameter (TypeName .get (field .asType ()), "value" ).returns (viewType );
110+ if ("java.lang.String" .equals (typeName )) {
111+ int size = this .getStringSize (field );
112+ setter .addStatement ("$T.set(memorySegment, $L.$L, value, $L)" , LAYOUT_FIELD_CLASS , componentReference , offsetName , size );
113+ } else {
114+ setter .addStatement ("$T.set(memorySegment, $L.$L, value)" , LAYOUT_FIELD_CLASS , componentReference , offsetName );
115+ }
116+ setter .addStatement ("return this" );
117+ methods .add (setter .build ());
65118 }
66119
67- method .addStatement ("return $L" , fieldName );
120+ return methods ;
121+ }
68122
69- return method .build ();
123+ private TypeName getElementType (VariableElement field ) {
124+ TypeMirror typeMirror = field .asType ();
125+ if (typeMirror instanceof ArrayType arrayType ) {
126+ return TypeName .get (arrayType .getComponentType ());
127+ }
128+ return TypeName .get (typeMirror );
70129 }
71- }
130+ }
0 commit comments