/// <summary> Determine which of two signatures is the closer fit. /// Returns one of PREFERENCE_EQUAL, PREFERENCE_FIRST_ARG, /// PREFERENCE_SECOND_ARG, or PREFERENCE_AMBIGUOUS. /// </summary> private static int PreferSignature(object [] args, ParameterInfo [] sig1, ParameterInfo [] sig2) { int totalPreference = 0; for (int j = 0; j < args.Length; j++) { Type type1 = sig1 [j].ParameterType; Type type2 = sig2 [j].ParameterType; if (type1 == type2) { continue; } object arg = args [j]; // Determine which of type1, type2 is easier to convert from arg. int rank1 = CliObject.GetConversionWeight(arg, type1); int rank2 = CliObject.GetConversionWeight(arg, type2); int preference; if (rank1 < rank2) { preference = PREFERENCE_FIRST_ARG; } else if (rank1 > rank2) { preference = PREFERENCE_SECOND_ARG; } else { // Equal ranks if (rank1 == CliObject.CONVERSION_NONTRIVIAL) { if (type1.IsAssignableFrom(type2)) { preference = PREFERENCE_SECOND_ARG; } else if (type2.IsAssignableFrom(type1)) { preference = PREFERENCE_FIRST_ARG; } else { preference = PREFERENCE_AMBIGUOUS; } } else { preference = PREFERENCE_AMBIGUOUS; } } totalPreference |= preference; if (totalPreference == PREFERENCE_AMBIGUOUS) { break; } } return(totalPreference); }
private void Init() { m_CliObject = new CliObject(m_Type, m_Type); }
/// <summary> 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. /// </summary> internal static int FindFunction(Context cx, MethodBase [] methodsOrCtors, object [] args, bool [] paramsParameter) { if (methodsOrCtors.Length == 0) { return(-1); } else if (methodsOrCtors.Length == 1) { MethodBase member = methodsOrCtors [0]; ParameterInfo [] pis = member.GetParameters(); int alength = pis.Length; if (alength != args.Length) { if (!paramsParameter [0]) { return(-1); } } for (int j = 0; j != alength; ++j) { object arg = args [j]; Type argType = null; if (paramsParameter [0] && j >= pis.Length - 1) { // params[] arg is always an array type argType = pis [pis.Length - 1].ParameterType.GetElementType(); } else { argType = pis [j].ParameterType; } if (!CliObject.CanConvert(arg, argType)) { //if (debug) // printDebug("Rejecting (args can't convert) ", member, args); return(-1); } } //if (debug) // printDebug("Found ", member, args); return(0); } int firstBestFit = -1; int [] extraBestFits = null; int extraBestFitsCount = 0; for (int i = 0; i < methodsOrCtors.Length; i++) { MethodBase member = methodsOrCtors [i]; ParameterInfo [] pis = member.GetParameters(); if (pis.Length != args.Length) { goto search; } for (int j = 0; j < pis.Length; j++) { if (!CliObject.CanConvert(args [j], pis [j].ParameterType)) { //if (debug) // printDebug("Rejecting (args can't convert) ", member, args); goto search; } } 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]; } MethodBase bestFit = methodsOrCtors [bestFitIndex]; int preference = PreferSignature(args, pis, bestFit.GetParameters()); if (preference == PREFERENCE_AMBIGUOUS) { break; } else if (preference == PREFERENCE_FIRST_ARG) { ++betterCount; } else if (preference == PREFERENCE_SECOND_ARG) { ++worseCount; } else { if (preference != PREFERENCE_EQUAL) { Context.CodeBug(); } // This should not happen in theory // but on some JVMs, Class.getMethods will return all // static methods of the class heirarchy, even if // a derived class's parameters match exactly. // We want to call the dervied class's method. if (bestFit.IsStatic && bestFit.DeclaringType.IsAssignableFrom(member.DeclaringType)) { // On some JVMs, Class.getMethods will return all // static methods of the class heirarchy, even if // 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); } goto 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; } } //UPGRADE_NOTE: Label 'search' was moved. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1014_3"' search: ; } if (firstBestFit < 0) { // Nothing was found return(-1); } else if (extraBestFitsCount == 0) { // single best fit return(firstBestFit); } // report remaining ambiguity System.Text.StringBuilder buf = new System.Text.StringBuilder(); for (int j = -1; j != extraBestFitsCount; ++j) { int bestFitIndex; if (j == -1) { bestFitIndex = firstBestFit; } else { bestFitIndex = extraBestFits [j]; } buf.Append("\n "); buf.Append(CliHelper.ToSignature(methodsOrCtors [bestFitIndex])); } MethodBase firstFitMember = methodsOrCtors [firstBestFit]; string memberName = firstFitMember.Name; //UPGRADE_TODO: The equivalent in .NET for method 'java.lang.Class.getName' may return a different value. 'ms-help://MS.VSCC.2003/commoner/redir/redirect.htm?keyword="jlca1043_3"' string memberClass = firstFitMember.DeclaringType.FullName; if (methodsOrCtors [0] is MethodInfo) { throw Context.ReportRuntimeErrorById("msg.constructor.ambiguous", memberName, ScriptSignature(args), buf.ToString()); } else { throw Context.ReportRuntimeErrorById("msg.method.ambiguous", memberClass, memberName, ScriptSignature(args), buf.ToString()); } }
private void Init() { m_CliObject = new CliObject (m_Type, m_Type); }