View | Details | Raw Unified | Return to bug 174588 | Differences between
and this patch

Collapse All | Expand All

(-)compiler/org/eclipse/jdt/internal/compiler/lookup/Scope.java (-35 / +52 lines)
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
	}

Return to bug 174588