internal static int FindFunction(Context cx, MemberBox[] methodsOrCtors, object[] args)
{
if (methodsOrCtors.Length == 0)
{
return -1;
}
else
{
if (methodsOrCtors.Length == 1)
{
MemberBox member = methodsOrCtors[0];
Type[] argTypes = member.argTypes;
int alength = argTypes.Length;
if (member.vararg)
{
alength--;
if (alength > args.Length)
{
return -1;
}
}
else
{
if (alength != args.Length)
{
return -1;
}
}
for (int j = 0; j != alength; ++j)
{
if (!NativeJavaObject.CanConvert(args[j], argTypes[j]))
{
return -1;
}
}
return 0;
}
}
int firstBestFit = -1;
int[] extraBestFits = null;
int extraBestFitsCount = 0;
for (int i = 0; i < methodsOrCtors.Length; i++)
{
MemberBox member = methodsOrCtors[i];
Type[] argTypes = member.argTypes;
int alength = argTypes.Length;
if (member.vararg)
{
alength--;
if (alength > args.Length)
{
goto search_continue;
}
}
else
{
if (alength != args.Length)
{
goto search_continue;
}
}
for (int j = 0; j < alength; j++)
{
if (!NativeJavaObject.CanConvert(args[j], argTypes[j]))
{
goto search_continue;
}
}
if (firstBestFit < 0)
{
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 = -1; j_1 != extraBestFitsCount; ++j_1)
{
int bestFitIndex;
if (j_1 == -1)
{
bestFitIndex = firstBestFit;
}
else
{
bestFitIndex = extraBestFits[j_1];
}
MemberBox bestFit = methodsOrCtors[bestFitIndex];
if (cx.HasFeature(Context.FEATURE_ENHANCED_JAVA_ACCESS) && (bestFit.Member().Attributes & Modifier.PUBLIC) != (member.Member().Attributes & Modifier.PUBLIC))
{
// When FEATURE_ENHANCED_JAVA_ACCESS gives us access
// to non-public members, continue to prefer public
// methods in overloading
if ((bestFit.Member().Attributes & Modifier.PUBLIC) == 0)
{
++betterCount;
}
else
{
++worseCount;
}
}
else
{
int preference = PreferSignature(args, argTypes, member.vararg, bestFit.argTypes, bestFit.vararg);
if (preference == PREFERENCE_AMBIGUOUS)
{
break;
}
else
{
if (preference == PREFERENCE_FIRST_ARG)
{
++betterCount;
}
else
{
if (preference == PREFERENCE_SECOND_ARG)
{
++worseCount;
}
else
{
if (preference != PREFERENCE_EQUAL)
{
Kit.CodeBug();
}
// This should not happen in theory
// but on some JVMs, Class.getMethods will return all
// static methods of the class hierarchy, even if
// a derived class's parameters match exactly.
// We want to call the derived class's method.
if (bestFit.IsStatic() && bestFit.GetDeclaringClass().IsAssignableFrom(member.GetDeclaringClass()))
{
// On some JVMs, Class.getMethods will return all
// static methods of the class hierarchy, even if
// a derived class's parameters match exactly.
// We want to call the derived class's method.
if (j_1 == -1)
{
firstBestFit = i;
}
else
{
extraBestFits[j_1] = i;
}
}
goto search_continue;
}
}
}
}
}
if (betterCount == 1 + extraBestFitsCount)
{
// member was prefered over all best fits
firstBestFit = i;
extraBestFitsCount = 0;
}
else
{
if (worseCount == 1 + extraBestFitsCount)
{
}
else
{
// all best fits were prefered over member, ignore it
// some ambiguity was present, add member to best fit set
if (extraBestFits == null)
{
// Allocate maximum possible array
extraBestFits = new int[methodsOrCtors.Length - 1];
}
extraBestFits[extraBestFitsCount] = i;
++extraBestFitsCount;
}
}
}
search_continue: ;
}
search_break: ;
if (firstBestFit < 0)
{
// Nothing was found
return -1;
}
else
{
if (extraBestFitsCount == 0)
{
// single best fit
return firstBestFit;
}
}
// report remaining ambiguity
StringBuilder buf = new StringBuilder();
for (int j_2 = -1; j_2 != extraBestFitsCount; ++j_2)
{
int bestFitIndex;
if (j_2 == -1)
{
bestFitIndex = firstBestFit;
}
else
{
bestFitIndex = extraBestFits[j_2];
}
buf.Append("\n ");
buf.Append(methodsOrCtors[bestFitIndex].ToJavaDeclaration());
}
MemberBox firstFitMember = methodsOrCtors[firstBestFit];
string memberName = firstFitMember.GetName();
string memberClass = firstFitMember.GetDeclaringClass().FullName;
if (methodsOrCtors[0].IsCtor())
{
throw Context.ReportRuntimeError3("msg.constructor.ambiguous", memberName, ScriptSignature(args), buf.ToString());
}
else
{
throw Context.ReportRuntimeError4("msg.method.ambiguous", memberClass, memberName, ScriptSignature(args), buf.ToString());
}
}