Rhino.NativeJavaMethod.FindFunction C# (CSharp) Method

FindFunction() static private method

Find the index of the correct function to call given the set of methods or constructors and the arguments.
Find the index of the correct function to call given the set of methods or constructors and the arguments. If no function can be found to call, return -1.
static private FindFunction ( Context cx, MemberBox methodsOrCtors, object args ) : int
cx Context
methodsOrCtors MemberBox
args object
return int
		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());
			}
		}