Skip to content

Commit f6ddcc3

Browse files
bcorsoDagger Team
authored andcommitted
Remove caching of @AssistedInject bindings to work around b/305748522.
This is a short-term fix for b/305748522 so that we can push through our other fix for b/302199325. The long-term fix is outlined in the b/305748522 but probably requires more design discussion. RELNOTES=N/A PiperOrigin-RevId: 574226829
1 parent d7dd656 commit f6ddcc3

File tree

4 files changed

+361
-3
lines changed

4 files changed

+361
-3
lines changed

java/dagger/internal/codegen/binding/BindingGraphFactory.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import dagger.internal.codegen.base.OptionalType;
5252
import dagger.internal.codegen.compileroption.CompilerOptions;
5353
import dagger.internal.codegen.javapoet.TypeNames;
54+
import dagger.internal.codegen.model.BindingKind;
5455
import dagger.internal.codegen.model.ComponentPath;
5556
import dagger.internal.codegen.model.DaggerTypeElement;
5657
import dagger.internal.codegen.model.DependencyRequest;
@@ -812,11 +813,17 @@ void resolve(Key key) {
812813
/* Resolve in the parent in case there are multibinding contributions or conflicts in some
813814
* component between this one and the previously-resolved one. */
814815
parentResolver.get().resolve(key);
815-
if (!new LocalDependencyChecker().dependsOnLocalBindings(key)
816-
&& getLocalExplicitBindings(key).isEmpty()) {
816+
ResolvedBindings previouslyResolvedBindings = getPreviouslyResolvedBindings(key).get();
817+
// TODO(b/305748522): Allow caching for assisted injection bindings.
818+
boolean isAssistedInjectionBinding =
819+
previouslyResolvedBindings.bindings().stream()
820+
.anyMatch(binding -> binding.kind() == BindingKind.ASSISTED_INJECTION);
821+
if (!isAssistedInjectionBinding
822+
&& !new LocalDependencyChecker().dependsOnLocalBindings(key)
823+
&& getLocalExplicitBindings(key).isEmpty()) {
817824
/* Cache the inherited parent component's bindings in case resolving at the parent found
818825
* bindings in some component between this one and the previously-resolved one. */
819-
resolvedContributionBindings.put(key, getPreviouslyResolvedBindings(key).get());
826+
resolvedContributionBindings.put(key, previouslyResolvedBindings);
820827
return;
821828
}
822829
}

javatests/dagger/internal/codegen/AssistedFactoryTest.java

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,4 +326,110 @@ public void testParameterizedAssistParam() throws Exception {
326326
subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent"));
327327
});
328328
}
329+
330+
// This is a regression test for b/305748522
331+
// The important thing for this test is that we have two assisted factories for the same assisted
332+
// injection class and that they are requested in different components.
333+
@Test
334+
public void testMultipleAssistedFactoryInDifferentComponents() throws Exception {
335+
Source component =
336+
CompilerTests.javaSource(
337+
"test.MyComponent",
338+
"package test;",
339+
"",
340+
"import dagger.Component;",
341+
"",
342+
"@Component",
343+
"interface MyComponent {",
344+
" MyComponentAssistedFactory myComponentAssistedFactory();",
345+
" MySubcomponent mySubcomponent();",
346+
"}");
347+
Source subcomponent =
348+
CompilerTests.javaSource(
349+
"test.MySubcomponent",
350+
"package test;",
351+
"",
352+
"import dagger.Subcomponent;",
353+
"",
354+
"@Subcomponent",
355+
"interface MySubcomponent {",
356+
" MySubcomponentAssistedFactory mySubcomponentAssistedFactory();",
357+
"}");
358+
Source assistedClass =
359+
CompilerTests.javaSource(
360+
"test.MyAssistedClass",
361+
"package test;",
362+
"",
363+
"import dagger.assisted.Assisted;",
364+
"import dagger.assisted.AssistedInject;",
365+
"",
366+
"final class MyAssistedClass {",
367+
" private final Foo foo;",
368+
" private final Bar bar;",
369+
"",
370+
" @AssistedInject",
371+
" MyAssistedClass(@Assisted Foo foo, Baz baz, @Assisted Bar bar) {",
372+
" this.foo = foo;",
373+
" this.bar = bar;",
374+
" }",
375+
"}");
376+
Source componentAssistedFactory =
377+
CompilerTests.javaSource(
378+
"test.MyComponentAssistedFactory",
379+
"package test;",
380+
"",
381+
"import dagger.assisted.AssistedFactory;",
382+
"",
383+
"@AssistedFactory",
384+
"interface MyComponentAssistedFactory {",
385+
" MyAssistedClass create(Bar bar, Foo foo);",
386+
"}");
387+
Source subcomponentAssistedFactory =
388+
CompilerTests.javaSource(
389+
"test.MySubcomponentAssistedFactory",
390+
"package test;",
391+
"",
392+
"import dagger.assisted.AssistedFactory;",
393+
"",
394+
"@AssistedFactory",
395+
"interface MySubcomponentAssistedFactory {",
396+
" MyAssistedClass create(Bar bar, Foo foo);",
397+
"}");
398+
Source foo =
399+
CompilerTests.javaSource(
400+
"test.Foo",
401+
"package test;",
402+
"final class Foo {}");
403+
Source bar =
404+
CompilerTests.javaSource(
405+
"test.Bar",
406+
"package test;",
407+
"final class Bar {}");
408+
Source baz =
409+
CompilerTests.javaSource(
410+
"test.Baz",
411+
"package test;",
412+
"",
413+
"import javax.inject.Inject;",
414+
"",
415+
"final class Baz {",
416+
" @Inject Baz() {}",
417+
"}");
418+
419+
CompilerTests.daggerCompiler(
420+
component,
421+
subcomponent,
422+
assistedClass,
423+
componentAssistedFactory,
424+
subcomponentAssistedFactory,
425+
foo,
426+
bar,
427+
baz)
428+
.withProcessingOptions(compilerMode.processorOptions())
429+
.compile(
430+
subject -> {
431+
subject.hasErrorCount(0);
432+
subject.generatedSource(goldenFileRule.goldenSource("test/DaggerMyComponent"));
433+
});
434+
}
329435
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package test;
2+
3+
import dagger.internal.DaggerGenerated;
4+
import javax.annotation.processing.Generated;
5+
import javax.inject.Provider;
6+
7+
@DaggerGenerated
8+
@Generated(
9+
value = "dagger.internal.codegen.ComponentProcessor",
10+
comments = "https://dagger.dev"
11+
)
12+
@SuppressWarnings({
13+
"unchecked",
14+
"rawtypes",
15+
"KotlinInternal",
16+
"KotlinInternalInJava"
17+
})
18+
final class DaggerMyComponent {
19+
private DaggerMyComponent() {
20+
}
21+
22+
public static Builder builder() {
23+
return new Builder();
24+
}
25+
26+
public static MyComponent create() {
27+
return new Builder().build();
28+
}
29+
30+
static final class Builder {
31+
private Builder() {
32+
}
33+
34+
public MyComponent build() {
35+
return new MyComponentImpl();
36+
}
37+
}
38+
39+
private static final class MySubcomponentImpl implements MySubcomponent {
40+
private final MyComponentImpl myComponentImpl;
41+
42+
private final MySubcomponentImpl mySubcomponentImpl = this;
43+
44+
private MyAssistedClass_Factory myAssistedClassProvider;
45+
46+
private Provider<MySubcomponentAssistedFactory> mySubcomponentAssistedFactoryProvider;
47+
48+
private MySubcomponentImpl(MyComponentImpl myComponentImpl) {
49+
this.myComponentImpl = myComponentImpl;
50+
51+
initialize();
52+
53+
}
54+
55+
@SuppressWarnings("unchecked")
56+
private void initialize() {
57+
this.myAssistedClassProvider = MyAssistedClass_Factory.create(Baz_Factory.create());
58+
this.mySubcomponentAssistedFactoryProvider = MySubcomponentAssistedFactory_Impl.create(myAssistedClassProvider);
59+
}
60+
61+
@Override
62+
public MySubcomponentAssistedFactory mySubcomponentAssistedFactory() {
63+
return mySubcomponentAssistedFactoryProvider.get();
64+
}
65+
}
66+
67+
private static final class MyComponentImpl implements MyComponent {
68+
private final MyComponentImpl myComponentImpl = this;
69+
70+
private MyAssistedClass_Factory myAssistedClassProvider;
71+
72+
private Provider<MyComponentAssistedFactory> myComponentAssistedFactoryProvider;
73+
74+
private MyComponentImpl() {
75+
76+
initialize();
77+
78+
}
79+
80+
@SuppressWarnings("unchecked")
81+
private void initialize() {
82+
this.myAssistedClassProvider = MyAssistedClass_Factory.create(Baz_Factory.create());
83+
this.myComponentAssistedFactoryProvider = MyComponentAssistedFactory_Impl.create(myAssistedClassProvider);
84+
}
85+
86+
@Override
87+
public MyComponentAssistedFactory myComponentAssistedFactory() {
88+
return myComponentAssistedFactoryProvider.get();
89+
}
90+
91+
@Override
92+
public MySubcomponent mySubcomponent() {
93+
return new MySubcomponentImpl(myComponentImpl);
94+
}
95+
}
96+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
package test;
2+
3+
import dagger.internal.DaggerGenerated;
4+
import dagger.internal.SingleCheck;
5+
import javax.annotation.processing.Generated;
6+
import javax.inject.Provider;
7+
8+
@DaggerGenerated
9+
@Generated(
10+
value = "dagger.internal.codegen.ComponentProcessor",
11+
comments = "https://dagger.dev"
12+
)
13+
@SuppressWarnings({
14+
"unchecked",
15+
"rawtypes",
16+
"KotlinInternal",
17+
"KotlinInternalInJava"
18+
})
19+
final class DaggerMyComponent {
20+
private DaggerMyComponent() {
21+
}
22+
23+
public static Builder builder() {
24+
return new Builder();
25+
}
26+
27+
public static MyComponent create() {
28+
return new Builder().build();
29+
}
30+
31+
static final class Builder {
32+
private Builder() {
33+
}
34+
35+
public MyComponent build() {
36+
return new MyComponentImpl();
37+
}
38+
}
39+
40+
private static final class MySubcomponentImpl implements MySubcomponent {
41+
private final MyComponentImpl myComponentImpl;
42+
43+
private final MySubcomponentImpl mySubcomponentImpl = this;
44+
45+
private Provider<MySubcomponentAssistedFactory> mySubcomponentAssistedFactoryProvider;
46+
47+
private MySubcomponentImpl(MyComponentImpl myComponentImpl) {
48+
this.myComponentImpl = myComponentImpl;
49+
50+
initialize();
51+
52+
}
53+
54+
@SuppressWarnings("unchecked")
55+
private void initialize() {
56+
this.mySubcomponentAssistedFactoryProvider = SingleCheck.provider(new SwitchingProvider<MySubcomponentAssistedFactory>(myComponentImpl, mySubcomponentImpl, 0));
57+
}
58+
59+
@Override
60+
public MySubcomponentAssistedFactory mySubcomponentAssistedFactory() {
61+
return mySubcomponentAssistedFactoryProvider.get();
62+
}
63+
64+
private static final class SwitchingProvider<T> implements Provider<T> {
65+
private final MyComponentImpl myComponentImpl;
66+
67+
private final MySubcomponentImpl mySubcomponentImpl;
68+
69+
private final int id;
70+
71+
SwitchingProvider(MyComponentImpl myComponentImpl, MySubcomponentImpl mySubcomponentImpl,
72+
int id) {
73+
this.myComponentImpl = myComponentImpl;
74+
this.mySubcomponentImpl = mySubcomponentImpl;
75+
this.id = id;
76+
}
77+
78+
@SuppressWarnings("unchecked")
79+
@Override
80+
public T get() {
81+
switch (id) {
82+
case 0: // test.MySubcomponentAssistedFactory
83+
return (T) new MySubcomponentAssistedFactory() {
84+
@Override
85+
public MyAssistedClass create(Bar bar, Foo foo) {
86+
return new MyAssistedClass(foo, new Baz(), bar);
87+
}
88+
};
89+
90+
default: throw new AssertionError(id);
91+
}
92+
}
93+
}
94+
}
95+
96+
private static final class MyComponentImpl implements MyComponent {
97+
private final MyComponentImpl myComponentImpl = this;
98+
99+
private Provider<MyComponentAssistedFactory> myComponentAssistedFactoryProvider;
100+
101+
private MyComponentImpl() {
102+
103+
initialize();
104+
105+
}
106+
107+
@SuppressWarnings("unchecked")
108+
private void initialize() {
109+
this.myComponentAssistedFactoryProvider = SingleCheck.provider(new SwitchingProvider<MyComponentAssistedFactory>(myComponentImpl, 0));
110+
}
111+
112+
@Override
113+
public MyComponentAssistedFactory myComponentAssistedFactory() {
114+
return myComponentAssistedFactoryProvider.get();
115+
}
116+
117+
@Override
118+
public MySubcomponent mySubcomponent() {
119+
return new MySubcomponentImpl(myComponentImpl);
120+
}
121+
122+
private static final class SwitchingProvider<T> implements Provider<T> {
123+
private final MyComponentImpl myComponentImpl;
124+
125+
private final int id;
126+
127+
SwitchingProvider(MyComponentImpl myComponentImpl, int id) {
128+
this.myComponentImpl = myComponentImpl;
129+
this.id = id;
130+
}
131+
132+
@SuppressWarnings("unchecked")
133+
@Override
134+
public T get() {
135+
switch (id) {
136+
case 0: // test.MyComponentAssistedFactory
137+
return (T) new MyComponentAssistedFactory() {
138+
@Override
139+
public MyAssistedClass create(Bar bar, Foo foo) {
140+
return new MyAssistedClass(foo, new Baz(), bar);
141+
}
142+
};
143+
144+
default: throw new AssertionError(id);
145+
}
146+
}
147+
}
148+
}
149+
}

0 commit comments

Comments
 (0)