Skip to content

Commit 7c00376

Browse files
committed
implement parameterized builder
1 parent c9811e3 commit 7c00376

File tree

8 files changed

+283
-48
lines changed

8 files changed

+283
-48
lines changed

options.md

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,20 @@ The names used for generated methods, classes, etc. can be changed via the follo
5454

5555
## Miscellaneous
5656

57-
| option | details |
58-
|----------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------|
59-
| `@RecordBuilder.Options(inheritComponentAnnotations = true/false)` | If true, any annotations (if applicable) on record components are copied to the builder methods. The default is `true`. |
60-
| `@RecordBuilder.Options(publicBuilderConstructors = true/false)` | Makes the generated builder's constructors public. The default is `false`. |
61-
| `@RecordBuilder.Options(builderClassModifiers = {}})` | Any additional `javax.lang.model.element.Modifier` you wish to apply to the builder. |
62-
| `@RecordBuilder.Options(beanClassName = "Foo")` | If set, the Builder will contain an internal interface with this name. |
63-
| `@RecordBuilder.Options(addClassRetainedGenerated = true/false)` | If true, generated classes are annotated with `RecordBuilderGenerated`. The default is `false`. |
64-
| `@RecordBuilder.Options(addStaticBuilder = true/false)` | If true, a functional-style builder is added so that record instances can be instantiated without `new()`. The default is `true`. |
65-
| `@RecordBuilder.Options(inheritComponentAnnotations = true/false)` | If true, any annotations (if applicable) on record components are copied to the builder methods. The default is `true`. |
66-
| `@RecordBuilder.Options(addConcreteSettersForOptional = true/false)` | Add non-optional setter methods for optional record components. The default is `false`. |
67-
| `@RecordBuilder.Options(useValidationApi = true/false)` | Pass built records through the Java Validation API if it's available in the classpath. The default is `false`. |
68-
| `@RecordBuilder.Options(builderMode = BuilderMode.XXX)` | Whether to add standard builder, staged builder or both. The default is `BuilderMode.STANDARD`. |
69-
| `@RecordBuilder.Options(onceOnlyAssignment = true/false)` | If true, attributes can be set/assigned only 1 time. Attempts to reassign/reset attributes will throw `java.lang.IllegalStateException`. The default is `false`. |
57+
| option | details |
58+
|----------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
59+
| `@RecordBuilder.Options(inheritComponentAnnotations = true/false)` | If true, any annotations (if applicable) on record components are copied to the builder methods. The default is `true`. |
60+
| `@RecordBuilder.Options(publicBuilderConstructors = true/false)` | Makes the generated builder's constructors public. The default is `false`. |
61+
| `@RecordBuilder.Options(parameterizedBuilder = true/false)` | Parameterizes the generated builder on the builder type itself. Builder setters will return the type parameter. This is useful when extending the builder. The default is `false`. | |
62+
| `@RecordBuilder.Options(builderClassModifiers = {}})` | Any additional `javax.lang.model.element.Modifier` you wish to apply to the builder. |
63+
| `@RecordBuilder.Options(beanClassName = "Foo")` | If set, the Builder will contain an internal interface with this name. |
64+
| `@RecordBuilder.Options(addClassRetainedGenerated = true/false)` | If true, generated classes are annotated with `RecordBuilderGenerated`. The default is `false`. |
65+
| `@RecordBuilder.Options(addStaticBuilder = true/false)` | If true, a functional-style builder is added so that record instances can be instantiated without `new()`. The default is `true`. |
66+
| `@RecordBuilder.Options(inheritComponentAnnotations = true/false)` | If true, any annotations (if applicable) on record components are copied to the builder methods. The default is `true`. |
67+
| `@RecordBuilder.Options(addConcreteSettersForOptional = true/false)` | Add non-optional setter methods for optional record components. The default is `false`. |
68+
| `@RecordBuilder.Options(useValidationApi = true/false)` | Pass built records through the Java Validation API if it's available in the classpath. The default is `false`. |
69+
| `@RecordBuilder.Options(builderMode = BuilderMode.XXX)` | Whether to add standard builder, staged builder or both. The default is `BuilderMode.STANDARD`. |
70+
| `@RecordBuilder.Options(onceOnlyAssignment = true/false)` | If true, attributes can be set/assigned only 1 time. Attempts to reassign/reset attributes will throw `java.lang.IllegalStateException`. The default is `false`. |
7071

7172
### Staged Builders
7273

record-builder-core/src/main/java/io/soabase/recordbuilder/core/RecordBuilder.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,12 @@
307307
*/
308308
boolean publicBuilderConstructors() default false;
309309

310+
/**
311+
* Parameterizes the generated builder on the builder type itself. Builder setters will return the type
312+
* parameter. This is useful when extending the builder.
313+
*/
314+
boolean parameterizedBuilder() default false;
315+
310316
/**
311317
* Whether to add standard builder, staged builder or both
312318
*/

record-builder-processor/src/main/java/io/soabase/recordbuilder/processor/ElementUtils.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ public static ClassType getClassType(ClassName builderClassName,
108108
if (typeParameters.isEmpty()) {
109109
return new ClassType(builderClassName, builderClassName.simpleName());
110110
}
111-
TypeName[] typeNames = typeParameters.stream().map(TypeVariableName::get).toArray(TypeName[]::new);
111+
TypeName[] typeNames = toTypeVariableNames(typeParameters).toArray(TypeName[]::new);
112112
return new ClassType(ParameterizedTypeName.get(builderClassName, typeNames), builderClassName.simpleName());
113113
}
114114

@@ -121,6 +121,10 @@ public static ClassType getClassTypeFromNames(ClassName builderClassName,
121121
return new ClassType(ParameterizedTypeName.get(builderClassName, typeNames), builderClassName.simpleName());
122122
}
123123

124+
public static List<TypeVariableName> toTypeVariableNames(List<? extends TypeParameterElement> typeParameters) {
125+
return typeParameters.stream().map(TypeVariableName::get).toList();
126+
}
127+
124128
public static RecordClassType getRecordClassType(ProcessingEnvironment processingEnv,
125129
RecordComponentElement recordComponent, List<? extends AnnotationMirror> accessorAnnotations,
126130
List<? extends AnnotationMirror> canonicalConstructorAnnotations) {

0 commit comments

Comments
 (0)