Skip to content

Commit d1163e4

Browse files
committed
#139 - Support types implementing interfaces with parameter type T etc (currently produces compile error)
1 parent bde60e5 commit d1163e4

File tree

8 files changed

+93
-15
lines changed

8 files changed

+93
-15
lines changed

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ static GenericType parse(String raw) {
4242
return new GenericTypeParser(raw).parse();
4343
}
4444

45+
/**
46+
* Parse and return the main type if it contains a type parameter like {@code <T>}.
47+
*/
48+
static String removeParameter(String raw) {
49+
final GenericType type = parse(raw);
50+
return type.hasParameter() ? type.getMainType() : raw;
51+
}
52+
4553
/**
4654
* Parse and return as GenericType or null if it is not generic.
4755
*/
@@ -54,6 +62,21 @@ public String toString() {
5462
return raw != null ? raw : mainType + '<' + params + '>';
5563
}
5664

65+
/**
66+
* Return true if the type contains a type parameter like {@code <T>}.
67+
*/
68+
boolean hasParameter() {
69+
if (mainType != null && mainType.indexOf('.') == -1) {
70+
return true;
71+
}
72+
for (GenericType param : params) {
73+
if (param.hasParameter()) {
74+
return true;
75+
}
76+
}
77+
return false;
78+
}
79+
5780
void addImports(Set<String> importTypes) {
5881
final String type = trimExtends();
5982
if (includeInImports(type)) {

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ class GenericTypeParser {
1616
}
1717

1818
GenericType parse() {
19-
2019
int len = raw.length();
2120
for (int i = 0; i < len; i++) {
2221
char ch = raw.charAt(i);

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ private void readInterfaces(TypeElement type) {
124124
} else if (Constants.AUTO_CLOSEABLE.equals(rawType) || Constants.IO_CLOSEABLE.equals(rawType)) {
125125
closeable = true;
126126
} else {
127+
rawType = GenericType.removeParameter(rawType);
127128
if (qualifierName == null) {
128129
final String iShortName = Util.shortName(rawType);
129130
if (beanSimpleName.endsWith(iShortName)) {

inject-generator/src/test/java/io/avaje/inject/generator/GenericTypeTest.java

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,24 @@
88
import static org.junit.jupiter.api.Assertions.assertFalse;
99
import static org.junit.jupiter.api.Assertions.assertTrue;
1010

11-
public class GenericTypeTest {
11+
class GenericTypeTest {
1212

1313
@Test
14-
public void isGeneric() {
14+
void isGeneric() {
1515

1616
assertFalse(GenericType.isGeneric("java.lang.List"));
1717
assertTrue(GenericType.isGeneric("java.lang.List<Foo>"));
1818
}
1919

2020
@Test
21-
public void maybe() {
21+
void maybe() {
2222

2323
assertThat(GenericType.maybe("java.lang.List<Foo>").getMainType()).isEqualTo("java.lang.List");
2424
assertThat(GenericType.maybe("java.lang.List")).isNull();
2525
}
2626

2727
@Test
28-
public void parse() {
28+
void parse() {
2929

3030
GenericType type = new GenericTypeParser("my.exa.Repo<T,K>").parse();
3131

@@ -36,8 +36,7 @@ public void parse() {
3636
}
3737

3838
@Test
39-
public void parse_withParams() {
40-
39+
void parse_withParams() {
4140

4241
GenericType type = GenericType.parse("my.exa.Repo<my.d.Haz,java.lang.Long>");
4342

@@ -48,7 +47,7 @@ public void parse_withParams() {
4847
}
4948

5049
@Test
51-
public void parse_withExtendsParams() {
50+
void parse_withExtendsParams() {
5251

5352
GenericType type = new GenericTypeParser("my.exa.Repo<? extends my.d.Haz,java.lang.Long>").parse();
5453

@@ -58,9 +57,8 @@ public void parse_withExtendsParams() {
5857
assertThat(type.getParams().get(1).getMainType()).isEqualTo("java.lang.Long");
5958
}
6059

61-
6260
@Test
63-
public void parse_withNestedParams() {
61+
void parse_withNestedParams() {
6462

6563
GenericType type = new GenericTypeParser("my.exa.Repo<my.a.Prov<my.b.Haz>,my.a.Key<java.util.UUID>>").parse();
6664

@@ -76,13 +74,29 @@ public void parse_withNestedParams() {
7674
}
7775

7876
@Test
79-
public void shortName() {
77+
void shortName() {
8078
assertThat(GenericType.parse("java.lang.List<Foo>").shortName()).isEqualTo("ListFoo");
8179
assertThat(GenericType.parse("java.lang.List<org.Foo<com.Bar>>").shortName()).isEqualTo("ListFooBar");
8280
}
8381

8482
@Test
85-
public void write() {
83+
void hasParameter() {
84+
assertThat(GenericType.parse("java.lang.List<T>").hasParameter()).isTrue();
85+
assertThat(GenericType.parse("java.lang.List<org.Foo<TYPE>").hasParameter()).isTrue();
86+
assertThat(GenericType.parse("java.lang.List<org.Foo<com.Bar>>").hasParameter()).isFalse();
87+
}
88+
89+
@Test
90+
void removeParameter() {
91+
assertThat(GenericType.removeParameter("java.lang.List<T>")).isEqualTo("java.lang.List");
92+
assertThat(GenericType.removeParameter("java.lang.List<org.Foo<T>>")).isEqualTo("java.lang.List");
93+
assertThat(GenericType.removeParameter("java.lang.List<org.Foo<TYPE>>")).isEqualTo("java.lang.List");
94+
assertThat(GenericType.removeParameter("face.FaceParam<T>")).isEqualTo("face.FaceParam");
95+
assertThat(GenericType.removeParameter("java.lang.List<org.Foo<com.Bar>>")).isEqualTo("java.lang.List<org.Foo<com.Bar>>");
96+
}
97+
98+
@Test
99+
void write() {
86100

87101
GenericType type = new GenericTypeParser("my.exa.Repo<my.a.Prov<my.b.Haz>,my.a.Key<java.util.UUID>>").parse();
88102

inject-test/src/test/java/org/example/coffee/CoffeeMakerTest.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@
99
import org.example.coffee.list.Somei;
1010
import org.example.coffee.provider.AProv;
1111
import org.example.coffee.provider.AProvProvider;
12-
import org.example.iface.ConcreteExtend;
13-
import org.example.iface.IfaceExtend;
14-
import org.example.iface.IfaseBase;
12+
import org.example.iface.*;
1513
import org.example.inherit.*;
1614
import org.junit.jupiter.api.Test;
1715

@@ -121,6 +119,22 @@ public void beanScope_all_includesGenericInterfaces() {
121119
}
122120
}
123121

122+
@Test
123+
public void beanScope_all_interfaceWithParameter() {
124+
try (BeanScope context = BeanScope.newBuilder().build()) {
125+
126+
final List<BeanEntry> beanEntries = context.all();
127+
128+
final BeanEntry hazRepo = beanEntries.stream()
129+
.filter(e -> e.hasKey(MyParam.class))
130+
.findFirst().orElse(null);
131+
132+
assertThat(hazRepo.keys())
133+
.containsExactly(name(MyParam.class), name(IfaceParam.class), name(IfaceParamParent.class));
134+
}
135+
}
136+
137+
124138
@Test
125139
public void beanScope_all_provider() {
126140
try (BeanScope context = BeanScope.newBuilder().build()) {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.example.iface;
2+
3+
/**
4+
* Interface with type parameter T.
5+
*/
6+
public interface IfaceParam<T> extends IfaceParamParent {
7+
8+
T param();
9+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package org.example.iface;
2+
3+
public interface IfaceParamParent {
4+
5+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package org.example.iface;
2+
3+
4+
import jakarta.inject.Singleton;
5+
6+
@Singleton
7+
public class MyParam<T> implements IfaceParam<T> {
8+
9+
@Override
10+
public T param() {
11+
return null;
12+
}
13+
}

0 commit comments

Comments
 (0)