Skip to content

Commit 56e1eeb

Browse files
bcorsoDagger Team
authored andcommitted
Internal changes
RELNOTES=N/A PiperOrigin-RevId: 653003160
1 parent fb8bd41 commit 56e1eeb

File tree

2 files changed

+239
-11
lines changed

2 files changed

+239
-11
lines changed

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

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -278,18 +278,19 @@ ResolvedBindings lookUpBindings(Key requestKey) {
278278
Set<SubcomponentDeclaration> subcomponentDeclarations = new LinkedHashSet<>();
279279

280280
// Gather all bindings, multibindings, optional, and subcomponent declarations/contributions.
281-
ImmutableSet<Key> keysMatchingRequest = keysMatchingRequest(requestKey);
281+
ImmutableSet<Key> multibindingKeysMatchingRequest =
282+
multibindingKeysMatchingRequest(requestKey);
282283
for (Resolver resolver : getResolverLineage()) {
283284
bindings.addAll(resolver.getLocalExplicitBindings(requestKey));
285+
subcomponentDeclarations.addAll(resolver.declarations.subcomponents(requestKey));
286+
// The optional binding declarations are keyed by the unwrapped type.
287+
keyFactory.unwrapOptional(requestKey)
288+
.map(resolver.declarations::optionalBindings)
289+
.ifPresent(optionalBindingDeclarations::addAll);
284290

285-
for (Key key : keysMatchingRequest) {
291+
for (Key key : multibindingKeysMatchingRequest) {
286292
multibindingContributions.addAll(resolver.getLocalMultibindingContributions(key));
287293
multibindingDeclarations.addAll(resolver.declarations.multibindings(key));
288-
subcomponentDeclarations.addAll(resolver.declarations.subcomponents(key));
289-
// The optional binding declarations are keyed by the unwrapped type.
290-
keyFactory.unwrapOptional(key)
291-
.map(resolver.declarations::optionalBindings)
292-
.ifPresent(optionalBindingDeclarations::addAll);
293294
}
294295
}
295296

@@ -425,12 +426,12 @@ private void addSubcomponentToOwningResolver(ContributionBinding subcomponentCre
425426
* javac users)
426427
* </ul>
427428
*/
428-
private ImmutableSet<Key> keysMatchingRequest(Key requestKey) {
429+
private ImmutableSet<Key> multibindingKeysMatchingRequest(Key requestKey) {
429430
return keysMatchingRequestCache.computeIfAbsent(
430-
requestKey, this::keysMatchingRequestUncached);
431+
requestKey, this::multibindingKeysMatchingRequestUncached);
431432
}
432433

433-
private ImmutableSet<Key> keysMatchingRequestUncached(Key requestKey) {
434+
private ImmutableSet<Key> multibindingKeysMatchingRequestUncached(Key requestKey) {
434435
ImmutableSet.Builder<Key> keys = ImmutableSet.builder();
435436
keys.add(requestKey);
436437
keyFactory.unwrapSetKey(requestKey, TypeNames.PRODUCED).ifPresent(keys::add);
@@ -867,7 +868,7 @@ private boolean hasLocalBindings(ResolvedBindings resolvedBindings) {
867868
* this component's modules that matches the key.
868869
*/
869870
private boolean hasLocalMultibindingContributions(Key requestKey) {
870-
return keysMatchingRequest(requestKey)
871+
return multibindingKeysMatchingRequest(requestKey)
871872
.stream()
872873
.anyMatch(key -> !getLocalMultibindingContributions(key).isEmpty());
873874
}

javatests/dagger/internal/codegen/MultibindingTest.java

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package dagger.internal.codegen;
1818

19+
import androidx.room.compiler.processing.XProcessingEnv;
1920
import androidx.room.compiler.processing.util.Source;
2021
import dagger.testing.compile.CompilerTests;
2122
import org.junit.Test;
@@ -299,4 +300,230 @@ public void provideExplicitSetInParent_AndMultibindingContributionInChild() {
299300
.onLineContaining("interface Parent");
300301
});
301302
}
303+
304+
// Regression test for b/352142595.
305+
@Test
306+
public void testMultibindingMapWithKotlinSource() {
307+
Source parent =
308+
CompilerTests.kotlinSource(
309+
"test.Parent.kt",
310+
"package test",
311+
"",
312+
"import dagger.Component",
313+
"",
314+
"@Component(modules = [ParentModule::class])",
315+
"interface Parent {",
316+
" fun usage(): Usage",
317+
"}");
318+
Source usage =
319+
CompilerTests.kotlinSource(
320+
"test.Usage.kt",
321+
"package test",
322+
"",
323+
"import javax.inject.Inject",
324+
"",
325+
"class Usage @Inject constructor(map: Map<String, MyInterface>)");
326+
Source parentModule =
327+
CompilerTests.kotlinSource(
328+
"test.ParentModule.kt",
329+
"@file:Suppress(\"INLINE_FROM_HIGHER_PLATFORM\")", // Required to use TODO()
330+
"package test",
331+
"",
332+
"import dagger.Module",
333+
"import dagger.Provides",
334+
"import dagger.multibindings.IntoMap",
335+
"import dagger.multibindings.StringKey",
336+
"",
337+
"@Module",
338+
"class ParentModule {",
339+
" @Provides",
340+
" @IntoMap",
341+
" @StringKey(\"key\")",
342+
" fun provideMyInterface(): MyInterface = TODO()",
343+
"}");
344+
Source myInterface =
345+
CompilerTests.kotlinSource(
346+
"test.MyInterface.kt",
347+
"package test",
348+
"",
349+
"interface MyInterface");
350+
351+
CompilerTests.daggerCompiler(parent, parentModule, myInterface, usage)
352+
.compile(
353+
subject -> {
354+
// TODO(b/284207175): Due to a bug in our KSP implementation, KSP and Javac behave
355+
// differently. Rather than cause a breaking change by fixing this bug directly, we've
356+
// decided to wait until b/284207175 is implemented.
357+
if (CompilerTests.backend(subject) == XProcessingEnv.Backend.KSP) {
358+
subject.hasErrorCount(0);
359+
} else {
360+
subject.hasErrorCount(1);
361+
subject.hasErrorContaining("Map<String,? extends MyInterface> cannot be provided");
362+
}
363+
});
364+
}
365+
366+
// Regression test for b/352142595.
367+
@Test
368+
public void testMultibindingMapProviderWithKotlinSource() {
369+
Source parent =
370+
CompilerTests.kotlinSource(
371+
"test.Parent.kt",
372+
"package test",
373+
"",
374+
"import dagger.Component",
375+
"",
376+
"@Component(modules = [ParentModule::class])",
377+
"interface Parent {",
378+
" fun usage(): Usage",
379+
"}");
380+
Source usage =
381+
CompilerTests.kotlinSource(
382+
"test.Usage.kt",
383+
"package test",
384+
"",
385+
"import javax.inject.Inject",
386+
"import javax.inject.Provider",
387+
"",
388+
"class Usage @Inject constructor(map: Map<String, Provider<MyInterface>>)");
389+
Source parentModule =
390+
CompilerTests.kotlinSource(
391+
"test.ParentModule.kt",
392+
"@file:Suppress(\"INLINE_FROM_HIGHER_PLATFORM\")", // Required to use TODO()
393+
"package test",
394+
"",
395+
"import dagger.Module",
396+
"import dagger.Provides",
397+
"import dagger.multibindings.IntoMap",
398+
"import dagger.multibindings.StringKey",
399+
"",
400+
"@Module",
401+
"class ParentModule {",
402+
" @Provides",
403+
" @IntoMap",
404+
" @StringKey(\"key\")",
405+
" fun provideMyInterface(): MyInterface = TODO()",
406+
"}");
407+
Source myInterface =
408+
CompilerTests.kotlinSource(
409+
"test.MyInterface.kt",
410+
"package test",
411+
"",
412+
"interface MyInterface");
413+
414+
CompilerTests.daggerCompiler(parent, parentModule, myInterface, usage)
415+
.compile(
416+
subject -> {
417+
subject.hasErrorCount(1);
418+
subject.hasErrorContaining(
419+
"Map<String,? extends Provider<MyInterface>> cannot be provided");
420+
});
421+
}
422+
423+
// Regression test for b/352142595.
424+
@Test
425+
public void testMultibindingSetWithKotlinSource() {
426+
Source parent =
427+
CompilerTests.kotlinSource(
428+
"test.Parent.kt",
429+
"package test",
430+
"",
431+
"import dagger.Component",
432+
"",
433+
"@Component(modules = [ParentModule::class])",
434+
"interface Parent {",
435+
" fun usage(): Usage",
436+
"}");
437+
Source usage =
438+
CompilerTests.kotlinSource(
439+
"test.Usage.kt",
440+
"package test",
441+
"",
442+
"import javax.inject.Inject",
443+
"",
444+
"class Usage @Inject constructor(set: Set<MyInterface>)");
445+
Source parentModule =
446+
CompilerTests.kotlinSource(
447+
"test.ParentModule.kt",
448+
"@file:Suppress(\"INLINE_FROM_HIGHER_PLATFORM\")", // Required to use TODO()
449+
"package test",
450+
"",
451+
"import dagger.Module",
452+
"import dagger.Provides",
453+
"import dagger.multibindings.IntoSet",
454+
"",
455+
"@Module",
456+
"class ParentModule {",
457+
" @Provides",
458+
" @IntoSet",
459+
" fun provideMyInterface(): MyInterface = TODO()",
460+
"}");
461+
Source myInterface =
462+
CompilerTests.kotlinSource(
463+
"test.MyInterface.kt",
464+
"package test",
465+
"",
466+
"interface MyInterface");
467+
468+
CompilerTests.daggerCompiler(parent, parentModule, myInterface, usage)
469+
.compile(
470+
subject -> {
471+
subject.hasErrorCount(1);
472+
subject.hasErrorContaining("Set<? extends MyInterface> cannot be provided");
473+
});
474+
}
475+
476+
// Regression test for b/352142595.
477+
@Test
478+
public void testMultibindingSetProviderWithKotlinSource() {
479+
Source parent =
480+
CompilerTests.kotlinSource(
481+
"test.Parent.kt",
482+
"package test",
483+
"",
484+
"import dagger.Component",
485+
"",
486+
"@Component(modules = [ParentModule::class])",
487+
"interface Parent {",
488+
" fun usage(): Usage",
489+
"}");
490+
Source usage =
491+
CompilerTests.kotlinSource(
492+
"test.Usage.kt",
493+
"package test",
494+
"",
495+
"import javax.inject.Inject",
496+
"import javax.inject.Provider",
497+
"",
498+
"class Usage @Inject constructor(set: Set<Provider<MyInterface>>)");
499+
Source parentModule =
500+
CompilerTests.kotlinSource(
501+
"test.ParentModule.kt",
502+
"@file:Suppress(\"INLINE_FROM_HIGHER_PLATFORM\")", // Required to use TODO()
503+
"package test",
504+
"",
505+
"import dagger.Module",
506+
"import dagger.Provides",
507+
"import dagger.multibindings.IntoSet",
508+
"",
509+
"@Module",
510+
"class ParentModule {",
511+
" @Provides",
512+
" @IntoSet",
513+
" fun provideMyInterface(): MyInterface = TODO()",
514+
"}");
515+
Source myInterface =
516+
CompilerTests.kotlinSource(
517+
"test.MyInterface.kt",
518+
"package test",
519+
"",
520+
"interface MyInterface");
521+
522+
CompilerTests.daggerCompiler(parent, parentModule, myInterface, usage)
523+
.compile(
524+
subject -> {
525+
subject.hasErrorCount(1);
526+
subject.hasErrorContaining("Set<? extends Provider<MyInterface>> cannot be provided");
527+
});
528+
}
302529
}

0 commit comments

Comments
 (0)