Lines 1035-1050
Link Here
|
1035 |
// Internal use only - use findMethod() |
1035 |
// Internal use only - use findMethod() |
1036 |
public MethodBinding findMethod(ReferenceBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) { |
1036 |
public MethodBinding findMethod(ReferenceBinding receiverType, char[] selector, TypeBinding[] argumentTypes, InvocationSite invocationSite) { |
1037 |
ReferenceBinding currentType = receiverType; |
1037 |
ReferenceBinding currentType = receiverType; |
|
|
1038 |
boolean receiverTypeIsInterface = receiverType.isInterface(); |
1038 |
ObjectVector found = new ObjectVector(3); |
1039 |
ObjectVector found = new ObjectVector(3); |
1039 |
CompilationUnitScope unitScope = compilationUnitScope(); |
1040 |
CompilationUnitScope unitScope = compilationUnitScope(); |
1040 |
unitScope.recordTypeReferences(argumentTypes); |
1041 |
unitScope.recordTypeReferences(argumentTypes); |
1041 |
|
1042 |
|
1042 |
if (currentType.isInterface()) { |
1043 |
if (receiverTypeIsInterface) { |
1043 |
unitScope.recordTypeReference(currentType); |
1044 |
unitScope.recordTypeReference(receiverType); |
1044 |
MethodBinding[] currentMethods = currentType.getMethods(selector); |
1045 |
MethodBinding[] receiverMethods = receiverType.getMethods(selector); |
1045 |
if (currentMethods.length > 0) |
1046 |
if (receiverMethods.length > 0) |
1046 |
found.addAll(currentMethods); |
1047 |
found.addAll(receiverMethods); |
1047 |
findMethodInSuperInterfaces(currentType, selector, found); |
1048 |
findMethodInSuperInterfaces(receiverType, selector, found); |
1048 |
currentType = getJavaLangObject(); |
1049 |
currentType = getJavaLangObject(); |
1049 |
} |
1050 |
} |
1050 |
|
1051 |
|
Lines 1053-1069
Link Here
|
1053 |
boolean isCompliant14 = complianceLevel >= ClassFileConstants.JDK1_4; |
1054 |
boolean isCompliant14 = complianceLevel >= ClassFileConstants.JDK1_4; |
1054 |
boolean isCompliant15 = complianceLevel >= ClassFileConstants.JDK1_5; |
1055 |
boolean isCompliant15 = complianceLevel >= ClassFileConstants.JDK1_5; |
1055 |
ReferenceBinding classHierarchyStart = currentType; |
1056 |
ReferenceBinding classHierarchyStart = currentType; |
1056 |
boolean mustBePublic = receiverType.isInterface(); |
|
|
1057 |
while (currentType != null) { |
1057 |
while (currentType != null) { |
1058 |
unitScope.recordTypeReference(currentType); |
1058 |
unitScope.recordTypeReference(currentType); |
1059 |
MethodBinding[] currentMethods = currentType.getMethods(selector); |
1059 |
MethodBinding[] currentMethods = currentType.getMethods(selector); |
1060 |
int currentLength = currentMethods.length; |
1060 |
int currentLength = currentMethods.length; |
1061 |
if (currentLength > 0) { |
1061 |
if (currentLength > 0) { |
1062 |
if (isCompliant14 && (mustBePublic || found.size > 0)) { |
1062 |
if (isCompliant14 && (receiverTypeIsInterface || found.size > 0)) { |
1063 |
nextMethod: for (int i = 0, l = currentLength; i < l; i++) { // currentLength can be modified inside the loop |
1063 |
nextMethod: for (int i = 0, l = currentLength; i < l; i++) { // currentLength can be modified inside the loop |
1064 |
MethodBinding currentMethod = currentMethods[i]; |
1064 |
MethodBinding currentMethod = currentMethods[i]; |
1065 |
if (currentMethod == null) continue nextMethod; |
1065 |
if (currentMethod == null) continue nextMethod; |
1066 |
if (mustBePublic && !currentMethod.isPublic()) { // only public methods from Object are visible to interface receiverTypes |
1066 |
if (receiverTypeIsInterface && !currentMethod.isPublic()) { // only public methods from Object are visible to interface receiverTypes |
1067 |
currentLength--; |
1067 |
currentLength--; |
1068 |
currentMethods[i] = null; |
1068 |
currentMethods[i] = null; |
1069 |
continue nextMethod; |
1069 |
continue nextMethod; |
Lines 1114-1119
Link Here
|
1114 |
MethodBinding[] candidates = null; |
1114 |
MethodBinding[] candidates = null; |
1115 |
int candidatesCount = 0; |
1115 |
int candidatesCount = 0; |
1116 |
MethodBinding problemMethod = null; |
1116 |
MethodBinding problemMethod = null; |
|
|
1117 |
boolean searchForDefaultAbstractMethod = isCompliant14 && ! receiverTypeIsInterface && (receiverType.isAbstract() || receiverType.isTypeVariable()); |
1117 |
if (foundSize > 0) { |
1118 |
if (foundSize > 0) { |
1118 |
// argument type compatibility check |
1119 |
// argument type compatibility check |
1119 |
for (int i = 0; i < foundSize; i++) { |
1120 |
for (int i = 0; i < foundSize; i++) { |
Lines 1123-1129
Link Here
|
1123 |
if (compatibleMethod.isValidBinding()) { |
1124 |
if (compatibleMethod.isValidBinding()) { |
1124 |
if (foundSize == 1 && compatibleMethod.canBeSeenBy(receiverType, invocationSite, this)) { |
1125 |
if (foundSize == 1 && compatibleMethod.canBeSeenBy(receiverType, invocationSite, this)) { |
1125 |
// return the single visible match now |
1126 |
// return the single visible match now |
1126 |
if (isCompliant14 && (receiverType.isAbstract() || receiverType.isTypeVariable())) |
1127 |
if (searchForDefaultAbstractMethod) |
1127 |
return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, compatibleMethod); |
1128 |
return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, compatibleMethod); |
1128 |
unitScope.recordTypeReferences(compatibleMethod.thrownExceptions); |
1129 |
unitScope.recordTypeReferences(compatibleMethod.thrownExceptions); |
1129 |
return compatibleMethod; |
1130 |
return compatibleMethod; |
Lines 1138-1152
Link Here
|
1138 |
} |
1139 |
} |
1139 |
} |
1140 |
} |
1140 |
|
1141 |
|
1141 |
// no match was found, try to find a close match when the parameter order is wrong or missing some parameters |
1142 |
// no match was found |
1142 |
if (candidatesCount == 0) { |
1143 |
if (candidatesCount == 0) { |
1143 |
// reduces secondary errors since missing interface method error is already reported |
1144 |
// abstract classes may get a match in interfaces; for non abstract |
|
|
1145 |
// classes, reduces secondary errors since missing interface method |
1146 |
// error is already reported |
1144 |
MethodBinding interfaceMethod = |
1147 |
MethodBinding interfaceMethod = |
1145 |
findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, null); |
1148 |
findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, null); |
1146 |
if (interfaceMethod != null) return interfaceMethod; |
1149 |
if (interfaceMethod != null) return interfaceMethod; |
1147 |
if (found.size == 0) return null; |
1150 |
if (found.size == 0) return null; |
1148 |
if (problemMethod != null) return problemMethod; |
1151 |
if (problemMethod != null) return problemMethod; |
1149 |
|
1152 |
|
|
|
1153 |
// still no match; try to find a close match when the parameter |
1154 |
// order is wrong or missing some parameters |
1155 |
|
1150 |
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=69471 |
1156 |
// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=69471 |
1151 |
// bad guesses are foo(), when argument types have been supplied |
1157 |
// bad guesses are foo(), when argument types have been supplied |
1152 |
// and foo(X, Y), when the argument types are (int, float, Y) |
1158 |
// and foo(X, Y), when the argument types are (int, float, Y) |
Lines 1186-1213
Link Here
|
1186 |
|
1192 |
|
1187 |
// tiebreak using visibility check |
1193 |
// tiebreak using visibility check |
1188 |
int visiblesCount = 0; |
1194 |
int visiblesCount = 0; |
1189 |
for (int i = 0; i < candidatesCount; i++) { |
1195 |
if (receiverTypeIsInterface) { |
1190 |
MethodBinding methodBinding = candidates[i]; |
1196 |
if (candidatesCount == 1) { |
1191 |
if (methodBinding.canBeSeenBy(receiverType, invocationSite, this)) { |
1197 |
unitScope.recordTypeReferences(candidates[0].thrownExceptions); |
1192 |
if (visiblesCount != i) { |
1198 |
return candidates[0]; |
1193 |
candidates[i] = null; |
1199 |
} |
1194 |
candidates[visiblesCount] = methodBinding; |
1200 |
visiblesCount = candidatesCount; |
|
|
1201 |
} else { |
1202 |
for (int i = 0; i < candidatesCount; i++) { |
1203 |
MethodBinding methodBinding = candidates[i]; |
1204 |
if (methodBinding.canBeSeenBy(receiverType, invocationSite, this)) { |
1205 |
if (visiblesCount != i) { |
1206 |
candidates[i] = null; |
1207 |
candidates[visiblesCount] = methodBinding; |
1208 |
} |
1209 |
visiblesCount++; |
1195 |
} |
1210 |
} |
1196 |
visiblesCount++; |
|
|
1197 |
} |
1211 |
} |
|
|
1212 |
if (visiblesCount == 1) { |
1213 |
if (searchForDefaultAbstractMethod) |
1214 |
return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, candidates[0]); |
1215 |
unitScope.recordTypeReferences(candidates[0].thrownExceptions); |
1216 |
return candidates[0]; |
1217 |
} |
1218 |
if (visiblesCount == 0) { |
1219 |
MethodBinding interfaceMethod = |
1220 |
findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, null); |
1221 |
if (interfaceMethod != null) return interfaceMethod; |
1222 |
return new ProblemMethodBinding(candidates[0], candidates[0].selector, candidates[0].parameters, ProblemReasons.NotVisible); |
1223 |
} |
1198 |
} |
1224 |
} |
1199 |
if (visiblesCount == 1) { |
|
|
1200 |
if (isCompliant14 && (receiverType.isAbstract() || receiverType.isTypeVariable())) |
1201 |
return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, candidates[0]); |
1202 |
unitScope.recordTypeReferences(candidates[0].thrownExceptions); |
1203 |
return candidates[0]; |
1204 |
} |
1205 |
if (visiblesCount == 0) { |
1206 |
MethodBinding interfaceMethod = |
1207 |
findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, null); |
1208 |
if (interfaceMethod != null) return interfaceMethod; |
1209 |
return new ProblemMethodBinding(candidates[0], candidates[0].selector, candidates[0].parameters, ProblemReasons.NotVisible); |
1210 |
} |
1211 |
|
1225 |
|
1212 |
if (complianceLevel <= ClassFileConstants.JDK1_3) { |
1226 |
if (complianceLevel <= ClassFileConstants.JDK1_3) { |
1213 |
ReferenceBinding declaringClass = candidates[0].declaringClass; |
1227 |
ReferenceBinding declaringClass = candidates[0].declaringClass; |
Lines 1230-1240
Link Here
|
1230 |
} |
1244 |
} |
1231 |
|
1245 |
|
1232 |
MethodBinding mostSpecificMethod = mostSpecificMethodBinding(candidates, visiblesCount, argumentTypes, invocationSite, receiverType); |
1246 |
MethodBinding mostSpecificMethod = mostSpecificMethodBinding(candidates, visiblesCount, argumentTypes, invocationSite, receiverType); |
1233 |
if (isCompliant15 |
1247 |
if (searchForDefaultAbstractMethod) { // search interfaces for a better match |
1234 |
&& mostSpecificMethod.isValidBinding() |
1248 |
if (mostSpecificMethod.isValidBinding()) |
1235 |
&& parameterCompatibilityLevel(mostSpecificMethod, argumentTypes) > COMPATIBLE) { |
1249 |
// see if there is a better match in the interfaces - see AutoBoxingTest 99, LookupTest#81 |
1236 |
// see if there is a better match in the interfaces - see AutoBoxingTest 99 |
|
|
1237 |
return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, mostSpecificMethod); |
1250 |
return findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, mostSpecificMethod); |
|
|
1251 |
// see if there is a match in the interfaces - see LookupTest#84 |
1252 |
MethodBinding interfaceMethod = findDefaultAbstractMethod(receiverType, selector, argumentTypes, invocationSite, classHierarchyStart, found, null); |
1253 |
if (interfaceMethod != null && interfaceMethod.isValidBinding() /* else return the same error as before */) |
1254 |
return interfaceMethod; |
1238 |
} |
1255 |
} |
1239 |
return mostSpecificMethod; |
1256 |
return mostSpecificMethod; |
1240 |
} |
1257 |
} |