Skip to content

Commit 94813aa

Browse files
authored
Merge pull request #384 from domaframework/issue-383
Resolve type parameters with actual type arguments for generic types
2 parents 2be1786 + ff7ef93 commit 94813aa

File tree

7 files changed

+82
-2
lines changed

7 files changed

+82
-2
lines changed

doma-core/src/main/java/org/seasar/doma/message/Message.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,8 @@ public enum Message implements MessageResource {
560560
"Failed to verify the SQL template \"{0}\" on line {2} at column {3}. "
561561
+ "The parameter type that corresponds to the expression \"{4}\" must be a subtype of either java.lang.Iterable or an array type. "
562562
+ "But the actual type is \"{5}\". "
563+
+ "If the actual type is a subtype of java.lang.Iterable, ensure that the type parameter or it is resolved with one of the supported types. "
564+
+ "If the actual type is an array type, ensure that the component type of it is one of the supported types. "
563565
+ "You may forget to access to its field or to invoke its method. SQL=[{1}]"),
564566
DOMA4163(
565567
"The user defined Config class must not be abstract. " + "The class \"{0}\" is abstract."),

doma-processor/src/main/java/org/seasar/doma/internal/apt/decl/Declarations.java

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,17 @@
55
import static org.seasar.doma.internal.util.AssertionUtil.assertNotNull;
66
import static org.seasar.doma.internal.util.AssertionUtil.assertTrue;
77

8-
import java.util.*;
9-
import javax.lang.model.element.*;
8+
import java.util.Collections;
9+
import java.util.LinkedHashMap;
10+
import java.util.List;
11+
import java.util.Map;
12+
import java.util.Optional;
13+
import java.util.stream.Collectors;
14+
import javax.lang.model.element.ElementKind;
15+
import javax.lang.model.element.ExecutableElement;
16+
import javax.lang.model.element.Name;
17+
import javax.lang.model.element.TypeElement;
18+
import javax.lang.model.element.VariableElement;
1019
import javax.lang.model.type.DeclaredType;
1120
import javax.lang.model.type.TypeKind;
1221
import javax.lang.model.type.TypeMirror;
@@ -124,6 +133,30 @@ private TypeMirror resolveTypeParameter(
124133
if (formalType.equals(typeParameterDecl.getFormalType())) {
125134
return typeParameterDecl.getActualType();
126135
}
136+
DeclaredType declaredType = ctx.getMoreTypes().toDeclaredType(formalType);
137+
if (declaredType == null) {
138+
continue;
139+
}
140+
if (declaredType.getTypeArguments().isEmpty()) {
141+
continue;
142+
}
143+
List<Optional<TypeMirror>> optTypeArgs =
144+
declaredType.getTypeArguments().stream()
145+
.map(
146+
arg ->
147+
typeParameterDeclarations.stream()
148+
.filter(declaration -> arg.equals(declaration.getFormalType()))
149+
.map(TypeParameterDeclaration::getActualType)
150+
.findFirst())
151+
.collect(Collectors.toList());
152+
if (optTypeArgs.stream().allMatch(Optional::isPresent)) {
153+
TypeMirror[] typeArgs = optTypeArgs.stream().map(Optional::get).toArray(TypeMirror[]::new);
154+
TypeElement typeElement = ctx.getMoreElements().toTypeElement(declaredType.asElement());
155+
if (typeElement == null) {
156+
continue;
157+
}
158+
return ctx.getMoreTypes().getDeclaredType(typeElement, typeArgs);
159+
}
127160
}
128161
return formalType;
129162
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
package org.seasar.doma.internal.apt.validator;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
public class AbstractCriteria<T> {
7+
private List<T> list = new ArrayList<>();
8+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package org.seasar.doma.internal.apt.validator;
2+
3+
public class CriteriaHolder {
4+
private LongCriteria criteria = new LongCriteria();
5+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package org.seasar.doma.internal.apt.validator;
2+
3+
public class LongCriteria extends AbstractCriteria<Long> {}

doma-processor/src/test/java/org/seasar/doma/internal/apt/validator/SqlValidationDao.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,6 @@ public interface SqlValidationDao {
2929
void testExpand(String name);
3030

3131
void testPopulate(String name);
32+
33+
void testTypeParameterResolution(CriteriaHolder criteriaHolder);
3234
}

doma-processor/src/test/java/org/seasar/doma/internal/apt/validator/SqlValidatorTest.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,33 @@ void beforeEach() {
2525
addSourcePath("src/main/java");
2626
}
2727

28+
@Test
29+
void testFormalTypeParameterResolution() throws Exception {
30+
Class<?> target = SqlValidationDao.class;
31+
addCompilationUnit(target);
32+
addProcessor(
33+
new TestProcessor() {
34+
@Override
35+
protected void run() {
36+
ExecutableElement methodElement =
37+
createMethodElement(target, "testTypeParameterResolution", CriteriaHolder.class);
38+
LinkedHashMap<String, TypeMirror> parameterTypeMap =
39+
createParameterTypeMap(methodElement);
40+
41+
SqlValidator validator =
42+
new SqlValidator(
43+
ctx, methodElement, parameterTypeMap, "aaa/bbbDao/ccc.sql", false, false);
44+
SqlParser parser =
45+
new SqlParser(
46+
"select * from emp where name in /* criteriaHolder.criteria.list */(0)");
47+
SqlNode sqlNode = parser.parse();
48+
sqlNode.accept(validator, null);
49+
}
50+
});
51+
compile();
52+
assertTrue(getCompiledResult());
53+
}
54+
2855
@Test
2956
void testBindVariable() throws Exception {
3057
Class<?> target = SqlValidationDao.class;

0 commit comments

Comments
 (0)