зеркало из https://github.com/mozilla/gecko-dev.git
Fixing bug 255549: proper resolution of overloaded methods.
This commit is contained in:
Родитель
0fa9344f94
Коммит
3a68eb5402
|
@ -254,130 +254,140 @@ public class NativeJavaMethod extends BaseFunction
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int bestFit = -1;
|
int firstBestFit = -1;
|
||||||
Class[] bestFitTypes = null;
|
int[] extraBestFits = null;
|
||||||
|
int extraBestFitsCount = 0;
|
||||||
int[] ambiguousMethods = null;
|
|
||||||
int ambiguousMethodCount = 0;
|
|
||||||
|
|
||||||
|
search:
|
||||||
for (int i = 0; i < methodsOrCtors.length; i++) {
|
for (int i = 0; i < methodsOrCtors.length; i++) {
|
||||||
MemberBox member = methodsOrCtors[i];
|
MemberBox member = methodsOrCtors[i];
|
||||||
Class[] argTypes = member.argTypes;
|
Class[] argTypes = member.argTypes;
|
||||||
if (argTypes.length != args.length) {
|
if (argTypes.length != args.length) {
|
||||||
continue;
|
continue search;
|
||||||
}
|
}
|
||||||
if (bestFit < 0) {
|
for (int j = 0; j < argTypes.length; j++) {
|
||||||
int j;
|
if (!NativeJavaObject.canConvert(args[j], argTypes[j])) {
|
||||||
for (j = 0; j < argTypes.length; j++) {
|
if (debug) printDebug("Rejecting (args can't convert) ",
|
||||||
if (!NativeJavaObject.canConvert(args[j], argTypes[j])) {
|
member, args);
|
||||||
if (debug) printDebug("Rejecting (args can't convert) ",
|
continue search;
|
||||||
member, args);
|
}
|
||||||
break;
|
}
|
||||||
|
if (firstBestFit < 0) {
|
||||||
|
if (debug) printDebug("Found first applicable ", member, args);
|
||||||
|
firstBestFit = i;
|
||||||
|
} else {
|
||||||
|
// Compare with all currently fit methods.
|
||||||
|
// The loop starts from -1 denoting firstBestFit and proceed
|
||||||
|
// until extraBestFitsCount to avoid extraBestFits allocation
|
||||||
|
// in the most common case of no ambiguity
|
||||||
|
int betterCount = 0; // number of times member was prefered over
|
||||||
|
// best fits
|
||||||
|
int worseCount = 0; // number of times best fits were prefered
|
||||||
|
// over member
|
||||||
|
for (int j = -1; j != extraBestFitsCount; ++j) {
|
||||||
|
int bestFitIndex;
|
||||||
|
if (j == -1) {
|
||||||
|
bestFitIndex = firstBestFit;
|
||||||
|
} else {
|
||||||
|
bestFitIndex = extraBestFits[j];
|
||||||
}
|
}
|
||||||
}
|
MemberBox bestFit = methodsOrCtors[bestFitIndex];
|
||||||
if (j == argTypes.length) {
|
int preference = preferSignature(args, argTypes,
|
||||||
if (debug) printDebug("Found ", member, args);
|
bestFit.argTypes);
|
||||||
bestFit = i;
|
if (preference == PREFERENCE_AMBIGUOUS) {
|
||||||
bestFitTypes = argTypes;
|
break;
|
||||||
}
|
} else if (preference == PREFERENCE_FIRST_ARG) {
|
||||||
}
|
++betterCount;
|
||||||
else {
|
} else if (preference == PREFERENCE_SECOND_ARG) {
|
||||||
int preference = preferSignature(args, argTypes,
|
++worseCount;
|
||||||
bestFitTypes);
|
} else {
|
||||||
if (preference == PREFERENCE_AMBIGUOUS) {
|
if (preference != PREFERENCE_EQUAL) Kit.codeBug();
|
||||||
if (debug) printDebug("Deferring ", member, args);
|
// This should not happen in theory
|
||||||
// add to "ambiguity list"
|
// but on some JVMs, Class.getMethods will return all
|
||||||
if (ambiguousMethods == null)
|
|
||||||
ambiguousMethods = new int[methodsOrCtors.length];
|
|
||||||
ambiguousMethods[ambiguousMethodCount++] = i;
|
|
||||||
} else if (preference == PREFERENCE_FIRST_ARG) {
|
|
||||||
if (debug) printDebug("Substituting ", member, args);
|
|
||||||
bestFit = i;
|
|
||||||
bestFitTypes = argTypes;
|
|
||||||
} else if (preference == PREFERENCE_SECOND_ARG) {
|
|
||||||
if (debug) printDebug("Rejecting ", member, args);
|
|
||||||
} else {
|
|
||||||
if (preference != PREFERENCE_EQUAL) Kit.codeBug();
|
|
||||||
MemberBox best = methodsOrCtors[bestFit];
|
|
||||||
if (best.isStatic()
|
|
||||||
&& best.getDeclaringClass().isAssignableFrom(
|
|
||||||
member.getDeclaringClass()))
|
|
||||||
{
|
|
||||||
// On some JVMs, Class.getMethods will return all
|
|
||||||
// static methods of the class heirarchy, even if
|
// static methods of the class heirarchy, even if
|
||||||
// a derived class's parameters match exactly.
|
// a derived class's parameters match exactly.
|
||||||
// We want to call the dervied class's method.
|
// We want to call the dervied class's method.
|
||||||
if (debug) printDebug(
|
if (bestFit.isStatic()
|
||||||
"Substituting (overridden static)", member, args);
|
&& bestFit.getDeclaringClass().isAssignableFrom(
|
||||||
bestFit = i;
|
member.getDeclaringClass()))
|
||||||
bestFitTypes = argTypes;
|
{
|
||||||
} else {
|
// On some JVMs, Class.getMethods will return all
|
||||||
if (debug) printDebug(
|
// static methods of the class heirarchy, even if
|
||||||
"Ignoring same signature member ", member, args);
|
// a derived class's parameters match exactly.
|
||||||
|
// We want to call the dervied class's method.
|
||||||
|
if (debug) printDebug(
|
||||||
|
"Substituting (overridden static)",
|
||||||
|
member, args);
|
||||||
|
if (j == -1) {
|
||||||
|
firstBestFit = i;
|
||||||
|
} else {
|
||||||
|
extraBestFits[j] = i;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (debug) printDebug(
|
||||||
|
"Ignoring same signature member ",
|
||||||
|
member, args);
|
||||||
|
}
|
||||||
|
continue search;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (betterCount == 1 + extraBestFitsCount) {
|
||||||
|
// member was prefered over all best fits
|
||||||
|
if (debug) printDebug(
|
||||||
|
"New first applicable ", member, args);
|
||||||
|
firstBestFit = i;
|
||||||
|
extraBestFitsCount = 0;
|
||||||
|
} else if (worseCount == 1 + extraBestFitsCount) {
|
||||||
|
// all best fits were prefered over member, ignore it
|
||||||
|
if (debug) printDebug(
|
||||||
|
"Rejecting (all current bests better) ", member, args);
|
||||||
|
} else {
|
||||||
|
// some ambiguity was present, add member to best fit set
|
||||||
|
if (debug) printDebug(
|
||||||
|
"Added to best fit set ", member, args);
|
||||||
|
if (extraBestFits == null) {
|
||||||
|
// Allocate maximum possible array
|
||||||
|
extraBestFits = new int[methodsOrCtors.length - 1];
|
||||||
|
}
|
||||||
|
extraBestFits[extraBestFitsCount] = i;
|
||||||
|
++extraBestFitsCount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ambiguousMethodCount == 0)
|
if (firstBestFit < 0) {
|
||||||
return bestFit;
|
// Nothing was found
|
||||||
|
return -1;
|
||||||
// Compare ambiguous methods with best fit, in case
|
} else if (extraBestFitsCount == 0) {
|
||||||
// the current best fit removes the ambiguities.
|
// single best fit
|
||||||
int removedCount = 0;
|
return firstBestFit;
|
||||||
for (int k = 0; k != ambiguousMethodCount; ++k) {
|
|
||||||
int i = ambiguousMethods[k];
|
|
||||||
MemberBox member = methodsOrCtors[i];
|
|
||||||
Class[] argTypes = member.argTypes;
|
|
||||||
int preference = preferSignature(args, argTypes,
|
|
||||||
bestFitTypes);
|
|
||||||
|
|
||||||
if (preference == PREFERENCE_FIRST_ARG) {
|
|
||||||
if (debug) printDebug("Substituting ", member, args);
|
|
||||||
bestFit = i;
|
|
||||||
bestFitTypes = argTypes;
|
|
||||||
ambiguousMethods[k] = -1;
|
|
||||||
++removedCount;
|
|
||||||
}
|
|
||||||
else if (preference == PREFERENCE_SECOND_ARG) {
|
|
||||||
if (debug) printDebug("Rejecting ", member, args);
|
|
||||||
ambiguousMethods[k] = -1;
|
|
||||||
++removedCount;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (debug) printDebug("UNRESOLVED: ", member, args);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (removedCount == ambiguousMethodCount) {
|
// report remaining ambiguity
|
||||||
return bestFit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// PENDING: report remaining ambiguity
|
|
||||||
StringBuffer buf = new StringBuffer();
|
StringBuffer buf = new StringBuffer();
|
||||||
|
for (int j = -1; j != extraBestFitsCount; ++j) {
|
||||||
ambiguousMethods[ambiguousMethodCount++] = bestFit;
|
int bestFitIndex;
|
||||||
boolean first = true;
|
if (j == -1) {
|
||||||
for (int k = 0; k < ambiguousMethodCount; k++) {
|
bestFitIndex = firstBestFit;
|
||||||
int i = ambiguousMethods[k];
|
} else {
|
||||||
if (i < 0) { continue; }
|
bestFitIndex = extraBestFits[j];
|
||||||
if (!first) {
|
|
||||||
buf.append(", ");
|
|
||||||
}
|
}
|
||||||
buf.append(methodsOrCtors[i].toJavaDeclaration());
|
buf.append("\n ");
|
||||||
first = false;
|
buf.append(methodsOrCtors[bestFitIndex].toJavaDeclaration());
|
||||||
}
|
}
|
||||||
|
|
||||||
MemberBox best = methodsOrCtors[bestFit];
|
MemberBox firstFitMember = methodsOrCtors[firstBestFit];
|
||||||
|
String memberName = firstFitMember.getName();
|
||||||
|
String memberClass = firstFitMember.getDeclaringClass().getName();
|
||||||
|
|
||||||
if (methodsOrCtors[0].isMethod()) {
|
if (methodsOrCtors[0].isMethod()) {
|
||||||
throw Context.reportRuntimeError3(
|
throw Context.reportRuntimeError3(
|
||||||
"msg.constructor.ambiguous",
|
"msg.constructor.ambiguous",
|
||||||
best.getName(), scriptSignature(args), buf.toString());
|
memberName, scriptSignature(args), buf.toString());
|
||||||
} else {
|
} else {
|
||||||
throw Context.reportRuntimeError4(
|
throw Context.reportRuntimeError4(
|
||||||
"msg.method.ambiguous", best.getDeclaringClass().getName(),
|
"msg.method.ambiguous", memberClass,
|
||||||
best.getName(), scriptSignature(args), buf.toString());
|
memberName, scriptSignature(args), buf.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,6 +478,7 @@ public class NativeJavaMethod extends BaseFunction
|
||||||
sb.append(" for arguments (");
|
sb.append(" for arguments (");
|
||||||
sb.append(scriptSignature(args));
|
sb.append(scriptSignature(args));
|
||||||
sb.append(')');
|
sb.append(')');
|
||||||
|
System.out.println(sb);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче