Skip to content

Commit

Permalink
Fix crash when there are multiple injected constructors
Browse files Browse the repository at this point in the history
RELNOTES=N/A
PiperOrigin-RevId: 555635748
  • Loading branch information
kuanyingchou authored and Dagger Team committed Aug 10, 2023
1 parent 8e4a4b4 commit 698f6cb
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@ public static ImmutableList<AssistedParameter> assistedInjectAssistedParameters(
XType assistedInjectType) {
// We keep track of the constructor both as an ExecutableElement to access @Assisted
// parameters and as an ExecutableType to access the resolved parameter types.
ImmutableSet<XConstructorElement> assistedInjectConstructors =
assistedInjectedConstructors(assistedInjectType.getTypeElement());
XConstructorElement assistedInjectConstructor =
getOnlyElement(assistedInjectedConstructors(assistedInjectType.getTypeElement()));
XConstructorType assistedInjectConstructorType =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.squareup.javapoet.ClassName;
import dagger.internal.codegen.binding.AssistedInjectionAnnotations.AssistedParameter;
import dagger.internal.codegen.javapoet.TypeNames;
import dagger.internal.codegen.validation.InjectValidator;
import dagger.internal.codegen.validation.ValidationReport;
import java.util.HashSet;
import java.util.Set;
Expand All @@ -34,10 +35,12 @@
/** An annotation processor for {@link dagger.assisted.AssistedInject}-annotated elements. */
final class AssistedInjectProcessingStep extends TypeCheckingProcessingStep<XConstructorElement> {
private final XMessager messager;
private final InjectValidator injectValidator;

@Inject
AssistedInjectProcessingStep(XMessager messager) {
AssistedInjectProcessingStep(XMessager messager, InjectValidator injectValidator) {
this.messager = messager;
this.injectValidator = injectValidator;
}

@Override
Expand All @@ -48,7 +51,13 @@ public ImmutableSet<ClassName> annotationClassNames() {
@Override
protected void process(
XConstructorElement assistedInjectElement, ImmutableSet<ClassName> annotations) {
new AssistedInjectValidator().validate(assistedInjectElement).printMessagesTo(messager);
// The InjectValidator has already run and reported its errors in InjectProcessingStep, so no
// need to report its errors. However, the AssistedInjectValidator relies on the InjectValidator
// returning a clean report, so we check that first before running AssistedInjectValidator. This
// shouldn't be expensive since InjectValidator caches its results after validating.
if (injectValidator.validate(assistedInjectElement.getEnclosingElement()).isClean()) {
new AssistedInjectValidator().validate(assistedInjectElement).printMessagesTo(messager);
}
}

private final class AssistedInjectValidator {
Expand Down
34 changes: 34 additions & 0 deletions javatests/dagger/internal/codegen/AssistedErrorsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,38 @@ public void testNestedFactoryNotStatic() {
.onLine(12);
});
}


@Test
public void testMultipleInjectedConstructors() {
Source foo =
CompilerTests.kotlinSource(
"test.Foo.kt",
"package test;",
"",
"import dagger.assisted.Assisted",
"import dagger.assisted.AssistedInject",
"import dagger.assisted.AssistedFactory",
"import javax.inject.Inject",
"",
"class Foo @AssistedInject constructor(@Assisted i: Int) {",
"",
" @Inject",
" constructor(s: String, @Assisted i: Int): this(i) {}",
"}");

CompilerTests.daggerCompiler(foo)
.withProcessingOptions(compilerMode.processorOptions())
.compile(
subject -> {
subject.hasErrorCount(2);
subject.hasErrorContaining(
"Type test.Foo may only contain one injected constructor."
+ " Found: [@Inject test.Foo(String, int),"
+ " @dagger.assisted.AssistedInject test.Foo(int)]");
subject.hasErrorContaining(
"@Assisted parameters can only be used within an"
+ " @AssistedInject-annotated constructor.");
});
}
}
29 changes: 29 additions & 0 deletions javatests/dagger/internal/codegen/AssistedInjectErrorsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -243,4 +243,33 @@ public void testAssistedInjectWithUniqueQualifiedTypesPasses() {
.withProcessingOptions(compilerMode.processorOptions())
.compile(subject -> subject.hasErrorCount(0));
}

@Test
public void testMultipleAssistedInjectedConstructors() {
Source foo =
CompilerTests.kotlinSource(
"test.Foo.kt",
"package test;",
"",
"import dagger.assisted.Assisted",
"import dagger.assisted.AssistedInject",
"import dagger.assisted.AssistedFactory",
"",
"class Foo @AssistedInject constructor(@Assisted i: Int) {",
"",
" @AssistedInject",
" constructor(s: String, @Assisted i: Int): this(i) {}",
"}");

CompilerTests.daggerCompiler(foo)
.withProcessingOptions(compilerMode.processorOptions())
.compile(
subject -> {
subject.hasErrorCount(1);
subject.hasErrorContaining(
"Type test.Foo may only contain one injected constructor."
+ " Found: [@dagger.assisted.AssistedInject test.Foo(int),"
+ " @dagger.assisted.AssistedInject test.Foo(String, int)]");
});
}
}

0 comments on commit 698f6cb

Please sign in to comment.