Skip to content

Commit

Permalink
Support records (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
dstepanov authored Oct 19, 2023
1 parent 55cbe0f commit a29a152
Show file tree
Hide file tree
Showing 12 changed files with 718 additions and 250 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import io.micronaut.sourcegen.model.MethodDef;
import io.micronaut.sourcegen.model.ObjectDef;
import io.micronaut.sourcegen.model.PropertyDef;
import io.micronaut.sourcegen.model.RecordDef;
import io.micronaut.sourcegen.model.StatementDef;
import io.micronaut.sourcegen.model.TypeDef;
import io.micronaut.sourcegen.model.VariableDef;
Expand Down Expand Up @@ -69,145 +70,168 @@ public VisitorContext.Language getLanguage() {
@Override
public void write(ObjectDef objectDef, Writer writer) throws IOException {
if (objectDef instanceof ClassDef classDef) {
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(classDef.getSimpleName());
classBuilder.addModifiers(classDef.getModifiersArray());
classDef.getTypeVariables().stream().map(this::asTypeVariable).forEach(classBuilder::addTypeVariable);
classDef.getSuperinterfaces().stream().map(this::asType).forEach(classBuilder::addSuperinterface);
writeClass(writer, classDef);
} else if (objectDef instanceof RecordDef recordDef) {
writeRecord(writer, recordDef);
} else if (objectDef instanceof InterfaceDef interfaceDef) {
writeInterface(writer, interfaceDef);
} else {
throw new IllegalStateException("Unknown object definition: " + objectDef);
}
}

for (PropertyDef property : classDef.getProperties()) {
TypeName propertyType = asType(property.getType());
String propertyName = property.getName();
FieldSpec.Builder fieldBuilder = FieldSpec.builder(
propertyType,
propertyName
).addModifiers(Modifier.PRIVATE);
for (AnnotationDef annotation : property.getAnnotations()) {
fieldBuilder.addAnnotation(
asAnnotationSpec(annotation)
);
}
classBuilder.addField(
fieldBuilder
.build()
private void writeInterface(Writer writer, InterfaceDef interfaceDef) throws IOException {
TypeSpec.Builder interfaceBuilder = TypeSpec.interfaceBuilder(interfaceDef.getSimpleName());
interfaceBuilder.addModifiers(interfaceDef.getModifiersArray());
interfaceDef.getTypeVariables().stream().map(this::asTypeVariable).forEach(interfaceBuilder::addTypeVariable);
interfaceDef.getSuperinterfaces().stream().map(this::asType).forEach(interfaceBuilder::addSuperinterface);

for (PropertyDef property : interfaceDef.getProperties()) {
TypeName propertyType = asType(property.getType());
String propertyName = property.getName();
FieldSpec.Builder fieldBuilder = FieldSpec.builder(
propertyType,
propertyName
).addModifiers(Modifier.PRIVATE);
for (AnnotationDef annotation : property.getAnnotations()) {
fieldBuilder.addAnnotation(
asAnnotationSpec(annotation)
);
String capitalizedPropertyName = NameUtils.capitalize(propertyName);
classBuilder.addMethod(MethodSpec.methodBuilder("get" + capitalizedPropertyName)
.addModifiers(property.getModifiersArray())
.returns(propertyType)
.addStatement("return this." + propertyName)
.build());
classBuilder.addMethod(MethodSpec.methodBuilder("set" + capitalizedPropertyName)
.addModifiers(property.getModifiersArray())
.addParameter(ParameterSpec.builder(propertyType, propertyName).build())
.addStatement("this." + propertyName + " = " + propertyName)
.build());
}
for (FieldDef field : classDef.getFields()) {
FieldSpec.Builder fieldBuilder = FieldSpec.builder(
asType(field.getType()),
field.getName()
).addModifiers(field.getModifiersArray());
for (AnnotationDef annotation : field.getAnnotations()) {
fieldBuilder.addAnnotation(
asAnnotationSpec(annotation)
);
}
classBuilder.addField(
fieldBuilder
.build()
interfaceBuilder.addField(
fieldBuilder
.build()
);
String capitalizedPropertyName = NameUtils.capitalize(propertyName);
interfaceBuilder.addMethod(MethodSpec.methodBuilder("get" + capitalizedPropertyName)
.addModifiers(property.getModifiersArray())
.returns(propertyType)
// .addStatement("return this." + propertyName)
.build());
interfaceBuilder.addMethod(MethodSpec.methodBuilder("set" + capitalizedPropertyName)
.addModifiers(property.getModifiersArray())
.addParameter(ParameterSpec.builder(propertyType, propertyName).build())
// .addStatement("this." + propertyName + " = " + propertyName)
.build());
}
for (MethodDef method : interfaceDef.getMethods()) {
interfaceBuilder.addMethod(
asMethodSpec(interfaceDef, method)
);
}
JavaFile javaFile = JavaFile.builder(interfaceDef.getPackageName(), interfaceBuilder.build()).build();
javaFile.writeTo(writer);
}

private void writeClass(Writer writer, ClassDef classDef) throws IOException {
TypeSpec.Builder classBuilder = TypeSpec.classBuilder(classDef.getSimpleName());
classBuilder.addModifiers(classDef.getModifiersArray());
classDef.getTypeVariables().stream().map(this::asTypeVariable).forEach(classBuilder::addTypeVariable);
classDef.getSuperinterfaces().stream().map(this::asType).forEach(classBuilder::addSuperinterface);

for (PropertyDef property : classDef.getProperties()) {
TypeName propertyType = asType(property.getType());
String propertyName = property.getName();
FieldSpec.Builder fieldBuilder = FieldSpec.builder(
propertyType,
propertyName
).addModifiers(Modifier.PRIVATE);
for (AnnotationDef annotation : property.getAnnotations()) {
fieldBuilder.addAnnotation(
asAnnotationSpec(annotation)
);
}
for (MethodDef method : classDef.getMethods()) {
MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(method.getName())
.addModifiers(method.getModifiersArray())
.returns(asType(method.getReturnType()))
.addParameters(
method.getParameters().stream()
.map(param -> ParameterSpec.builder(
asType(param.getType()),
param.getName(),
param.getModifiersArray()
).build())
.toList()
);
for (AnnotationDef annotation : method.getAnnotations()) {
methodBuilder.addAnnotation(
asAnnotationSpec(annotation)
);
}
method.getStatements().stream()
.map(st -> renderStatement(classDef, method, st))
.forEach(methodBuilder::addStatement);
classBuilder.addMethod(
methodBuilder.build()
classBuilder.addField(
fieldBuilder
.build()
);
String capitalizedPropertyName = NameUtils.capitalize(propertyName);
classBuilder.addMethod(MethodSpec.methodBuilder("get" + capitalizedPropertyName)
.addModifiers(property.getModifiersArray())
.returns(propertyType)
.addStatement("return this." + propertyName)
.build());
classBuilder.addMethod(MethodSpec.methodBuilder("set" + capitalizedPropertyName)
.addModifiers(property.getModifiersArray())
.addParameter(ParameterSpec.builder(propertyType, propertyName).build())
.addStatement("this." + propertyName + " = " + propertyName)
.build());
}
for (FieldDef field : classDef.getFields()) {
FieldSpec.Builder fieldBuilder = FieldSpec.builder(
asType(field.getType()),
field.getName()
).addModifiers(field.getModifiersArray());
for (AnnotationDef annotation : field.getAnnotations()) {
fieldBuilder.addAnnotation(
asAnnotationSpec(annotation)
);
}
JavaFile javaFile = JavaFile.builder(classDef.getPackageName(), classBuilder.build()).build();
javaFile.writeTo(writer);
} else if (objectDef instanceof InterfaceDef interfaceDef) {
TypeSpec.Builder interfaceBuilder = TypeSpec.interfaceBuilder(interfaceDef.getSimpleName());
interfaceBuilder.addModifiers(interfaceDef.getModifiersArray());
interfaceDef.getTypeVariables().stream().map(this::asTypeVariable).forEach(interfaceBuilder::addTypeVariable);
interfaceDef.getSuperinterfaces().stream().map(this::asType).forEach(interfaceBuilder::addSuperinterface);
classBuilder.addField(
fieldBuilder
.build()
);
}
for (MethodDef method : classDef.getMethods()) {
classBuilder.addMethod(
asMethodSpec(classDef, method)
);
}
JavaFile javaFile = JavaFile.builder(classDef.getPackageName(), classBuilder.build()).build();
javaFile.writeTo(writer);
}

for (PropertyDef property : interfaceDef.getProperties()) {
TypeName propertyType = asType(property.getType());
String propertyName = property.getName();
FieldSpec.Builder fieldBuilder = FieldSpec.builder(
propertyType,
propertyName
).addModifiers(Modifier.PRIVATE);
for (AnnotationDef annotation : property.getAnnotations()) {
fieldBuilder.addAnnotation(
asAnnotationSpec(annotation)
);
}
interfaceBuilder.addField(
fieldBuilder
.build()
);
String capitalizedPropertyName = NameUtils.capitalize(propertyName);
interfaceBuilder.addMethod(MethodSpec.methodBuilder("get" + capitalizedPropertyName)
.addModifiers(property.getModifiersArray())
.returns(propertyType)
// .addStatement("return this." + propertyName)
.build());
interfaceBuilder.addMethod(MethodSpec.methodBuilder("set" + capitalizedPropertyName)
.addModifiers(property.getModifiersArray())
.addParameter(ParameterSpec.builder(propertyType, propertyName).build())
// .addStatement("this." + propertyName + " = " + propertyName)
.build());
}
for (MethodDef method : interfaceDef.getMethods()) {
MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(method.getName())
.addModifiers(method.getModifiersArray())
.returns(asType(method.getReturnType()))
.addParameters(
method.getParameters().stream()
.map(param -> ParameterSpec.builder(
asType(param.getType()),
param.getName(),
param.getModifiersArray()
).build())
.toList()
);
for (AnnotationDef annotation : method.getAnnotations()) {
methodBuilder.addAnnotation(
asAnnotationSpec(annotation)
);
}
method.getStatements().stream()
.map(st -> renderStatement(interfaceDef, method, st))
.forEach(methodBuilder::addStatement);
interfaceBuilder.addMethod(
methodBuilder.build()
private void writeRecord(Writer writer, RecordDef recordDef) throws IOException {
TypeSpec.Builder classBuilder = TypeSpec.recordBuilder(recordDef.getSimpleName());
classBuilder.addModifiers(recordDef.getModifiersArray());
recordDef.getTypeVariables().stream().map(this::asTypeVariable).forEach(classBuilder::addTypeVariable);
recordDef.getSuperinterfaces().stream().map(this::asType).forEach(classBuilder::addSuperinterface);

for (PropertyDef property : recordDef.getProperties()) {
TypeName propertyType = asType(property.getType());
String propertyName = property.getName();
ParameterSpec.Builder componentBuilder = ParameterSpec.builder(propertyType, propertyName);
for (AnnotationDef annotation : property.getAnnotations()) {
componentBuilder.addAnnotation(
asAnnotationSpec(annotation)
);
}
JavaFile javaFile = JavaFile.builder(interfaceDef.getPackageName(), interfaceBuilder.build()).build();
javaFile.writeTo(writer);
} else {
throw new IllegalStateException("Unknown object definition: " + objectDef);
classBuilder.addRecordComponent(
componentBuilder.build()
);
}
for (MethodDef method : recordDef.getMethods()) {
classBuilder.addMethod(
asMethodSpec(recordDef, method)
);
}
JavaFile javaFile = JavaFile.builder(recordDef.getPackageName(), classBuilder.build()).build();
javaFile.writeTo(writer);
}

private MethodSpec asMethodSpec(ObjectDef objectDef, MethodDef method) {
MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder(method.getName())
.addModifiers(method.getModifiersArray())
.returns(asType(method.getReturnType()))
.addParameters(
method.getParameters().stream()
.map(param -> ParameterSpec.builder(
asType(param.getType()),
param.getName(),
param.getModifiersArray()
).build())
.toList()
);
for (AnnotationDef annotation : method.getAnnotations()) {
methodBuilder.addAnnotation(
asAnnotationSpec(annotation)
);
}
method.getStatements().stream()
.map(st -> renderStatement(objectDef, method, st))
.forEach(methodBuilder::addStatement);

return methodBuilder.build();
}

private TypeVariableName asTypeVariable(TypeDef.TypeVariable tv) {
Expand Down
Loading

0 comments on commit a29a152

Please sign in to comment.