From 4d0cd23af55e01b3572a4226edd2e508f3667e83 Mon Sep 17 00:00:00 2001 From: Dagger Team Date: Wed, 11 Dec 2024 11:36:08 -0800 Subject: [PATCH] Add Nullmarking to Components RELNOTES=Expand Nullmarking PiperOrigin-RevId: 705180224 --- .../binding/ComponentCreatorDescriptor.java | 6 ++++- .../codegen/binding/ComponentRequirement.java | 24 +++++++++++++++---- .../writing/ComponentImplementation.java | 21 +++++++++++++++- .../ComponentRequirementExpressions.java | 19 ++++++++++++++- .../codegen/xprocessing/MethodSpecs.java | 18 +++++++++++++- .../factory/FactoryBindsInstanceTest.java | 3 ++- ...ance_DEFAULT_MODE_test.DaggerTestComponent | 2 +- ...ce_FAST_INIT_MODE_test.DaggerTestComponent | 2 +- ...ance_DEFAULT_MODE_test.DaggerTestComponent | 2 +- ...ce_FAST_INIT_MODE_test.DaggerTestComponent | 2 +- 10 files changed, 86 insertions(+), 13 deletions(-) diff --git a/java/dagger/internal/codegen/binding/ComponentCreatorDescriptor.java b/java/dagger/internal/codegen/binding/ComponentCreatorDescriptor.java index 254ca7ea566..cf978a26f80 100644 --- a/java/dagger/internal/codegen/binding/ComponentCreatorDescriptor.java +++ b/java/dagger/internal/codegen/binding/ComponentCreatorDescriptor.java @@ -41,6 +41,7 @@ import dagger.internal.codegen.base.ComponentCreatorKind; import dagger.internal.codegen.javapoet.TypeNames; import dagger.internal.codegen.model.DependencyRequest; +import dagger.internal.codegen.xprocessing.Nullability; import dagger.internal.codegen.xprocessing.XElements; import java.util.List; @@ -217,7 +218,10 @@ private static ComponentRequirement requirement( DependencyRequest request = dependencyRequestFactory.forRequiredResolvedVariable(parameter, parameterType); return ComponentRequirement.forBoundInstance( - request.key(), request.isNullable(), elementForVariableName); + request.key(), + request.isNullable(), + elementForVariableName, + Nullability.of(elementForVariableName)); } return parameterType.getTypeElement().hasAnyAnnotation(moduleAnnotations()) diff --git a/java/dagger/internal/codegen/binding/ComponentRequirement.java b/java/dagger/internal/codegen/binding/ComponentRequirement.java index f5b5aa0c5e2..e54fee19f77 100644 --- a/java/dagger/internal/codegen/binding/ComponentRequirement.java +++ b/java/dagger/internal/codegen/binding/ComponentRequirement.java @@ -34,6 +34,7 @@ import dagger.internal.codegen.javapoet.TypeNames; import dagger.internal.codegen.model.BindingKind; import dagger.internal.codegen.model.Key; +import dagger.internal.codegen.xprocessing.Nullability; import dagger.internal.codegen.xprocessing.XTypeElements; import java.util.Optional; @@ -106,6 +107,16 @@ public enum NullPolicy { */ abstract Optional overrideNullPolicy(); + /** + * The nullability of the requirement. If set, this is used to determine the nullability of the + * requirement's type. + */ + public Nullability getNullability() { + return nullability; + } + + private Nullability nullability = Nullability.NOT_NULLABLE; + /** The requirement's null policy. */ public NullPolicy nullPolicy() { if (overrideNullPolicy().isPresent()) { @@ -195,16 +206,18 @@ public static ComponentRequirement forModule(XType type) { public static ComponentRequirement forBoundInstance(BoundInstanceBinding binding) { checkArgument(binding.kind().equals(BindingKind.BOUND_INSTANCE)); - return forBoundInstance(binding.key(), binding.isNullable(), binding.bindingElement().get()); + return forBoundInstance( + binding.key(), binding.isNullable(), binding.bindingElement().get(), binding.nullability()); } static ComponentRequirement forBoundInstance( - Key key, boolean nullable, XElement elementForVariableName) { + Key key, boolean nullable, XElement elementForVariableName, Nullability nullability) { return create( Kind.BOUND_INSTANCE, key.type().xprocessing(), nullable ? Optional.of(NullPolicy.ALLOW) : Optional.empty(), Optional.of(key), + nullability, getSimpleName(elementForVariableName)); } @@ -212,8 +225,9 @@ private static ComponentRequirement create(Kind kind, XType type) { return create( kind, type, - Optional.empty(), - Optional.empty(), + /* overrideNullPolicy= */ Optional.empty(), + /* key= */ Optional.empty(), + Nullability.NOT_NULLABLE, simpleVariableName(type.getTypeElement().getClassName())); } @@ -222,10 +236,12 @@ private static ComponentRequirement create( XType type, Optional overrideNullPolicy, Optional key, + Nullability nullability, String variableName) { ComponentRequirement requirement = new AutoValue_ComponentRequirement( kind, type.getTypeName(), overrideNullPolicy, key, variableName); + requirement.nullability = nullability; requirement.type = type; return requirement; } diff --git a/java/dagger/internal/codegen/writing/ComponentImplementation.java b/java/dagger/internal/codegen/writing/ComponentImplementation.java index 58c8c93f4ea..e11d3a3d47c 100644 --- a/java/dagger/internal/codegen/writing/ComponentImplementation.java +++ b/java/dagger/internal/codegen/writing/ComponentImplementation.java @@ -59,6 +59,7 @@ import com.google.common.collect.ListMultimap; import com.google.common.collect.Lists; import com.google.common.collect.MultimapBuilder; +import com.squareup.javapoet.AnnotationSpec; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; import com.squareup.javapoet.FieldSpec; @@ -491,8 +492,26 @@ private ShardImplementation(ClassName name) { requirement -> requirement, requirement -> ParameterSpec.builder( - requirement.type().getTypeName(), + requirement + .type() + .getTypeName() + .annotated( + requirement + .getNullability() + .typeUseNullableAnnotations() + .stream() + .map(AnnotationSpec::builder) + .map(AnnotationSpec.Builder::build) + .collect(toImmutableList())), getUniqueFieldName(requirement.variableName() + "Param")) + .addAnnotations( + requirement + .getNullability() + .nonTypeUseNullableAnnotations() + .stream() + .map(AnnotationSpec::builder) + .map(AnnotationSpec.Builder::build) + .collect(toImmutableList())) .build())); } diff --git a/java/dagger/internal/codegen/writing/ComponentRequirementExpressions.java b/java/dagger/internal/codegen/writing/ComponentRequirementExpressions.java index ea82f32891b..ea03683cdc7 100644 --- a/java/dagger/internal/codegen/writing/ComponentRequirementExpressions.java +++ b/java/dagger/internal/codegen/writing/ComponentRequirementExpressions.java @@ -19,12 +19,14 @@ import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Suppliers.memoize; +import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList; import static dagger.internal.codegen.writing.ComponentImplementation.FieldSpecKind.COMPONENT_REQUIREMENT_FIELD; import static javax.lang.model.element.Modifier.FINAL; import static javax.lang.model.element.Modifier.PRIVATE; import androidx.room.compiler.processing.XTypeElement; import com.google.common.base.Supplier; +import com.squareup.javapoet.AnnotationSpec; import com.squareup.javapoet.ClassName; import com.squareup.javapoet.CodeBlock; import com.squareup.javapoet.FieldSpec; @@ -129,7 +131,22 @@ public CodeBlock getExpression(ClassName requestingClass) { private MemberSelect createField() { String fieldName = componentShard.getUniqueFieldName(componentRequirement.variableName()); TypeName fieldType = componentRequirement.type().getTypeName(); - FieldSpec field = FieldSpec.builder(fieldType, fieldName, PRIVATE, FINAL).build(); + FieldSpec field = + FieldSpec.builder( + fieldType.annotated( + componentRequirement.getNullability().typeUseNullableAnnotations().stream() + .map(AnnotationSpec::builder) + .map(AnnotationSpec.Builder::build) + .collect(toImmutableList())), + fieldName, + PRIVATE, + FINAL) + .addAnnotations( + componentRequirement.getNullability().nonTypeUseNullableAnnotations().stream() + .map(AnnotationSpec::builder) + .map(AnnotationSpec.Builder::build) + .collect(toImmutableList())) + .build(); componentShard.addField(COMPONENT_REQUIREMENT_FIELD, field); componentShard.addComponentRequirementInitialization(fieldInitialization(field)); return MemberSelect.localField(componentShard, fieldName); diff --git a/java/dagger/internal/codegen/xprocessing/MethodSpecs.java b/java/dagger/internal/codegen/xprocessing/MethodSpecs.java index 405b73a7f0f..2eaac123504 100644 --- a/java/dagger/internal/codegen/xprocessing/MethodSpecs.java +++ b/java/dagger/internal/codegen/xprocessing/MethodSpecs.java @@ -16,6 +16,7 @@ package dagger.internal.codegen.xprocessing; +import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList; import static dagger.internal.codegen.xprocessing.JavaPoetExt.toParameterSpec; import static javax.lang.model.element.Modifier.PROTECTED; import static javax.lang.model.element.Modifier.PUBLIC; @@ -24,6 +25,7 @@ import androidx.room.compiler.processing.XMethodElement; import androidx.room.compiler.processing.XMethodType; import androidx.room.compiler.processing.XType; +import com.squareup.javapoet.AnnotationSpec; import com.squareup.javapoet.MethodSpec; // TODO(bcorso): Consider moving these methods into XProcessing library. @@ -33,13 +35,27 @@ public final class MethodSpecs { /** Returns a {@link MethodSpec} that overrides the given method. */ public static MethodSpec.Builder overriding(XMethodElement method, XType owner) { XMethodType methodType = method.asMemberOf(owner); + Nullability nullability = Nullability.of(method); MethodSpec.Builder builder = // We're overriding the method so we have to use the jvm name here. MethodSpec.methodBuilder(method.getJvmName()) .addAnnotation(Override.class) + .addAnnotations( + nullability.nonTypeUseNullableAnnotations().stream() + .map(AnnotationSpec::builder) + .map(AnnotationSpec.Builder::build) + .collect(toImmutableList())) .addTypeVariables(methodType.getTypeVariableNames()) .varargs(method.isVarArgs()) - .returns(methodType.getReturnType().getTypeName()); + .returns( + methodType + .getReturnType() + .getTypeName() + .annotated( + nullability.typeUseNullableAnnotations().stream() + .map(AnnotationSpec::builder) + .map(AnnotationSpec.Builder::build) + .collect(toImmutableList()))); if (method.isPublic()) { builder.addModifiers(PUBLIC); } else if (method.isProtected()) { diff --git a/javatests/dagger/functional/factory/FactoryBindsInstanceTest.java b/javatests/dagger/functional/factory/FactoryBindsInstanceTest.java index 83505e9812e..2dd16f2bedc 100644 --- a/javatests/dagger/functional/factory/FactoryBindsInstanceTest.java +++ b/javatests/dagger/functional/factory/FactoryBindsInstanceTest.java @@ -17,6 +17,7 @@ package dagger.functional.factory; import static com.google.common.truth.Truth.assertThat; +import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.METHOD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.RetentionPolicy.RUNTIME; @@ -60,7 +61,7 @@ public void nonNullableBindsInstance_failsOnNull() { } } - @Target({METHOD, PARAMETER}) + @Target({METHOD, PARAMETER, FIELD}) @Retention(RUNTIME) @interface Nullable {} diff --git a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsNullableInstance_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsNullableInstance_DEFAULT_MODE_test.DaggerTestComponent index 2cf0f2fa17a..e48486193b9 100644 --- a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsNullableInstance_DEFAULT_MODE_test.DaggerTestComponent +++ b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsNullableInstance_DEFAULT_MODE_test.DaggerTestComponent @@ -35,7 +35,7 @@ final class DaggerTestComponent { private static final class TestComponentImpl implements TestComponent { private final TestComponentImpl testComponentImpl = this; - private TestComponentImpl(Bar argParam) { + private TestComponentImpl(@Nullable Bar argParam) { } diff --git a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsNullableInstance_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsNullableInstance_FAST_INIT_MODE_test.DaggerTestComponent index b1241f879ce..95c16687644 100644 --- a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsNullableInstance_FAST_INIT_MODE_test.DaggerTestComponent +++ b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsNullableInstance_FAST_INIT_MODE_test.DaggerTestComponent @@ -35,7 +35,7 @@ final class DaggerTestComponent { private static final class TestComponentImpl implements TestComponent { private final TestComponentImpl testComponentImpl = this; - private TestComponentImpl(Bar argParam) { + private TestComponentImpl(@Nullable Bar argParam) { } diff --git a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsTypeUseNullableInstance_DEFAULT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsTypeUseNullableInstance_DEFAULT_MODE_test.DaggerTestComponent index b1241f879ce..95c16687644 100644 --- a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsTypeUseNullableInstance_DEFAULT_MODE_test.DaggerTestComponent +++ b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsTypeUseNullableInstance_DEFAULT_MODE_test.DaggerTestComponent @@ -35,7 +35,7 @@ final class DaggerTestComponent { private static final class TestComponentImpl implements TestComponent { private final TestComponentImpl testComponentImpl = this; - private TestComponentImpl(Bar argParam) { + private TestComponentImpl(@Nullable Bar argParam) { } diff --git a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsTypeUseNullableInstance_FAST_INIT_MODE_test.DaggerTestComponent b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsTypeUseNullableInstance_FAST_INIT_MODE_test.DaggerTestComponent index b1241f879ce..95c16687644 100644 --- a/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsTypeUseNullableInstance_FAST_INIT_MODE_test.DaggerTestComponent +++ b/javatests/dagger/internal/codegen/goldens/ComponentRequirementFieldTest_testBindsTypeUseNullableInstance_FAST_INIT_MODE_test.DaggerTestComponent @@ -35,7 +35,7 @@ final class DaggerTestComponent { private static final class TestComponentImpl implements TestComponent { private final TestComponentImpl testComponentImpl = this; - private TestComponentImpl(Bar argParam) { + private TestComponentImpl(@Nullable Bar argParam) { }