Skip to content

Commit

Permalink
Retain nullability annotations when building override versions of fun…
Browse files Browse the repository at this point in the history
…ctions.

PiperOrigin-RevId: 684170828
  • Loading branch information
java-team-github-bot authored and Dagger Team committed Oct 9, 2024
1 parent a03263c commit 41fd826
Show file tree
Hide file tree
Showing 7 changed files with 233 additions and 5 deletions.
21 changes: 21 additions & 0 deletions java/dagger/internal/codegen/xprocessing/JavaPoetExt.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@

package dagger.internal.codegen.xprocessing;

import static dagger.internal.codegen.extension.DaggerStreams.toImmutableSet;
import static dagger.internal.codegen.xprocessing.XElements.getSimpleName;

import androidx.room.compiler.processing.XExecutableParameterElement;
import androidx.room.compiler.processing.XType;
import androidx.room.compiler.processing.XTypeElement;
import com.google.common.collect.ImmutableSet;
import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.TypeSpec;

Expand Down Expand Up @@ -53,5 +56,23 @@ public static ParameterSpec toParameterSpec(XExecutableParameterElement param) {
return ParameterSpec.builder(param.getType().getTypeName(), param.getJvmName()).build();
}

public static ParameterSpec toParameterSpec(
XExecutableParameterElement parameter, XType parameterType) {
Nullability nullability = Nullability.of(parameter);
ImmutableSet<AnnotationSpec> typeUseNullableAnnotations =
nullability.typeUseNullableAnnotations().stream()
.map(annotation -> AnnotationSpec.builder(annotation).build())
.collect(toImmutableSet());
ImmutableSet<AnnotationSpec> nonTypeUseNullableAnnotations =
nullability.nonTypeUseNullableAnnotations().stream()
.map(annotation -> AnnotationSpec.builder(annotation).build())
.collect(toImmutableSet());
return ParameterSpec.builder(
parameterType.getTypeName().annotated(typeUseNullableAnnotations.asList()),
parameter.getJvmName())
.addAnnotations(nonTypeUseNullableAnnotations)
.build();
}

private JavaPoetExt() {}
}
10 changes: 5 additions & 5 deletions java/dagger/internal/codegen/xprocessing/MethodSpecs.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@

package dagger.internal.codegen.xprocessing;

import static dagger.internal.codegen.xprocessing.JavaPoetExt.toParameterSpec;
import static javax.lang.model.element.Modifier.PROTECTED;
import static javax.lang.model.element.Modifier.PUBLIC;

import androidx.room.compiler.processing.XExecutableParameterElement;
import androidx.room.compiler.processing.XMethodElement;
import androidx.room.compiler.processing.XMethodType;
import androidx.room.compiler.processing.XType;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterSpec;
import com.squareup.javapoet.TypeName;

// TODO(bcorso): Consider moving these methods into XProcessing library.
/** A utility class for {@link MethodSpec} helper methods. */
Expand All @@ -46,9 +46,9 @@ public static MethodSpec.Builder overriding(XMethodElement method, XType owner)
builder.addModifiers(PROTECTED);
}
for (int i = 0; i < methodType.getParameterTypes().size(); i++) {
String parameterName = method.getParameters().get(i).getJvmName();
TypeName parameterType = methodType.getParameterTypes().get(i).getTypeName();
builder.addParameter(ParameterSpec.builder(parameterType, parameterName).build());
XExecutableParameterElement parameter = method.getParameters().get(i);
XType parameterType = methodType.getParameterTypes().get(i);
builder.addParameter(toParameterSpec(parameter, parameterType));
}
method.getThrownTypes().stream().map(XType::getTypeName).forEach(builder::addException);
return builder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ public static Collection<Object[]> parameters() {
return CompilerMode.TEST_PARAMETERS;
}

private static final Source NON_TYPE_USE_NULLABLE =
CompilerTests.javaSource(
"test.Nullable", // force one-string-per-line format
"package test;",
"",
"public @interface Nullable {}");

@Rule public GoldenFileRule goldenFileRule = new GoldenFileRule();

private final CompilerMode compilerMode;
Expand Down Expand Up @@ -73,6 +80,38 @@ public void bindsInstance() throws Exception {
});
}

@Test
public void testBindsNullableInstance() throws Exception {
Source component =
CompilerTests.javaSource(
"test.TestComponent",
"package test;",
"",
"import dagger.BindsInstance;",
"import dagger.Component;",
"",
"@Component",
"interface TestComponent {",
" @Component.Factory",
" interface Factory {",
" TestComponent create(@BindsInstance @Nullable Bar arg);",
"}",
"}");
Source bar =
CompilerTests.javaSource(
"test.Bar", // force one-string-per-line format
"package test;",
"",
"interface Bar {}");
CompilerTests.daggerCompiler(component, bar, NON_TYPE_USE_NULLABLE)
.withProcessingOptions(compilerMode.processorOptions())
.compile(
subject -> {
subject.hasErrorCount(0);
subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent"));
});
}

@Test
public void instanceModuleMethod() throws Exception {
Source module =
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package test;

import dagger.internal.DaggerGenerated;
import javax.annotation.processing.Generated;

@DaggerGenerated
@Generated(
value = "dagger.internal.codegen.ComponentProcessor",
comments = "https://dagger.dev"
)
@SuppressWarnings({
"unchecked",
"rawtypes",
"KotlinInternal",
"KotlinInternalInJava",
"cast",
"deprecation"
})
final class DaggerTestComponent {
private DaggerTestComponent() {
}

public static TestComponent.Factory factory() {
return new Factory();
}

private static final class Factory implements TestComponent.Factory {
@Override
public TestComponent create(@Nullable Bar arg) {
return new TestComponentImpl(arg);
}
}

private static final class TestComponentImpl implements TestComponent {
private final TestComponentImpl testComponentImpl = this;

private TestComponentImpl(Bar argParam) {


}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package test;

import dagger.internal.DaggerGenerated;
import javax.annotation.processing.Generated;

@DaggerGenerated
@Generated(
value = "dagger.internal.codegen.ComponentProcessor",
comments = "https://dagger.dev"
)
@SuppressWarnings({
"unchecked",
"rawtypes",
"KotlinInternal",
"KotlinInternalInJava",
"cast",
"deprecation"
})
final class DaggerTestComponent {
private DaggerTestComponent() {
}

public static TestComponent.Factory factory() {
return new Factory();
}

private static final class Factory implements TestComponent.Factory {
@Override
public TestComponent create(@Nullable Bar arg) {
return new TestComponentImpl(arg);
}
}

private static final class TestComponentImpl implements TestComponent {
private final TestComponentImpl testComponentImpl = this;

private TestComponentImpl(Bar argParam) {


}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package test;

import dagger.internal.DaggerGenerated;
import javax.annotation.processing.Generated;

@DaggerGenerated
@Generated(
value = "dagger.internal.codegen.ComponentProcessor",
comments = "https://dagger.dev"
)
@SuppressWarnings({
"unchecked",
"rawtypes",
"KotlinInternal",
"KotlinInternalInJava",
"cast",
"deprecation"
})
final class DaggerTestComponent {
private DaggerTestComponent() {
}

public static TestComponent.Factory factory() {
return new Factory();
}

private static final class Factory implements TestComponent.Factory {
@Override
public TestComponent create(@Nullable Bar arg) {
return new TestComponentImpl(arg);
}
}

private static final class TestComponentImpl implements TestComponent {
private final TestComponentImpl testComponentImpl = this;

private TestComponentImpl(Bar argParam) {


}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package test;

import dagger.internal.DaggerGenerated;
import javax.annotation.processing.Generated;

@DaggerGenerated
@Generated(
value = "dagger.internal.codegen.ComponentProcessor",
comments = "https://dagger.dev"
)
@SuppressWarnings({
"unchecked",
"rawtypes",
"KotlinInternal",
"KotlinInternalInJava",
"cast",
"deprecation"
})
final class DaggerTestComponent {
private DaggerTestComponent() {
}

public static TestComponent.Factory factory() {
return new Factory();
}

private static final class Factory implements TestComponent.Factory {
@Override
public TestComponent create(@Nullable Bar arg) {
return new TestComponentImpl(arg);
}
}

private static final class TestComponentImpl implements TestComponent {
private final TestComponentImpl testComponentImpl = this;

private TestComponentImpl(Bar argParam) {


}
}
}

0 comments on commit 41fd826

Please sign in to comment.