Skip to content

Commit b5e4caf

Browse files
authored
Fix Injecting generic ypes extending generic types (#765)
* fix injecting generic types extending generic types * provider test * Update TypeAppender.java * Update TypeAppender.java
1 parent 16ccf41 commit b5e4caf

File tree

14 files changed

+165
-38
lines changed

14 files changed

+165
-38
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package org.example.myapp.generic;
2+
3+
import java.util.function.BiConsumer;
4+
import java.util.function.Consumer;
5+
6+
public interface Aldrich<T, T2> extends BiConsumer<T, T2>, Consumer<BiConsumer<T, T2>> {}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package org.example.myapp.generic;
2+
3+
public interface MyA {
4+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package org.example.myapp.generic;
2+
3+
public interface MyB {
4+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.example.myapp.generic;
2+
3+
import java.util.function.BiConsumer;
4+
5+
public class MyConsumer implements BiConsumer<MyA, MyB> {
6+
7+
@Override
8+
public void accept(MyA t, MyB u) {}
9+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package org.example.myapp.generic;
2+
3+
import io.avaje.inject.Bean;
4+
import io.avaje.inject.Factory;
5+
6+
import java.util.HashMap;
7+
import java.util.Map;
8+
import java.util.function.BiConsumer;
9+
10+
@Factory
11+
class MyConsumerFactory {
12+
13+
@Bean
14+
MyConsumer createTest() {
15+
return new MyConsumer();
16+
}
17+
18+
@Bean
19+
Map<String, MyConsumer> genericMap(BiConsumer<MyA, MyB> consumer) {
20+
return new HashMap<>();
21+
}
22+
23+
@Bean
24+
Aldrich<String, String> bean() {
25+
return new Aldrich<>() {
26+
@Override
27+
public void accept(String s, String s2) {
28+
29+
}
30+
31+
@Override
32+
public void accept(BiConsumer<String, String> stringStringBiConsumer) {
33+
34+
}
35+
};
36+
}
37+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package org.example.myapp.generic;
2+
3+
import jakarta.inject.Singleton;
4+
5+
import java.util.Map;
6+
import java.util.function.BiConsumer;
7+
8+
@Singleton
9+
class MyUseGenericDependencies {
10+
11+
private final Aldrich<String, String> aldrich;
12+
private final Map<String, MyConsumer> genericMap;
13+
private final BiConsumer<MyA, MyB> biConsumer;
14+
15+
MyUseGenericDependencies(Aldrich<String, String> aldrich,
16+
Map<String, MyConsumer> genericMap,
17+
BiConsumer<MyA, MyB> biConsumer) {
18+
this.aldrich = aldrich;
19+
this.genericMap = genericMap;
20+
this.biConsumer = biConsumer;
21+
}
22+
23+
Aldrich<String, String> getAldrich() {
24+
return aldrich;
25+
}
26+
27+
Map<String, MyConsumer> getGenericMap() {
28+
return genericMap;
29+
}
30+
31+
BiConsumer<MyA, MyB> getBiConsumer() {
32+
return biConsumer;
33+
}
34+
}

blackbox-test-inject/src/test/java/org/example/myapp/generic/GenericFactoryTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,14 @@ class GenericFactoryTest {
1212

1313
@Inject Generic<Integer> intymcintface;
1414
@Inject Generic<String> stringy;
15+
@Inject MyUseGenericDependencies others;
1516

1617
@Test
1718
void test() {
1819
assertThat(intymcintface).isNotNull();
1920
assertThat(stringy).isNotNull();
21+
assertThat(others.getAldrich()).isNotNull();
22+
assertThat(others.getGenericMap()).isNotNull();
23+
assertThat(others.getBiConsumer()).isNotNull();
2024
}
2125
}

inject-generator/src/main/java/io/avaje/inject/generator/TypeAppender.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.util.LinkedHashSet;
44
import java.util.List;
55
import java.util.Set;
6+
import java.util.stream.Stream;
67

78
import javax.lang.model.type.TypeKind;
89

@@ -21,22 +22,31 @@ final class TypeAppender {
2122

2223
void add(UType utype) {
2324
var type = Util.unwrapProvider(utype);
24-
var components = type.componentTypes();
25-
if (isAddGenericType(type, components)) {
25+
if (isAddGenericType(type)) {
2626
addUType(type);
2727
} else {
2828
addSimpleType(type.mainType());
2929
}
3030
}
3131

32-
private static boolean isAddGenericType(UType type, List<UType> components) {
32+
private static boolean isAddGenericType(UType type) {
33+
var components = type.componentTypes();
3334
return type.isGeneric()
3435
&& type.kind() != TypeKind.TYPEVAR
3536
&& (components.size() != 1 || components.get(0).kind() != TypeKind.WILDCARD)
3637
&& components.stream()
38+
.flatMap(TypeAppender::allComponentTypes)
3739
.noneMatch(u -> u.kind() == TypeKind.TYPEVAR || u.kind() == TypeKind.WILDCARD);
3840
}
3941

42+
private static Stream<UType> allComponentTypes(UType u) {
43+
final var componentTypes = u.componentTypes();
44+
return componentTypes.isEmpty()
45+
? Stream.of(u)
46+
: Stream.concat(
47+
Stream.of(u), componentTypes.stream().flatMap(TypeAppender::allComponentTypes));
48+
}
49+
4050
void add(List<UType> sourceTypes) {
4151
sourceTypes.forEach(this::add);
4252
}

inject-generator/src/test/java/io/avaje/inject/generator/models/valid/generic/MyConsumer.java

Lines changed: 0 additions & 12 deletions
This file was deleted.

inject-generator/src/test/java/io/avaje/inject/generator/models/valid/generic/MyConsumerFactory.java

Lines changed: 0 additions & 23 deletions
This file was deleted.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package io.avaje.inject.generator.models.valid.provider;
2+
3+
public class BProv<T> {
4+
5+
final T value;
6+
7+
public BProv(T value) {
8+
this.value = value;
9+
}
10+
11+
public T get() {
12+
return value;
13+
}
14+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package io.avaje.inject.generator.models.valid.provider;
2+
3+
import io.avaje.inject.Component;
4+
import jakarta.inject.Provider;
5+
6+
import java.util.concurrent.atomic.AtomicInteger;
7+
8+
@Component
9+
public class BProvProvider implements Provider<BProv<String>> {
10+
11+
AtomicInteger counter = new AtomicInteger();
12+
13+
@Override
14+
public BProv<String> get() {
15+
return new BProv<>("Hello BProv" + counter.incrementAndGet());
16+
}
17+
}

inject-test/src/test/java/org/example/coffee/provider/BProvProviderTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ void providerOfGenericType() {
1717
BProv<String> bProv2 = beanScope.get(BProvProvider$DI.TYPE_BProvString);
1818
assertThat(bProv).isNotSameAs(bProv2);
1919
assertThat(bProv2.get()).isEqualTo("Hello BProv2");
20+
21+
BProvUser bProvUser = beanScope.get(BProvUser.class);
22+
BProv<String> bProv3 = bProvUser.getProvider().get();
23+
assertThat(bProv3.get()).isEqualTo("Hello BProv3");
24+
assertThat(bProv).isNotSameAs(bProv3);
2025
}
2126
}
2227

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package org.example.coffee.provider;
2+
3+
import io.avaje.inject.Component;
4+
import jakarta.inject.Provider;
5+
6+
@Component
7+
class BProvUser {
8+
9+
private final Provider<BProv<String>> provider;
10+
11+
BProvUser(Provider<BProv<String>> provider){
12+
this.provider = provider;
13+
}
14+
15+
Provider<BProv<String>> getProvider() {
16+
return provider;
17+
}
18+
}

0 commit comments

Comments
 (0)