diff --git a/pom.xml b/pom.xml
index 4e8418dc..8a0ccead 100644
--- a/pom.xml
+++ b/pom.xml
@@ -56,7 +56,7 @@
src/etc/header.txt
- 1.12.1
+ 1.0
5.5.2
3.24.2
7.2
@@ -123,9 +123,9 @@
- com.squareup
- javapoet
- ${javapoet-version}
+ io.soabase.java-composer
+ java-composer
+ ${java-composer-version}
diff --git a/record-builder-processor/pom.xml b/record-builder-processor/pom.xml
index 6465532e..4fab111f 100644
--- a/record-builder-processor/pom.xml
+++ b/record-builder-processor/pom.xml
@@ -32,8 +32,8 @@
- com.squareup
- javapoet
+ io.soabase.java-composer
+ java-composer
diff --git a/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/InternalRecordInterfaceProcessor.java b/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/InternalRecordInterfaceProcessor.java
index b050c5c0..b56da57a 100644
--- a/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/InternalRecordInterfaceProcessor.java
+++ b/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/InternalRecordInterfaceProcessor.java
@@ -27,8 +27,6 @@
import javax.lang.model.type.TypeKind;
import javax.tools.Diagnostic;
import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static io.soabase.recordbuilder.processor.ElementUtils.getBuilderName;
@@ -40,11 +38,7 @@ class InternalRecordInterfaceProcessor {
private final String packageName;
private final TypeSpec recordType;
private final List recordComponents;
- private final TypeElement iface;
private final ClassType recordClassType;
- private final List alternateMethods;
-
- private static final String FAKE_METHOD_NAME = "__FAKE__";
private static final Set javaBeanPrefixes = Set.of("get", "is");
@@ -56,7 +50,6 @@ private record Component(ExecutableElement element, Optional alternateNa
this.processingEnv = processingEnv;
packageName = packageNameOpt.orElseGet(() -> ElementUtils.getPackageName(iface));
recordComponents = getRecordComponents(iface);
- this.iface = iface;
ClassType ifaceClassType = ElementUtils.getClassType(iface, iface.getTypeParameters());
recordClassType = ElementUtils.getClassType(packageName,
@@ -64,15 +57,23 @@ private record Component(ExecutableElement element, Optional alternateNa
List typeVariables = iface.getTypeParameters().stream().map(TypeVariableName::get)
.collect(Collectors.toList());
- MethodSpec methodSpec = generateArgumentList();
-
- TypeSpec.Builder builder = TypeSpec.classBuilder(recordClassType.name()).addSuperinterface(iface.asType())
- .addMethod(methodSpec).addModifiers(Modifier.PUBLIC).addAnnotation(generatedRecordInterfaceAnnotation)
+ TypeSpec.Builder builder = TypeSpec.recordBuilder(recordClassType.name()).addSuperinterface(iface.asType())
.addTypeVariables(typeVariables);
if (metaData.addClassRetainedGenerated()) {
builder.addAnnotation(recordBuilderGeneratedAnnotation);
}
+ var actualPackage = ElementUtils.getPackageName(iface);
+ addVisibility(builder, actualPackage.equals(packageName), iface.getModifiers());
+
+ recordComponents.forEach(component -> {
+ String name = component.alternateName.orElseGet(() -> component.element.getSimpleName().toString());
+ FieldSpec parameterSpec = FieldSpec.builder(ClassName.get(component.element.getReturnType()), name).build();
+ builder.addTypeVariables(component.element.getTypeParameters().stream().map(TypeVariableName::get)
+ .collect(Collectors.toList()));
+ builder.addField(parameterSpec);
+ });
+
if (addRecordBuilder) {
ClassType builderClassType = ElementUtils.getClassType(packageName,
getBuilderName(iface, metaData, recordClassType, metaData.suffix()) + "."
@@ -90,7 +91,7 @@ private record Component(ExecutableElement element, Optional alternateNa
}
}
- alternateMethods = buildAlternateMethods(recordComponents);
+ addAlternateMethods(builder, recordComponents);
recordType = builder.build();
}
@@ -111,59 +112,27 @@ ClassType recordClassType() {
return recordClassType;
}
- String toRecord(String classSource) {
- // javapoet does yet support records - so a class was created and we can reshape it
- // The class will look something like this:
- /*
- * // Auto generated by io.soabase.recordbuilder.core.RecordBuilder: https://github.com/Randgalt/record-builder
- * package io.soabase.recordbuilder.test;
- *
- * import io.soabase.recordbuilder.core.RecordBuilder; import javax.annotation.processing.Generated;
- *
- * @Generated("io.soabase.recordbuilder.core.RecordInterface")
- *
- * @RecordBuilder public class MyRecord implements MyInterface { void __FAKE__(String name, int age) { } }
- */
- Pattern pattern = Pattern.compile("(.*)(implements.*)(\\{)(.*" + FAKE_METHOD_NAME + ")(\\(.*\\))(.*)",
- Pattern.MULTILINE | Pattern.DOTALL);
- Matcher matcher = pattern.matcher(classSource);
- if (!matcher.find() || matcher.groupCount() != 6) {
- processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
- "Internal error generating record. Group count: " + matcher.groupCount(), iface);
+ private void addVisibility(TypeSpec.Builder builder, boolean builderIsInRecordPackage, Set modifiers) {
+ if (builderIsInRecordPackage) {
+ if (modifiers.contains(Modifier.PUBLIC) || modifiers.contains(Modifier.PRIVATE)
+ || modifiers.contains(Modifier.PROTECTED)) {
+ builder.addModifiers(Modifier.PUBLIC); // builders are top level classes - can only be public or
+ // package-private
+ }
+ // is package-private
+ } else {
+ builder.addModifiers(Modifier.PUBLIC);
}
-
- String declaration = matcher.group(1).trim().replace("class", "record");
- String implementsSection = matcher.group(2).trim();
- String argumentList = matcher.group(5).trim();
-
- StringBuilder fixedRecord = new StringBuilder(declaration).append(argumentList).append(' ')
- .append(implementsSection).append(" {");
- alternateMethods.forEach(method -> fixedRecord.append('\n').append(method));
- fixedRecord.append('}');
- return fixedRecord.toString();
- }
-
- private MethodSpec generateArgumentList() {
- MethodSpec.Builder builder = MethodSpec.methodBuilder(FAKE_METHOD_NAME);
- recordComponents.forEach(component -> {
- String name = component.alternateName.orElseGet(() -> component.element.getSimpleName().toString());
- ParameterSpec parameterSpec = ParameterSpec.builder(ClassName.get(component.element.getReturnType()), name)
- .build();
- builder.addTypeVariables(component.element.getTypeParameters().stream().map(TypeVariableName::get)
- .collect(Collectors.toList()));
- builder.addParameter(parameterSpec);
- });
- return builder.build();
}
- private List buildAlternateMethods(List recordComponents) {
- return recordComponents.stream().filter(component -> component.alternateName.isPresent()).map(component -> {
+ private void addAlternateMethods(TypeSpec.Builder builder, List recordComponents) {
+ recordComponents.stream().filter(component -> component.alternateName.isPresent()).forEach(component -> {
var method = MethodSpec.methodBuilder(component.element.getSimpleName().toString())
.addAnnotation(Override.class).addAnnotation(generatedRecordInterfaceAnnotation)
.returns(ClassName.get(component.element.getReturnType())).addModifiers(Modifier.PUBLIC)
.addCode("return $L();", component.alternateName.get()).build();
- return method.toString();
- }).collect(Collectors.toList());
+ builder.addMethod(method);
+ });
}
private List getRecordComponents(TypeElement iface) {
diff --git a/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/RecordBuilderProcessor.java b/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/RecordBuilderProcessor.java
index ac5b34f0..643d8e5c 100644
--- a/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/RecordBuilderProcessor.java
+++ b/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/RecordBuilderProcessor.java
@@ -36,7 +36,6 @@
import java.io.Writer;
import java.util.Optional;
import java.util.Set;
-import java.util.function.Function;
public class RecordBuilderProcessor extends AbstractProcessor {
private static final String RECORD_BUILDER = RecordBuilder.class.getName();
@@ -173,7 +172,7 @@ private void processRecordInterface(TypeElement element, boolean addRecordBuilde
return;
}
writeRecordInterfaceJavaFile(element, internalProcessor.packageName(), internalProcessor.recordClassType(),
- internalProcessor.recordType(), metaData, internalProcessor::toRecord);
+ internalProcessor.recordType(), metaData);
}
private void processRecordBuilder(TypeElement record, RecordBuilder.Options metaData,
@@ -229,12 +228,10 @@ private void writeRecordBuilderJavaFile(TypeElement record, String packageName,
}
private void writeRecordInterfaceJavaFile(TypeElement element, String packageName, ClassType classType,
- TypeSpec type, RecordBuilder.Options metaData, Function toRecordProc) {
+ TypeSpec type, RecordBuilder.Options metaData) {
JavaFile javaFile = javaFileBuilder(packageName, type, metaData);
- String classSourceCode = javaFile.toString();
- int generatedIndex = classSourceCode.indexOf("@Generated");
- String recordSourceCode = toRecordProc.apply(classSourceCode);
+ String recordSourceCode = javaFile.toString();
Filer filer = processingEnv.getFiler();
try {