diff --git a/record-builder-core/src/main/java/io/soabase/recordbuilder/core/RecordBuilder.java b/record-builder-core/src/main/java/io/soabase/recordbuilder/core/RecordBuilder.java
index 4583fbd1..b56b94a5 100644
--- a/record-builder-core/src/main/java/io/soabase/recordbuilder/core/RecordBuilder.java
+++ b/record-builder-core/src/main/java/io/soabase/recordbuilder/core/RecordBuilder.java
@@ -267,6 +267,16 @@
*/
String beanClassName() default "";
+ /**
+ * When to add the {@link javax.annotation.processing.Generated} annotation to generated files
+ *
+ *
+ * If set to 'ALWAYS' (default), then always add the {@link javax.annotation.processing.Generated} annotation to
+ * generated files.
+ *
+ */
+ GeneratedAnnotation addGeneratedAnnotation() default GeneratedAnnotation.ALWAYS;
+
/**
* If true, generated classes are annotated with {@code RecordBuilderGenerated} which has a retention policy of
* {@code CLASS}. This ensures that analyzers such as Jacoco will ignore the generated class.
@@ -378,6 +388,18 @@ enum ConcreteSettersForOptionalMode {
DISABLED, ENABLED, ENABLED_WITH_NULLABLE_ANNOTATION,
}
+ enum GeneratedAnnotation {
+ /**
+ * Always add the {@link javax.annotation.processing.Generated} annotation (default).
+ */
+ ALWAYS,
+ /**
+ * Never add the {@link javax.annotation.processing.Generated} annotation.
+ */
+ NEVER,
+ /* IF_ON_CLASSPATH, */ /* USER_SUPPLIED, */
+ }
+
/**
* Apply to record components to specify a field initializer for the generated builder
*/
diff --git a/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/InternalRecordBuilderProcessor.java b/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/InternalRecordBuilderProcessor.java
index 4faab9cd..ea0b2407 100644
--- a/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/InternalRecordBuilderProcessor.java
+++ b/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/InternalRecordBuilderProcessor.java
@@ -37,8 +37,7 @@
import static io.soabase.recordbuilder.processor.CollectionBuilderUtils.SingleItemsMetaDataMode.STANDARD_FOR_SETTER;
import static io.soabase.recordbuilder.processor.ElementUtils.getClassTypeFromNames;
import static io.soabase.recordbuilder.processor.ElementUtils.getWithMethodName;
-import static io.soabase.recordbuilder.processor.RecordBuilderProcessor.generatedRecordBuilderAnnotation;
-import static io.soabase.recordbuilder.processor.RecordBuilderProcessor.recordBuilderGeneratedAnnotation;
+import static io.soabase.recordbuilder.processor.RecordBuilderProcessor.*;
import static javax.tools.Diagnostic.Kind.ERROR;
class InternalRecordBuilderProcessor {
@@ -80,11 +79,16 @@ class InternalRecordBuilderProcessor {
constructorVisibilityModifier = metaData.publicBuilderConstructors() ? Modifier.PUBLIC : Modifier.PRIVATE;
initializers = recordFacade.initializers();
- builder = TypeSpec.classBuilder(builderClassType.name()).addAnnotation(generatedRecordBuilderAnnotation)
- .addModifiers(metaData.builderClassModifiers()).addTypeVariables(typeVariables);
+ builder = TypeSpec.classBuilder(builderClassType.name()).addModifiers(metaData.builderClassModifiers())
+ .addTypeVariables(typeVariables);
if (metaData.addClassRetainedGenerated()) {
builder.addAnnotation(recordBuilderGeneratedAnnotation);
}
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> builder.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
if (!validateMethodNameConflicts(processingEnv, recordFacade.element())) {
builderType = Optional.empty();
@@ -255,12 +259,16 @@ private void addStagedBuilderClasses() {
* default Person build() { return builder().build(); }
*/
var classBuilder = TypeSpec.interfaceBuilder(stagedBuilderName(builderClassType))
- .addAnnotation(generatedRecordBuilderAnnotation)
.addJavadoc("Add final staged builder to {@code $L}\n", recordClassType.name())
.addModifiers(Modifier.PUBLIC).addTypeVariables(typeVariables);
if (metaData.addClassRetainedGenerated()) {
classBuilder.addAnnotation(recordBuilderGeneratedAnnotation);
}
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> classBuilder.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
MethodSpec buildMethod = buildMethod().addModifiers(Modifier.PUBLIC, Modifier.DEFAULT)
.addStatement("return $L().$L()", metaData.builderMethodName(), metaData.buildMethodName()).build();
@@ -275,11 +283,15 @@ private void addStagedBuilderClasses() {
optionalComponent.name());
addConstructorAnnotations(optionalComponent, parameterSpecBuilder);
var methodSpec = MethodSpec.methodBuilder(optionalComponent.name())
- .addAnnotation(generatedRecordBuilderAnnotation)
.addJavadoc("Call builder for optional component {@code $L}", optionalComponent.name())
.addModifiers(Modifier.PUBLIC, Modifier.DEFAULT).addParameter(parameterSpecBuilder.build())
- .addCode(codeBlock).returns(builderClassType.typeName()).build();
- classBuilder.addMethod(methodSpec);
+ .addCode(codeBlock).returns(builderClassType.typeName());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> methodSpec.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
+ classBuilder.addMethod(methodSpec.build());
if (metaData
.addConcreteSettersForOptional() != RecordBuilder.ConcreteSettersForOptionalMode.DISABLED) {
@@ -289,9 +301,13 @@ private void addStagedBuilderClasses() {
var builderMethod = MethodSpec.methodBuilder(metaData.builderMethodName())
.addJavadoc("Return a new builder with all fields set to the current values in this builder\n")
- .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT).addAnnotation(generatedRecordBuilderAnnotation)
- .returns(builderClassType.typeName()).build();
- classBuilder.addMethod(builderMethod);
+ .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT).returns(builderClassType.typeName());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> builderMethod.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
+ classBuilder.addMethod(builderMethod.build());
builder.addType(classBuilder.build());
}
@@ -303,19 +319,27 @@ private void add1StagedBuilderClass(RecordClassType component, Optional classBuilder.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
var returnType = nextComponent.map(this::stagedBuilderType)
.orElseGet(() -> stagedBuilderType(builderClassType));
- var methodSpec = MethodSpec.methodBuilder(prefixedName(component, false))
- .addAnnotation(generatedRecordBuilderAnnotation).returns(returnType.typeName())
+ var methodSpec = MethodSpec.methodBuilder(prefixedName(component, false)).returns(returnType.typeName())
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT);
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> methodSpec.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
methodSpec.addJavadoc("Set a new value for the {@code $L} record component in the builder\n", component.name());
var parameterSpecBuilder = ParameterSpec.builder(component.typeName(), component.name());
@@ -337,11 +361,15 @@ private void add1ConcreteOptionalSetterMethodToFinalStage(RecordClassType option
var concreteParameterSpecBuilder = ParameterSpec.builder(type.valueType(), optionalComponent.name());
applyConcreteOptionalSetterNullable(concreteParameterSpecBuilder);
var concreteMethodSpec = MethodSpec.methodBuilder(optionalComponent.name())
- .addAnnotation(generatedRecordBuilderAnnotation)
.addJavadoc("Call builder for optional component {@code $L}", optionalComponent.name())
.addModifiers(Modifier.PUBLIC, Modifier.DEFAULT).addParameter(concreteParameterSpecBuilder.build())
- .addCode(concreteCodeBlock).returns(builderClassType.typeName()).build();
- classBuilder.addMethod(concreteMethodSpec);
+ .addCode(concreteCodeBlock).returns(builderClassType.typeName());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> concreteMethodSpec.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
+ classBuilder.addMethod(concreteMethodSpec.build());
}
}
@@ -365,12 +393,16 @@ private void addWithNestedClass() {
* public class MyRecordBuilder { public interface With { // with methods } }
*/
var classBuilder = TypeSpec.interfaceBuilder(metaData.withClassName())
- .addAnnotation(generatedRecordBuilderAnnotation)
.addJavadoc("Add withers to {@code $L}\n", recordClassType.name()).addModifiers(Modifier.PUBLIC)
.addTypeVariables(typeVariables);
if (metaData.addClassRetainedGenerated()) {
classBuilder.addAnnotation(recordBuilderGeneratedAnnotation);
}
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> classBuilder.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
recordComponents.forEach(component -> addNestedGetterMethod(classBuilder, component, component.name()));
addWithBuilderMethod(classBuilder);
addWithSuppliedBuilderMethod(classBuilder);
@@ -392,9 +424,13 @@ private void addBeanNestedClass() {
* public class MyRecordBuilder { public interface Bean { // getter methods } }
*/
var classBuilder = TypeSpec.interfaceBuilder(metaData.beanClassName())
- .addAnnotation(generatedRecordBuilderAnnotation)
.addJavadoc("Add getters to {@code $L}\n", recordClassType.name()).addModifiers(Modifier.PUBLIC)
.addTypeVariables(typeVariables);
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> classBuilder.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
recordComponents.forEach(component -> {
if (prefixedName(component, true).equals(component.name())) {
return;
@@ -417,11 +453,15 @@ private void addWithSuppliedBuilderMethod(TypeSpec.Builder classBuilder) {
var consumerType = ParameterizedTypeName.get(ClassName.get(Consumer.class), builderClassType.typeName());
var parameter = ParameterSpec.builder(consumerType, "consumer").build();
var methodSpec = MethodSpec.methodBuilder(metaData.withClassMethodPrefix())
- .addAnnotation(generatedRecordBuilderAnnotation)
.addJavadoc("Return a new record built from the builder passed to the given consumer")
.addModifiers(Modifier.PUBLIC, Modifier.DEFAULT).addParameter(parameter)
- .returns(recordClassType.typeName()).addCode(codeBlockBuilder.build()).build();
- classBuilder.addMethod(methodSpec);
+ .returns(recordClassType.typeName()).addCode(codeBlockBuilder.build());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> methodSpec.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
+ classBuilder.addMethod(methodSpec.build());
}
private void addWithBuilderMethod(TypeSpec.Builder classBuilder) {
@@ -435,11 +475,15 @@ private void addWithBuilderMethod(TypeSpec.Builder classBuilder) {
addComponentCallsAsArguments(-1, codeBlockBuilder);
codeBlockBuilder.add(");");
var methodSpec = MethodSpec.methodBuilder(metaData.withClassMethodPrefix())
- .addAnnotation(generatedRecordBuilderAnnotation)
.addJavadoc("Return a new record builder using the current values")
.addModifiers(Modifier.PUBLIC, Modifier.DEFAULT).returns(builderClassType.typeName())
- .addCode(codeBlockBuilder.build()).build();
- classBuilder.addMethod(methodSpec);
+ .addCode(codeBlockBuilder.build());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> methodSpec.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
+ classBuilder.addMethod(methodSpec.build());
}
private String getUniqueVarName() {
@@ -475,12 +519,17 @@ private void add1WithMethod(TypeSpec.Builder classBuilder, RecordClassType compo
var methodName = getWithMethodName(component, metaData.withClassMethodPrefix());
var parameterSpecBuilder = ParameterSpec.builder(component.typeName(), component.name());
addConstructorAnnotations(component, parameterSpecBuilder);
- var methodSpec = MethodSpec.methodBuilder(methodName).addAnnotation(generatedRecordBuilderAnnotation)
+ var methodSpec = MethodSpec.methodBuilder(methodName)
.addJavadoc("Return a new instance of {@code $L} with a new value for {@code $L}\n",
recordClassType.name(), component.name())
.addModifiers(Modifier.PUBLIC, Modifier.DEFAULT).addParameter(parameterSpecBuilder.build())
- .addCode(codeBlockBuilder.build()).returns(recordClassType.typeName()).build();
- classBuilder.addMethod(methodSpec);
+ .addCode(codeBlockBuilder.build()).returns(recordClassType.typeName());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> methodSpec.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
+ classBuilder.addMethod(methodSpec.build());
}
private void add1PrefixedGetterMethod(TypeSpec.Builder classBuilder, RecordClassType component) {
@@ -493,11 +542,16 @@ private void add1PrefixedGetterMethod(TypeSpec.Builder classBuilder, RecordClass
codeBlockBuilder.add("$[return $L()$];", component.name());
var methodName = prefixedName(component, true);
- var methodSpec = MethodSpec.methodBuilder(methodName).addAnnotation(generatedRecordBuilderAnnotation)
+ var methodSpec = MethodSpec.methodBuilder(methodName)
.addJavadoc("Returns the value of {@code $L}\n", component.name())
.addModifiers(Modifier.PUBLIC, Modifier.DEFAULT).addCode(codeBlockBuilder.build())
- .returns(component.typeName()).build();
- classBuilder.addMethod(methodSpec);
+ .returns(component.typeName());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> methodSpec.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
+ classBuilder.addMethod(methodSpec.build());
}
private void addComponentCallsAsArguments(int index, CodeBlock.Builder codeBlockBuilder) {
@@ -520,9 +574,13 @@ private void addDefaultConstructor() {
*
* private MyRecordBuilder() { }
*/
- var constructor = MethodSpec.constructorBuilder().addModifiers(constructorVisibilityModifier)
- .addAnnotation(generatedRecordBuilderAnnotation).build();
- builder.addMethod(constructor);
+ var constructor = MethodSpec.constructorBuilder().addModifiers(constructorVisibilityModifier);
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> constructor.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
+ builder.addMethod(constructor.build());
}
private void addStaticBuilder() {
@@ -535,7 +593,12 @@ private void addStaticBuilder() {
var builder = MethodSpec.methodBuilder(recordClassType.name())
.addJavadoc("Static constructor/builder. Can be used instead of new $L(...)\n", recordClassType.name())
.addTypeVariables(typeVariables).addModifiers(Modifier.PUBLIC, Modifier.STATIC)
- .addAnnotation(generatedRecordBuilderAnnotation).returns(recordClassType.typeName()).addCode(codeBlock);
+ .returns(recordClassType.typeName()).addCode(codeBlock);
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> builder.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
recordComponents.forEach(component -> {
var parameterSpecBuilder = ParameterSpec.builder(component.typeName(), component.name());
addConstructorAnnotations(component, parameterSpecBuilder);
@@ -582,8 +645,12 @@ private void addAllArgsConstructor() {
*
* private MyRecordBuilder(int p1, T p2, ...) { this.p1 = p1; this.p2 = p2; ... }
*/
- var constructorBuilder = MethodSpec.constructorBuilder().addModifiers(constructorVisibilityModifier)
- .addAnnotation(generatedRecordBuilderAnnotation);
+ var constructorBuilder = MethodSpec.constructorBuilder().addModifiers(constructorVisibilityModifier);
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> constructorBuilder.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
recordComponents.forEach(component -> {
var parameterSpecBuilder = ParameterSpec.builder(component.typeName(), component.name());
addConstructorAnnotations(component, parameterSpecBuilder);
@@ -610,9 +677,13 @@ private void addToStringMethod() {
codeBuilder.add("]\"");
var methodSpec = MethodSpec.methodBuilder("toString").addModifiers(Modifier.PUBLIC)
- .addAnnotation(generatedRecordBuilderAnnotation).addAnnotation(Override.class).returns(String.class)
- .addStatement(codeBuilder.build()).build();
- builder.addMethod(methodSpec);
+ .addAnnotation(Override.class).returns(String.class).addStatement(codeBuilder.build());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> methodSpec.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
+ builder.addMethod(methodSpec.build());
}
private void addHashCodeMethod() {
@@ -631,9 +702,13 @@ private void addHashCodeMethod() {
codeBuilder.add(")");
var methodSpec = MethodSpec.methodBuilder("hashCode").addModifiers(Modifier.PUBLIC)
- .addAnnotation(generatedRecordBuilderAnnotation).addAnnotation(Override.class).returns(TypeName.INT)
- .addStatement(codeBuilder.build()).build();
- builder.addMethod(methodSpec);
+ .addAnnotation(Override.class).returns(TypeName.INT).addStatement(codeBuilder.build());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> methodSpec.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
+ builder.addMethod(methodSpec.build());
}
private void addEqualsMethod() {
@@ -662,9 +737,14 @@ private void addEqualsMethod() {
codeBuilder.add(")");
var methodSpec = MethodSpec.methodBuilder("equals").addParameter(Object.class, "o")
- .addModifiers(Modifier.PUBLIC).addAnnotation(generatedRecordBuilderAnnotation)
- .addAnnotation(Override.class).returns(TypeName.BOOLEAN).addStatement(codeBuilder.build()).build();
- builder.addMethod(methodSpec);
+ .addModifiers(Modifier.PUBLIC).addAnnotation(Override.class).returns(TypeName.BOOLEAN)
+ .addStatement(codeBuilder.build());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> methodSpec.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
+ builder.addMethod(methodSpec.build());
}
private void addBuildMethod() {
@@ -679,10 +759,15 @@ private void addBuildMethod() {
}
private MethodSpec.Builder buildMethod() {
- return MethodSpec.methodBuilder(metaData.buildMethodName())
+ MethodSpec.Builder buildMethod = MethodSpec.methodBuilder(metaData.buildMethodName())
.addJavadoc("Return a new record instance with all fields set to the current values in this builder\n")
- .addModifiers(Modifier.PUBLIC).addAnnotation(generatedRecordBuilderAnnotation)
- .returns(recordClassType.typeName());
+ .addModifiers(Modifier.PUBLIC).returns(recordClassType.typeName());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> buildMethod.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
+ return buildMethod;
}
private CodeBlock buildCodeBlock() {
@@ -741,26 +826,39 @@ private void addFromWithClass() {
*/
var fromWithClassBuilder = TypeSpec.classBuilder(metaData.fromWithClassName())
- .addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL)
- .addAnnotation(generatedRecordBuilderAnnotation).addTypeVariables(typeVariables)
+ .addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL).addTypeVariables(typeVariables)
.addSuperinterface(buildWithTypeName());
if (metaData.addClassRetainedGenerated()) {
fromWithClassBuilder.addAnnotation(recordBuilderGeneratedAnnotation);
}
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> fromWithClassBuilder.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
fromWithClassBuilder.addField(recordClassType.typeName(), "from", Modifier.PRIVATE, Modifier.FINAL);
- MethodSpec constructorSpec = MethodSpec.constructorBuilder().addParameter(recordClassType.typeName(), "from")
- .addStatement("this.from = from").addModifiers(Modifier.PRIVATE)
- .addAnnotation(generatedRecordBuilderAnnotation).build();
- fromWithClassBuilder.addMethod(constructorSpec);
+ MethodSpec.Builder constructorSpec = MethodSpec.constructorBuilder()
+ .addParameter(recordClassType.typeName(), "from").addStatement("this.from = from")
+ .addModifiers(Modifier.PRIVATE);
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> constructorSpec.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
+ fromWithClassBuilder.addMethod(constructorSpec.build());
IntStream.range(0, recordComponents.size()).forEach(index -> {
var component = recordComponents.get(index);
- MethodSpec methodSpec = MethodSpec.methodBuilder(component.name()).returns(component.typeName())
+ MethodSpec.Builder methodSpec = MethodSpec.methodBuilder(component.name()).returns(component.typeName())
.addAnnotation(Override.class).addModifiers(Modifier.PUBLIC)
- .addStatement("return from.$L()", component.name()).addAnnotation(generatedRecordBuilderAnnotation)
- .build();
- fromWithClassBuilder.addMethod(methodSpec);
+ .addStatement("return from.$L()", component.name());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> methodSpec.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
+ fromWithClassBuilder.addMethod(methodSpec.build());
});
this.builder.addType(fromWithClassBuilder.build());
}
@@ -776,12 +874,16 @@ private void addStaticFromWithMethod() {
var methodSpec = MethodSpec.methodBuilder(metaData.fromMethodName())
.addJavadoc("Return a \"with\"er for an existing record instance\n")
- .addModifiers(Modifier.PUBLIC, Modifier.STATIC).addAnnotation(generatedRecordBuilderAnnotation)
- .addTypeVariables(typeVariables).addParameter(recordClassType.typeName(), metaData.fromMethodName())
- .returns(buildWithTypeName()).addStatement("return new $L$L($L)", metaData.fromWithClassName(),
- typeVariables.isEmpty() ? "" : "<>", metaData.fromMethodName())
- .build();
- builder.addMethod(methodSpec);
+ .addModifiers(Modifier.PUBLIC, Modifier.STATIC).addTypeVariables(typeVariables)
+ .addParameter(recordClassType.typeName(), metaData.fromMethodName()).returns(buildWithTypeName())
+ .addStatement("return new $L$L($L)", metaData.fromWithClassName(), typeVariables.isEmpty() ? "" : "<>",
+ metaData.fromMethodName());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> methodSpec.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
+ builder.addMethod(methodSpec.build());
}
private void addStaticCopyBuilderMethod() {
@@ -803,10 +905,15 @@ private void addStaticCopyBuilderMethod() {
var methodSpec = MethodSpec.methodBuilder(metaData.copyMethodName())
.addJavadoc(
"Return a new builder with all fields set to the values taken from the given record instance\n")
- .addModifiers(Modifier.PUBLIC, Modifier.STATIC).addAnnotation(generatedRecordBuilderAnnotation)
- .addTypeVariables(typeVariables).addParameter(recordClassType.typeName(), "from")
- .returns(builderClassType.typeName()).addStatement(codeBuilder.build()).build();
- builder.addMethod(methodSpec);
+ .addModifiers(Modifier.PUBLIC, Modifier.STATIC).addTypeVariables(typeVariables)
+ .addParameter(recordClassType.typeName(), "from").returns(builderClassType.typeName())
+ .addStatement(codeBuilder.build());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> methodSpec.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
+ builder.addMethod(methodSpec.build());
}
private void addStaticDefaultBuilderMethod() {
@@ -817,10 +924,14 @@ private void addStaticDefaultBuilderMethod() {
*/
var methodSpec = MethodSpec.methodBuilder(metaData.builderMethodName())
.addJavadoc("Return a new builder with all fields set to default Java values\n")
- .addModifiers(Modifier.PUBLIC, Modifier.STATIC).addAnnotation(generatedRecordBuilderAnnotation)
- .addTypeVariables(typeVariables).returns(builderClassType.typeName())
- .addStatement("return new $T()", builderClassType.typeName()).build();
- builder.addMethod(methodSpec);
+ .addModifiers(Modifier.PUBLIC, Modifier.STATIC).addTypeVariables(typeVariables)
+ .returns(builderClassType.typeName()).addStatement("return new $T()", builderClassType.typeName());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> methodSpec.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
+ builder.addMethod(methodSpec.build());
}
private void addStaticStagedBuilderMethod(String builderMethodName) {
@@ -848,9 +959,14 @@ private void addStaticStagedBuilderMethod(String builderMethodName) {
var methodSpec = MethodSpec.methodBuilder(builderMethodName)
.addJavadoc("Return the first stage of a staged builder\n")
- .addModifiers(Modifier.PUBLIC, Modifier.STATIC).addAnnotation(generatedRecordBuilderAnnotation)
- .addTypeVariables(typeVariables).returns(returnType.typeName()).addCode(codeBlock.build()).build();
- builder.addMethod(methodSpec);
+ .addModifiers(Modifier.PUBLIC, Modifier.STATIC).addTypeVariables(typeVariables)
+ .returns(returnType.typeName()).addCode(codeBlock.build());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> methodSpec.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
+ builder.addMethod(methodSpec.build());
}
private void addStaticComponentsMethod() {
@@ -875,9 +991,13 @@ private void addStaticComponentsMethod() {
var methodSpec = MethodSpec.methodBuilder(metaData.componentsMethodName()).addJavadoc(
"Return a stream of the record components as map entries keyed with the component name and the value as the component value\n")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC).addParameter(recordClassType.typeName(), "record")
- .addAnnotation(generatedRecordBuilderAnnotation).addTypeVariables(typeVariables).returns(mapEntryType)
- .addStatement(codeBuilder.build()).build();
- builder.addMethod(methodSpec);
+ .addTypeVariables(typeVariables).returns(mapEntryType).addStatement(codeBuilder.build());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> methodSpec.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
+ builder.addMethod(methodSpec.build());
}
private void add1Field(ClassType component) {
@@ -911,8 +1031,12 @@ private void addNestedGetterMethod(TypeSpec.Builder classBuilder, RecordClassTyp
var methodSpecBuilder = MethodSpec.methodBuilder(methodName)
.addJavadoc("Return the current value for the {@code $L} record component in the builder\n",
component.name())
- .addModifiers(Modifier.ABSTRACT, Modifier.PUBLIC).addAnnotation(generatedRecordBuilderAnnotation)
- .returns(component.typeName());
+ .addModifiers(Modifier.ABSTRACT, Modifier.PUBLIC).returns(component.typeName());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> methodSpecBuilder.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
addAccessorAnnotations(component, methodSpecBuilder, this::filterOutValid);
classBuilder.addMethod(methodSpecBuilder.build());
}
@@ -977,8 +1101,12 @@ private void add1MapBuilder(SingleItemsMetaData meta, RecordClassType component)
var methodSpecBuilder = MethodSpec
.methodBuilder(metaData.singleItemBuilderPrefix() + capitalize(component.name()))
.addJavadoc("Add to the internally allocated {@code HashMap} for {@code $L}\n", component.name())
- .addModifiers(Modifier.PUBLIC).addAnnotation(generatedRecordBuilderAnnotation)
- .returns(builderClassType.typeName());
+ .addModifiers(Modifier.PUBLIC).returns(builderClassType.typeName());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> methodSpecBuilder.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
if (i == 0) {
methodSpecBuilder.addParameter(meta.typeArguments().get(0), "key");
methodSpecBuilder.addParameter(meta.typeArguments().get(1), "value");
@@ -1038,9 +1166,13 @@ private void add1ListBuilder(SingleItemsMetaData meta, RecordClassType component
.methodBuilder(metaData.singleItemBuilderPrefix() + capitalize(component.name()))
.addJavadoc("Add to the internally allocated {@code $L} for {@code $L}\n",
meta.singleItemCollectionClass().getSimpleName(), component.name())
- .addModifiers(Modifier.PUBLIC).addAnnotation(generatedRecordBuilderAnnotation)
- .returns(builderClassType.typeName()).addParameter(parameter, "i")
+ .addModifiers(Modifier.PUBLIC).returns(builderClassType.typeName()).addParameter(parameter, "i")
.addCode(codeBlockBuilder.build());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> methodSpecBuilder.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
builder.addMethod(methodSpecBuilder.build());
}
}
@@ -1054,9 +1186,13 @@ private void add1GetterMethod(RecordClassType component) {
var methodSpecBuilder = MethodSpec.methodBuilder(prefixedName(component, true))
.addJavadoc("Return the current value for the {@code $L} record component in the builder\n",
component.name())
- .addModifiers(Modifier.PUBLIC).addAnnotation(generatedRecordBuilderAnnotation)
- .returns(component.typeName()).addCode(checkReturnShim(component));
+ .addModifiers(Modifier.PUBLIC).returns(component.typeName()).addCode(checkReturnShim(component));
addAccessorAnnotations(component, methodSpecBuilder, __ -> true);
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> methodSpecBuilder.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
builder.addMethod(methodSpecBuilder.build());
}
@@ -1079,7 +1215,12 @@ private void add1SetterMethod(RecordClassType component, int componentIndex) {
* public MyRecordBuilder p(T p) { this.p = p; return this; }
*/
var methodSpec = MethodSpec.methodBuilder(prefixedName(component, false)).addModifiers(Modifier.PUBLIC)
- .addAnnotation(generatedRecordBuilderAnnotation).returns(builderClassType.typeName());
+ .returns(builderClassType.typeName());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> methodSpec.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
if (metaData.onceOnlyAssignment()) {
var onceOnlyCheck = CodeBlock.builder()
@@ -1124,8 +1265,12 @@ private void add1ConcreteOptionalSetterMethod(RecordClassType component) {
}
var type = optionalType.get();
var methodSpec = MethodSpec.methodBuilder(prefixedName(component, false)).addModifiers(Modifier.PUBLIC)
- .addAnnotation(generatedRecordBuilderAnnotation).returns(builderClassType.typeName());
-
+ .returns(builderClassType.typeName());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> methodSpec.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
var parameterSpecBuilder = ParameterSpec.builder(type.valueType(), component.name());
methodSpec.addJavadoc("Set a new value for the {@code $L} record component in the builder\n", component.name())
.addStatement(getOptionalStatement(type), component.name(), type.typeName(), component.name());
@@ -1160,8 +1305,13 @@ private MethodSpec buildFunctionalHandler(String className, String methodName, b
var localTypeVariables = isMap ? typeVariablesWithReturn() : typeVariables;
var typeName = localTypeVariables.isEmpty() ? ClassName.get("", className)
: ParameterizedTypeName.get(ClassName.get("", className), localTypeVariables.toArray(TypeName[]::new));
- var methodBuilder = MethodSpec.methodBuilder(methodName).addAnnotation(generatedRecordBuilderAnnotation)
- .addModifiers(Modifier.PUBLIC, Modifier.DEFAULT).addParameter(typeName, "proc");
+ var methodBuilder = MethodSpec.methodBuilder(methodName).addModifiers(Modifier.PUBLIC, Modifier.DEFAULT)
+ .addParameter(typeName, "proc");
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> methodBuilder.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
var codeBlockBuilder = CodeBlock.builder();
if (isMap) {
methodBuilder.addJavadoc("Map record components into a new object");
@@ -1194,9 +1344,15 @@ private TypeSpec buildFunctionalInterface(String className, boolean isMap) {
if (isMap) {
methodBuilder.returns(rType);
}
- return TypeSpec.interfaceBuilder(className).addAnnotation(generatedRecordBuilderAnnotation)
- .addAnnotation(FunctionalInterface.class).addModifiers(Modifier.PUBLIC, Modifier.STATIC)
- .addTypeVariables(localTypeVariables).addMethod(methodBuilder.build()).build();
+ var typeSpecBuilder = TypeSpec.interfaceBuilder(className).addAnnotation(FunctionalInterface.class)
+ .addModifiers(Modifier.PUBLIC, Modifier.STATIC).addTypeVariables(localTypeVariables)
+ .addMethod(methodBuilder.build());
+ switch (metaData.addGeneratedAnnotation()) {
+ case ALWAYS -> typeSpecBuilder.addAnnotation(generatedRecordBuilderAnnotation);
+ case NEVER -> {
+ /* no-op */ }
+ }
+ return typeSpecBuilder.build();
}
private String prefixedName(RecordClassType component, boolean isGetter) {
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 d71697ab..2a88b48a 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
@@ -132,9 +132,8 @@ private void addVisibility(TypeSpec.Builder builder, boolean builderIsInRecordPa
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();
+ .addAnnotation(Override.class).returns(ClassName.get(component.element.getReturnType()))
+ .addModifiers(Modifier.PUBLIC).addCode("return $L();", component.alternateName.get()).build();
builder.addMethod(method);
});
}
diff --git a/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/RecordBuilderOptions.java b/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/RecordBuilderOptions.java
index 0fa34607..ec0057d9 100644
--- a/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/RecordBuilderOptions.java
+++ b/record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/RecordBuilderOptions.java
@@ -55,6 +55,9 @@ static RecordBuilder.Options build(Map options) {
if (defaultValue instanceof RecordBuilder.ConcreteSettersForOptionalMode) {
return RecordBuilder.ConcreteSettersForOptionalMode.valueOf(option);
}
+ if (defaultValue instanceof RecordBuilder.GeneratedAnnotation) {
+ return RecordBuilder.GeneratedAnnotation.valueOf(option);
+ }
throw new IllegalArgumentException("Unhandled option type: " + defaultValue.getClass());
}
return defaultValue;
diff --git a/record-builder-test/src/main/java/io/soabase/recordbuilder/test/NoGeneratedAnnotation.java b/record-builder-test/src/main/java/io/soabase/recordbuilder/test/NoGeneratedAnnotation.java
new file mode 100644
index 00000000..f974eb92
--- /dev/null
+++ b/record-builder-test/src/main/java/io/soabase/recordbuilder/test/NoGeneratedAnnotation.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2019 The original author or authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.soabase.recordbuilder.test;
+
+import io.soabase.recordbuilder.core.RecordBuilder;
+
+@RecordBuilder
+@RecordBuilder.Options(addGeneratedAnnotation = RecordBuilder.GeneratedAnnotation.NEVER)
+public record NoGeneratedAnnotation(String empty) {
+}
diff --git a/record-builder-test/src/test/java/io/soabase/recordbuilder/test/TestNoGeneratedAnnotation.java b/record-builder-test/src/test/java/io/soabase/recordbuilder/test/TestNoGeneratedAnnotation.java
new file mode 100644
index 00000000..d8774553
--- /dev/null
+++ b/record-builder-test/src/test/java/io/soabase/recordbuilder/test/TestNoGeneratedAnnotation.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019 The original author or authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package io.soabase.recordbuilder.test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.junit.jupiter.api.Test;
+
+class TestNoGeneratedAnnotation {
+
+ @Test
+ void assertNoGeneratedAnnotationPresent() throws IOException {
+ // given
+ Class builderClass = NoGeneratedAnnotationBuilder.class;
+ Path path = Paths.get("target/generated-sources/annotations",
+ builderClass.getPackageName().replace(".", File.separator), builderClass.getSimpleName() + ".java");
+
+ // when
+ String source = Files.readString(path);
+
+ // then expect
+ assertThat(source).as("generated source file should not contain @Generated annotation nor import.").isNotEmpty()
+ .doesNotContain("@Generated").doesNotContain("import javax.annotation.processing.Generated");
+ }
+}