Skip to content

Commit f070cea

Browse files
committed
Fix non-deterministic annotation generation by using declaredAnnotationValues
The xprocessing library's XAnnotation.annotationValues property exhibits non-deterministic behavior in KSP, sometimes returning annotation values with defaults and sometimes returning an empty list. This caused tests to fail randomly depending on which values were returned during processing. Switched to using declaredAnnotationValues instead, which consistently returns only explicitly declared values (excluding defaults). This approach mirrors Room's implementation in JavaPoetExt.kt. This fix eliminates the flakiness where @deprecated would sometimes be generated as @deprecated and sometimes as @deprecated(since = "", forRemoval = false).
1 parent 550955a commit f070cea

File tree

11 files changed

+70
-114
lines changed

11 files changed

+70
-114
lines changed

epoxy-processor/src/main/java/com/airbnb/epoxy/processor/XProcessingUtils.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,14 @@ fun XAnnotation.toAnnotationSpec(memoizer: Memoizer): AnnotationSpec {
174174
return addMember(memberName, "\$L", value)
175175
}
176176
return AnnotationSpec.builder(ClassName.get(packageName, name)).apply {
177-
annotationValues.forEach { annotationValue ->
177+
// Use declaredAnnotationValues instead of annotationValues to exclude default values.
178+
// This ensures consistent behavior across KSP runs, as annotationValues has been observed
179+
// to non-deterministically return different results in KSP (sometimes including defaults,
180+
// sometimes not).
181+
//
182+
// This approach mirrors Room's implementation in JavaPoetExt.kt:
183+
// @see androidx.room.compiler.processing.toAnnotationSpec
184+
declaredAnnotationValues.forEach { annotationValue ->
178185
addMemberForValue(annotationValue.name, annotationValue.value, memoizer)
179186
}
180187
}.build()

epoxy-processortest/src/test/resources/ModelWithAnnotation_.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,7 @@
1212
/**
1313
* Generated file. Do not modify!
1414
*/
15-
@Deprecated(
16-
since = "",
17-
forRemoval = false
18-
)
15+
@Deprecated
1916
public class ModelWithAnnotation_ extends ModelWithAnnotation implements GeneratedModel<Object>, ModelWithAnnotationBuilder {
2017
private OnModelBoundListener<ModelWithAnnotation_, Object> onModelBoundListener_epoxyGeneratedModel;
2118

epoxy-processortest/src/test/resources/ViewProcessorTest/annotationsAreCopied/SourceViewModel_.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@
1414
/**
1515
* Generated file. Do not modify!
1616
*/
17-
@Deprecated(
18-
since = "",
19-
forRemoval = false
20-
)
17+
@Deprecated
2118
public class SourceViewModel_ extends EpoxyModel<SourceView> implements GeneratedModel<SourceView>, SourceViewModelBuilder {
2219
private OnModelBoundListener<SourceViewModel_, SourceView> onModelBoundListener_epoxyGeneratedModel;
2320

epoxy-processortest/src/test/resources/ViewProcessorTest/annotationsAreCopied/ksp/SourceViewModel_.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,12 @@
1010
import java.lang.String;
1111
import java.lang.UnsupportedOperationException;
1212
import kotlin.Deprecated;
13-
import kotlin.DeprecationLevel;
14-
import kotlin.ReplaceWith;
1513

1614
/**
1715
* Generated file. Do not modify!
1816
*/
1917
@Deprecated(
20-
message = "some message",
21-
replaceWith = @ReplaceWith(expression = "", imports = {}),
22-
level = DeprecationLevel.WARNING
18+
message = "some message"
2319
)
2420
public class SourceViewModel_ extends EpoxyModel<SourceView> implements GeneratedModel<SourceView>, SourceViewModelBuilder {
2521
private OnModelBoundListener<SourceViewModel_, SourceView> onModelBoundListener_epoxyGeneratedModel;

epoxy-processortest/src/test/resources/ViewProcessorTest/inheritingAttributesWorksCorrectly/SourceViewModelBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ SourceViewModelBuilder onVisibilityStateChanged(
1818
SourceViewModelBuilder onVisibilityChanged(
1919
OnModelVisibilityChangedListener<SourceViewModel_, SourceView> listener);
2020

21-
SourceViewModelBuilder sectionId(@Nullable("") String sectionId);
21+
SourceViewModelBuilder sectionId(@Nullable String sectionId);
2222

2323
SourceViewModelBuilder baseViewProp(int baseViewProp);
2424

epoxy-processortest/src/test/resources/ViewProcessorTest/inheritingAttributesWorksCorrectly/SourceViewModel_.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class SourceViewModel_ extends AirEpoxyModel<SourceView> implements Gener
2323

2424
private OnModelVisibilityChangedListener<SourceViewModel_, SourceView> onModelVisibilityChangedListener_epoxyGeneratedModel;
2525

26-
@Nullable("")
26+
@Nullable
2727
private String sectionId_String = (String) null;
2828

2929
private int baseViewProp_Int = 0;
@@ -180,13 +180,13 @@ public SourceViewModel_ onVisibilityChanged(
180180
*
181181
* @see SourceView#setSectionId(String)
182182
*/
183-
public SourceViewModel_ sectionId(@Nullable("") String sectionId) {
183+
public SourceViewModel_ sectionId(@Nullable String sectionId) {
184184
onMutation();
185185
this.sectionId_String = sectionId;
186186
return this;
187187
}
188188

189-
@Nullable("")
189+
@Nullable
190190
public String sectionId() {
191191
return sectionId_String;
192192
}

epoxy-processortest/src/test/resources/ViewProcessorTest/inheritingAttributesWorksCorrectlyJavaClassPath/SourceViewModelBuilder.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ SourceViewModelBuilder onVisibilityStateChanged(
1717
SourceViewModelBuilder onVisibilityChanged(
1818
OnModelVisibilityChangedListener<SourceViewModel_, SourceView> listener);
1919

20-
SourceViewModelBuilder sectionId(@Nullable("") String sectionId);
20+
SourceViewModelBuilder sectionId(@Nullable String sectionId);
2121

2222
SourceViewModelBuilder processorTest2ValueProtected(int processorTest2ValueProtected);
2323

epoxy-processortest/src/test/resources/ViewProcessorTest/inheritingAttributesWorksCorrectlyJavaClassPath/SourceViewModel_.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class SourceViewModel_ extends ProcessorTest2Model<SourceView> implements
2323

2424
private OnModelVisibilityChangedListener<SourceViewModel_, SourceView> onModelVisibilityChangedListener_epoxyGeneratedModel;
2525

26-
@Nullable("")
26+
@Nullable
2727
private String sectionId_String = (String) null;
2828

2929
public SourceViewModel_() {
@@ -166,13 +166,13 @@ public SourceViewModel_ onVisibilityChanged(
166166
*
167167
* @see SourceView#setSectionId(String)
168168
*/
169-
public SourceViewModel_ sectionId(@Nullable("") String sectionId) {
169+
public SourceViewModel_ sectionId(@Nullable String sectionId) {
170170
onMutation();
171171
this.sectionId_String = sectionId;
172172
return this;
173173
}
174174

175-
@Nullable("")
175+
@Nullable
176176
public String sectionId() {
177177
return sectionId_String;
178178
}

epoxy-processortest/src/test/resources/ViewProcessorTest/testManyTypes/TestManyTypesViewModelBuilder.java

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import androidx.annotation.StringRes;
88
import java.lang.Boolean;
99
import java.lang.CharSequence;
10-
import java.lang.Exception;
1110
import java.lang.Integer;
1211
import java.lang.Number;
1312
import java.lang.Object;
@@ -33,25 +32,23 @@ TestManyTypesViewModelBuilder onVisibilityChanged(
3332

3433
TestManyTypesViewModelBuilder myProperty(int myProperty);
3534

36-
TestManyTypesViewModelBuilder myNullableProperty(@Nullable("") Integer myNullableProperty);
35+
TestManyTypesViewModelBuilder myNullableProperty(@Nullable Integer myNullableProperty);
3736

3837
TestManyTypesViewModelBuilder delegatedProperty(int delegatedProperty);
3938

4039
TestManyTypesViewModelBuilder enabled(boolean enabled);
4140

42-
TestManyTypesViewModelBuilder stringValue(
43-
@NotNull(value = "", exception = Exception.class) String stringValue);
41+
TestManyTypesViewModelBuilder stringValue(@NotNull String stringValue);
4442

4543
TestManyTypesViewModelBuilder functionType(
46-
@NotNull(value = "", exception = Exception.class) Function2<? super String, ? super String, Integer> functionType);
44+
@NotNull Function2<? super String, ? super String, Integer> functionType);
4745

48-
TestManyTypesViewModelBuilder listOfDataClass(
49-
@NotNull(value = "", exception = Exception.class) List<SomeDataClass> listOfDataClass);
46+
TestManyTypesViewModelBuilder listOfDataClass(@NotNull List<SomeDataClass> listOfDataClass);
5047

5148
TestManyTypesViewModelBuilder listOfEnumClass(
52-
@NotNull(value = "", exception = Exception.class) List<? extends SomeEnumClass> listOfEnumClass);
49+
@NotNull List<? extends SomeEnumClass> listOfEnumClass);
5350

54-
TestManyTypesViewModelBuilder nullableStringValue(@Nullable("") String nullableStringValue);
51+
TestManyTypesViewModelBuilder nullableStringValue(@Nullable String nullableStringValue);
5552

5653
TestManyTypesViewModelBuilder intValue(int intValue);
5754

@@ -72,22 +69,21 @@ TestManyTypesViewModelBuilder intWithMultipleAnnotations(
7269

7370
TestManyTypesViewModelBuilder boolValue(boolean boolValue);
7471

75-
TestManyTypesViewModelBuilder models(
76-
@NotNull(value = "", exception = Exception.class) List<? extends EpoxyModel<?>> models);
72+
TestManyTypesViewModelBuilder models(@NotNull List<? extends EpoxyModel<?>> models);
7773

78-
TestManyTypesViewModelBuilder booleanValue(@Nullable("") Boolean booleanValue);
74+
TestManyTypesViewModelBuilder booleanValue(@Nullable Boolean booleanValue);
7975

80-
TestManyTypesViewModelBuilder arrayValue(@Nullable("") String[] arrayValue);
76+
TestManyTypesViewModelBuilder arrayValue(@Nullable String[] arrayValue);
8177

82-
TestManyTypesViewModelBuilder listValue(@Nullable("") List<String> listValue);
78+
TestManyTypesViewModelBuilder listValue(@Nullable List<String> listValue);
8379

8480
TestManyTypesViewModelBuilder clickListener(
85-
@Nullable("") final OnModelClickListener<TestManyTypesViewModel_, TestManyTypesView> clickListener);
81+
@Nullable final OnModelClickListener<TestManyTypesViewModel_, TestManyTypesView> clickListener);
8682

87-
TestManyTypesViewModelBuilder clickListener(@Nullable("") View.OnClickListener clickListener);
83+
TestManyTypesViewModelBuilder clickListener(@Nullable View.OnClickListener clickListener);
8884

8985
TestManyTypesViewModelBuilder customClickListener(
90-
@Nullable("") CustomClickListenerSubclass customClickListener);
86+
@Nullable CustomClickListenerSubclass customClickListener);
9187

9288
TestManyTypesViewModelBuilder title(@androidx.annotation.Nullable CharSequence title);
9389

0 commit comments

Comments
 (0)