|
24 | 24 | import spoon.reflect.declaration.CtParameter; |
25 | 25 | import spoon.reflect.declaration.CtType; |
26 | 26 | import spoon.reflect.factory.Factory; |
| 27 | +import spoon.reflect.reference.CtTypeParameterReference; |
27 | 28 | import spoon.reflect.reference.CtTypeReference; |
28 | 29 |
|
29 | 30 | public class ExternalRefinementTypeChecker extends TypeChecker { |
@@ -66,10 +67,13 @@ public <T> void visitCtField(CtField<T> f) { |
66 | 67 |
|
67 | 68 | public <R> void visitCtMethod(CtMethod<R> method) { |
68 | 69 | CtType<?> targetType = factory.Type().createReference(prefix).getTypeDeclaration(); |
69 | | - if (!(targetType instanceof CtClass)) |
| 70 | + if (!(targetType instanceof CtClass) && !(targetType instanceof CtInterface)) |
70 | 71 | return; |
71 | 72 |
|
72 | | - boolean isConstructor = method.getSimpleName().equals(targetType.getSimpleName()); |
| 73 | + // Interfaces have no constructors; only a class can declare one, so the constructor-name shortcut |
| 74 | + // (a refinement method named like the target type) only applies to class targets. |
| 75 | + boolean isConstructor = targetType instanceof CtClass |
| 76 | + && method.getSimpleName().equals(targetType.getSimpleName()); |
73 | 77 | if (isConstructor) { |
74 | 78 | if (!constructorExists(targetType, method)) { |
75 | 79 | String signature = method.getSignature(); |
@@ -149,9 +153,18 @@ private boolean typesMatch(CtTypeReference<?> type1, CtTypeReference<?> type2) { |
149 | 153 | if (type1 == null || type2 == null) |
150 | 154 | return false; |
151 | 155 |
|
| 156 | + // Type variables (generics such as E, N, T) carry different names in the JDK type |
| 157 | + if (type1 instanceof CtTypeParameterReference t1 && type2 instanceof CtTypeParameterReference t2) |
| 158 | + return boundName(t1).equals(boundName(t2)); |
| 159 | + |
152 | 160 | return type1.getQualifiedName().equals(type2.getQualifiedName()); |
153 | 161 | } |
154 | 162 |
|
| 163 | + private static String boundName(CtTypeParameterReference ref) { |
| 164 | + CtTypeReference<?> bound = ref.getBoundingType(); |
| 165 | + return bound == null ? "java.lang.Object" : bound.getQualifiedName(); |
| 166 | + } |
| 167 | + |
155 | 168 | private boolean parametersMatch(List<?> targetParams, List<?> refinementParams) { |
156 | 169 | if (targetParams.size() != refinementParams.size()) |
157 | 170 | return false; |
|
0 commit comments