Skip to content

Commit

Permalink
Add Nullmarking to Components
Browse files Browse the repository at this point in the history
RELNOTES=Expand Nullmarking
PiperOrigin-RevId: 705180224
  • Loading branch information
java-team-github-bot authored and Dagger Team committed Dec 20, 2024
1 parent 07d8f88 commit 093158b
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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())
Expand Down
24 changes: 20 additions & 4 deletions java/dagger/internal/codegen/binding/ComponentRequirement.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -106,6 +107,16 @@ public enum NullPolicy {
*/
abstract Optional<NullPolicy> 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()) {
Expand Down Expand Up @@ -195,25 +206,28 @@ 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));
}

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()));
}

Expand All @@ -222,10 +236,12 @@ private static ComponentRequirement create(
XType type,
Optional<NullPolicy> overrideNullPolicy,
Optional<Key> key,
Nullability nullability,
String variableName) {
ComponentRequirement requirement =
new AutoValue_ComponentRequirement(
kind, type.getTypeName(), overrideNullPolicy, key, variableName);
requirement.nullability = nullability;
requirement.type = type;
return requirement;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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()));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
18 changes: 17 additions & 1 deletion java/dagger/internal/codegen/xprocessing/MethodSpecs.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
Expand All @@ -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()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -60,7 +61,7 @@ public void nonNullableBindsInstance_failsOnNull() {
}
}

@Target({METHOD, PARAMETER})
@Target({METHOD, PARAMETER, FIELD})
@Retention(RUNTIME)
@interface Nullable {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {


}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {


}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {


}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {


}
Expand Down

0 comments on commit 093158b

Please sign in to comment.