diff --git a/blackbox-test-inject/src/main/java/org/example/myapp/generic/Aldrich.java b/blackbox-test-inject/src/main/java/org/example/myapp/generic/Aldrich.java new file mode 100644 index 000000000..e906fb9e9 --- /dev/null +++ b/blackbox-test-inject/src/main/java/org/example/myapp/generic/Aldrich.java @@ -0,0 +1,6 @@ +package org.example.myapp.generic; + +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +public interface Aldrich extends BiConsumer, Consumer> {} diff --git a/blackbox-test-inject/src/main/java/org/example/myapp/generic/MyA.java b/blackbox-test-inject/src/main/java/org/example/myapp/generic/MyA.java new file mode 100644 index 000000000..dc595929b --- /dev/null +++ b/blackbox-test-inject/src/main/java/org/example/myapp/generic/MyA.java @@ -0,0 +1,4 @@ +package org.example.myapp.generic; + +public interface MyA { +} diff --git a/blackbox-test-inject/src/main/java/org/example/myapp/generic/MyB.java b/blackbox-test-inject/src/main/java/org/example/myapp/generic/MyB.java new file mode 100644 index 000000000..e68343d8c --- /dev/null +++ b/blackbox-test-inject/src/main/java/org/example/myapp/generic/MyB.java @@ -0,0 +1,4 @@ +package org.example.myapp.generic; + +public interface MyB { +} diff --git a/blackbox-test-inject/src/main/java/org/example/myapp/generic/MyConsumer.java b/blackbox-test-inject/src/main/java/org/example/myapp/generic/MyConsumer.java new file mode 100644 index 000000000..a34b04a2a --- /dev/null +++ b/blackbox-test-inject/src/main/java/org/example/myapp/generic/MyConsumer.java @@ -0,0 +1,9 @@ +package org.example.myapp.generic; + +import java.util.function.BiConsumer; + +public class MyConsumer implements BiConsumer { + + @Override + public void accept(MyA t, MyB u) {} +} diff --git a/blackbox-test-inject/src/main/java/org/example/myapp/generic/MyConsumerFactory.java b/blackbox-test-inject/src/main/java/org/example/myapp/generic/MyConsumerFactory.java new file mode 100644 index 000000000..93dd72c26 --- /dev/null +++ b/blackbox-test-inject/src/main/java/org/example/myapp/generic/MyConsumerFactory.java @@ -0,0 +1,37 @@ +package org.example.myapp.generic; + +import io.avaje.inject.Bean; +import io.avaje.inject.Factory; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.BiConsumer; + +@Factory +class MyConsumerFactory { + + @Bean + MyConsumer createTest() { + return new MyConsumer(); + } + + @Bean + Map genericMap(BiConsumer consumer) { + return new HashMap<>(); + } + + @Bean + Aldrich bean() { + return new Aldrich<>() { + @Override + public void accept(String s, String s2) { + + } + + @Override + public void accept(BiConsumer stringStringBiConsumer) { + + } + }; + } +} diff --git a/blackbox-test-inject/src/main/java/org/example/myapp/generic/MyUseGenericDependencies.java b/blackbox-test-inject/src/main/java/org/example/myapp/generic/MyUseGenericDependencies.java new file mode 100644 index 000000000..0bd7fbb31 --- /dev/null +++ b/blackbox-test-inject/src/main/java/org/example/myapp/generic/MyUseGenericDependencies.java @@ -0,0 +1,34 @@ +package org.example.myapp.generic; + +import jakarta.inject.Singleton; + +import java.util.Map; +import java.util.function.BiConsumer; + +@Singleton +class MyUseGenericDependencies { + + private final Aldrich aldrich; + private final Map genericMap; + private final BiConsumer biConsumer; + + MyUseGenericDependencies(Aldrich aldrich, + Map genericMap, + BiConsumer biConsumer) { + this.aldrich = aldrich; + this.genericMap = genericMap; + this.biConsumer = biConsumer; + } + + Aldrich getAldrich() { + return aldrich; + } + + Map getGenericMap() { + return genericMap; + } + + BiConsumer getBiConsumer() { + return biConsumer; + } +} diff --git a/blackbox-test-inject/src/test/java/org/example/myapp/generic/GenericFactoryTest.java b/blackbox-test-inject/src/test/java/org/example/myapp/generic/GenericFactoryTest.java index bc16a9c13..dc7c5a5e3 100644 --- a/blackbox-test-inject/src/test/java/org/example/myapp/generic/GenericFactoryTest.java +++ b/blackbox-test-inject/src/test/java/org/example/myapp/generic/GenericFactoryTest.java @@ -12,10 +12,14 @@ class GenericFactoryTest { @Inject Generic intymcintface; @Inject Generic stringy; + @Inject MyUseGenericDependencies others; @Test void test() { assertThat(intymcintface).isNotNull(); assertThat(stringy).isNotNull(); + assertThat(others.getAldrich()).isNotNull(); + assertThat(others.getGenericMap()).isNotNull(); + assertThat(others.getBiConsumer()).isNotNull(); } } diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/TypeAppender.java b/inject-generator/src/main/java/io/avaje/inject/generator/TypeAppender.java index 48ede3867..a99461622 100644 --- a/inject-generator/src/main/java/io/avaje/inject/generator/TypeAppender.java +++ b/inject-generator/src/main/java/io/avaje/inject/generator/TypeAppender.java @@ -3,6 +3,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Set; +import java.util.stream.Stream; import javax.lang.model.type.TypeKind; @@ -21,22 +22,31 @@ final class TypeAppender { void add(UType utype) { var type = Util.unwrapProvider(utype); - var components = type.componentTypes(); - if (isAddGenericType(type, components)) { + if (isAddGenericType(type)) { addUType(type); } else { addSimpleType(type.mainType()); } } - private static boolean isAddGenericType(UType type, List components) { + private static boolean isAddGenericType(UType type) { + var components = type.componentTypes(); return type.isGeneric() && type.kind() != TypeKind.TYPEVAR && (components.size() != 1 || components.get(0).kind() != TypeKind.WILDCARD) && components.stream() + .flatMap(TypeAppender::allComponentTypes) .noneMatch(u -> u.kind() == TypeKind.TYPEVAR || u.kind() == TypeKind.WILDCARD); } + private static Stream allComponentTypes(UType u) { + final var componentTypes = u.componentTypes(); + return componentTypes.isEmpty() + ? Stream.of(u) + : Stream.concat( + Stream.of(u), componentTypes.stream().flatMap(TypeAppender::allComponentTypes)); + } + void add(List sourceTypes) { sourceTypes.forEach(this::add); } diff --git a/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/generic/MyConsumer.java b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/generic/MyConsumer.java deleted file mode 100644 index d9131be81..000000000 --- a/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/generic/MyConsumer.java +++ /dev/null @@ -1,12 +0,0 @@ -package io.avaje.inject.generator.models.valid.generic; - -import java.util.function.BiConsumer; -import java.util.function.Function; - -import io.avaje.inject.generator.models.valid.A0; - -public class MyConsumer implements BiConsumer { - - @Override - public void accept(A0 t, io.avaje.inject.generator.models.valid.nested.A0 u) {} -} diff --git a/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/generic/MyConsumerFactory.java b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/generic/MyConsumerFactory.java deleted file mode 100644 index b6b667518..000000000 --- a/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/generic/MyConsumerFactory.java +++ /dev/null @@ -1,23 +0,0 @@ -package io.avaje.inject.generator.models.valid.generic; - -import java.util.Map; -import java.util.function.BiConsumer; - -import io.avaje.inject.Bean; -import io.avaje.inject.Factory; -import io.avaje.inject.generator.models.valid.A0; - -@Factory -public class MyConsumerFactory { - - @Bean - MyConsumer createTest() { - return new MyConsumer(); - } - - @Bean - Map genericMap( - BiConsumer consumer) { - return null; - } -} diff --git a/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/provider/BProv.java b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/provider/BProv.java new file mode 100644 index 000000000..4e02be9dd --- /dev/null +++ b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/provider/BProv.java @@ -0,0 +1,14 @@ +package io.avaje.inject.generator.models.valid.provider; + +public class BProv { + + final T value; + + public BProv(T value) { + this.value = value; + } + + public T get() { + return value; + } +} diff --git a/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/provider/BProvProvider.java b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/provider/BProvProvider.java new file mode 100644 index 000000000..2f722e516 --- /dev/null +++ b/inject-generator/src/test/java/io/avaje/inject/generator/models/valid/provider/BProvProvider.java @@ -0,0 +1,17 @@ +package io.avaje.inject.generator.models.valid.provider; + +import io.avaje.inject.Component; +import jakarta.inject.Provider; + +import java.util.concurrent.atomic.AtomicInteger; + +@Component +public class BProvProvider implements Provider> { + + AtomicInteger counter = new AtomicInteger(); + + @Override + public BProv get() { + return new BProv<>("Hello BProv" + counter.incrementAndGet()); + } +} diff --git a/inject-test/src/test/java/org/example/coffee/provider/BProvProviderTest.java b/inject-test/src/test/java/org/example/coffee/provider/BProvProviderTest.java index 2e5e80ba5..424818e16 100644 --- a/inject-test/src/test/java/org/example/coffee/provider/BProvProviderTest.java +++ b/inject-test/src/test/java/org/example/coffee/provider/BProvProviderTest.java @@ -17,6 +17,11 @@ void providerOfGenericType() { BProv bProv2 = beanScope.get(BProvProvider$DI.TYPE_BProvString); assertThat(bProv).isNotSameAs(bProv2); assertThat(bProv2.get()).isEqualTo("Hello BProv2"); + + BProvUser bProvUser = beanScope.get(BProvUser.class); + BProv bProv3 = bProvUser.getProvider().get(); + assertThat(bProv3.get()).isEqualTo("Hello BProv3"); + assertThat(bProv).isNotSameAs(bProv3); } } diff --git a/inject-test/src/test/java/org/example/coffee/provider/BProvUser.java b/inject-test/src/test/java/org/example/coffee/provider/BProvUser.java new file mode 100644 index 000000000..b460a476b --- /dev/null +++ b/inject-test/src/test/java/org/example/coffee/provider/BProvUser.java @@ -0,0 +1,18 @@ +package org.example.coffee.provider; + +import io.avaje.inject.Component; +import jakarta.inject.Provider; + +@Component +class BProvUser { + + private final Provider> provider; + + BProvUser(Provider> provider){ + this.provider = provider; + } + + Provider> getProvider() { + return provider; + } +}