Skip to content

Commit

Permalink
Propagate the @nullable annotation to the setters of the builder and …
Browse files Browse the repository at this point in the history
…the type-safe interfaces.
  • Loading branch information
skinny85 committed Jan 17, 2024
1 parent 0042473 commit 9f28b64
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 6 deletions.
28 changes: 25 additions & 3 deletions src/main/java/org/jilt/internal/AbstractBuilderGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.squareup.javapoet.FieldSpec;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
Expand Down Expand Up @@ -92,7 +93,7 @@ public final void generateBuilderClass() throws Exception {
.methodBuilder(builderSetterMethodName(attribute))
.addModifiers(Modifier.PUBLIC)
.returns(returnTypeForSetterFor(attribute))
.addParameter(fieldType, fieldName)
.addParameter(this.setterParameterInBuilder(attribute))
.addStatement("this.$1L = $1L", fieldName)
.addStatement("return this")
.build());
Expand Down Expand Up @@ -122,6 +123,20 @@ public final void generateBuilderClass() throws Exception {
javaFile.writeTo(filer);
}

private ParameterSpec setterParameterInBuilder(VariableElement attribute) {
return this.setterParameter(attribute, TypeName.get(attribute.asType()));
}

protected final ParameterSpec setterParameter(VariableElement attribute, TypeName parameterType) {
ParameterSpec.Builder ret = ParameterSpec.builder(parameterType,
this.attributeSimpleName(attribute));
AnnotationMirror nullableAnnotation = this.firstAnnotationCalledNullable(attribute);
if (nullableAnnotation!= null) {
ret.addAnnotation(AnnotationSpec.get(nullableAnnotation));
}
return ret.build();
}

private List<String> attributeNames() {
List<String> ret = new ArrayList<String>(attributes.size());
for (VariableElement attribute : attributes) {
Expand Down Expand Up @@ -156,12 +171,19 @@ private boolean determineIfAttributeIsOptional(VariableElement attribute) {
if (attribute.getAnnotation(Opt.class) != null) {
return true;
}
if (this.firstAnnotationCalledNullable(attribute) != null) {
return true;
}
return false;
}

private AnnotationMirror firstAnnotationCalledNullable(VariableElement attribute) {
for (AnnotationMirror annotation : attribute.getAnnotationMirrors()) {
if (annotationIsCalledNullable(annotation)) {
return true;
return annotation;
}
}
return false;
return null;
}

private static boolean annotationIsCalledNullable(AnnotationMirror annotation) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
Expand Down Expand Up @@ -65,6 +66,10 @@ protected final String interfaceNameForAttribute(VariableElement attribute) {
return interfaceNameFromBaseName(Utils.capitalize(attributeSimpleName(attribute)));
}

protected final ParameterSpec setterParameterInInterface(VariableElement attribute) {
return this.setterParameter(attribute, this.attributeType(attribute));
}

protected final TypeName attributeType(VariableElement attribute) {
TypeName ret = TypeName.get(attribute.asType());
if (ret instanceof TypeVariableName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ protected void generateClassesNeededByBuilder() throws Exception {
.methodBuilder(builderSetterMethodName(currentAttribute))
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.returns(this.returnTypeForSetterFor(currentAttribute, !attributeIsOptional))
.addParameter(this.attributeType(currentAttribute), this.attributeSimpleName(currentAttribute))
.addParameter(this.setterParameterInInterface(currentAttribute))
.build();

if (attributeIsOptional) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ protected void generateClassesNeededByBuilder() throws Exception {
.methodBuilder(builderSetterMethodName(currentAttribute))
.addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
.returns(this.returnTypeForSetterFor(currentAttribute, true))
.addParameter(this.attributeType(currentAttribute), this.attributeSimpleName(currentAttribute))
.addParameter(this.setterParameterInInterface(currentAttribute))
.build());

if (nextAttribute == null && isOptional(currentAttribute)) {
Expand Down
21 changes: 20 additions & 1 deletion src/test/java/org/jilt/test/FullNameTest.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package org.jilt.test;

import org.jilt.test.data.nullable.FullName;
import org.jilt.test.data.nullable.FullNameBuilder;
import org.jilt.test.data.nullable.FullNameBuilders;
import org.junit.Test;

import javax.annotation.Nullable;
import java.lang.reflect.Method;

import static org.assertj.core.api.Assertions.assertThat;
import static org.jilt.test.data.nullable.FullNameBuilder.fullName;

public class FullNameTest {
@Test
public void nullable_attribute() throws Exception {
public void nullable_annotation_makes_attribute_optional() {
FullName value = fullName()
.firstName("First")
.lastName(null)
Expand All @@ -19,4 +24,18 @@ public void nullable_attribute() throws Exception {
assertThat(value.middleName).isNull();
assertThat(value.lastName).isNull();
}

@Test
public void setter_in_builder_propagates_nullable_annotation() throws Exception {
Method middleNameSetter = FullNameBuilder.class.getMethod("middleName", String.class);

assertThat(middleNameSetter.getParameters()[0].getAnnotation(Nullable.class)).isNotNull();
}

@Test
public void setter_in_type_safe_interface_propagates_nullable_annotation() throws Exception {
Method middleNameSetter = FullNameBuilders.Optionals.class.getMethod("middleName", String.class);

assertThat(middleNameSetter.getParameters()[0].getAnnotation(Nullable.class)).isNotNull();
}
}

0 comments on commit 9f28b64

Please sign in to comment.