private void WriteType(IReturnType rt) { if (rt == null) { _writer.Write(NullRTReferenceCode); return; } if (rt.IsDefaultReturnType) { string name = rt.FullyQualifiedName; if (name == "System.Void") { _writer.Write(VoidRTCode); } else { _writer.Write(_classIndices[new ClassNameTypeCountPair(rt)]); } } else if (rt.IsGenericReturnType) { GenericReturnType grt = rt.CastToGenericReturnType(); if (grt.TypeParameter.Method != null) { _writer.Write(MethodGenericRTCode); } else { _writer.Write(TypeGenericRTCode); } _writer.Write(grt.TypeParameter.Index); } else if (rt.IsArrayReturnType) { _writer.Write(ArrayRTCode); _writer.Write(rt.CastToArrayReturnType().ArrayDimensions); WriteType(rt.CastToArrayReturnType().ArrayElementType); } else if (rt.IsConstructedReturnType) { ConstructedReturnType crt = rt.CastToConstructedReturnType(); _writer.Write(ConstructedRTCode); WriteType(crt.UnboundType); _writer.Write((byte)crt.TypeArguments.Count); foreach (IReturnType typeArgument in crt.TypeArguments) { WriteType(typeArgument); } } else { _writer.Write(NullRTReferenceCode); LoggingService.Warn("Unknown return type: " + rt.ToString()); } }
/// <summary> /// Gets the common base type of a and b. /// </summary> public static IReturnType GetCommonType(IProjectContent projectContent, IReturnType a, IReturnType b) { if (projectContent == null) { throw new ArgumentNullException("projectContent"); } if (a == null) { return(b); } if (b == null) { return(a); } if (ConversionExists(a, b)) { return(b); } if (ConversionExists(b, a)) { return(a); } IClass c = a.GetUnderlyingClass(); if (c != null) { foreach (IClass baseClass in c.ClassInheritanceTree) { IReturnType baseType = baseClass.DefaultReturnType; if (baseClass.TypeParameters.Count > 0) { IReturnType[] typeArguments = new IReturnType[baseClass.TypeParameters.Count]; for (int i = 0; i < typeArguments.Length; i++) { typeArguments[i] = GetTypeParameterPassedToBaseClass(a, baseClass, i); } baseType = new ConstructedReturnType(baseType, typeArguments); } if (ConversionExists(b, baseType)) { return(baseType); } } } return(projectContent.SystemTypes.Object); }
static void TryAddExtension(LanguageProperties language, ArrayList res, IMethodOrProperty ext, IReturnType resolvedType) { // accept only extension methods if (!ext.IsExtensionMethod) { return; } // don't add extension if method with that name already exists // but allow overloading extension methods foreach (IMember member in res) { IMethodOrProperty p = member as IMethodOrProperty; if (p != null && p.IsExtensionMethod) { continue; } if (language.NameComparer.Equals(member.Name, ext.Name)) { return; } } // now add the extension method if it fits the type if (MemberLookupHelper.ConversionExists(resolvedType, ext.Parameters[0].ReturnType)) { IMethod method = ext as IMethod; if (method != null && method.TypeParameters.Count > 0) { IReturnType[] typeArguments = new IReturnType[method.TypeParameters.Count]; MemberLookupHelper.InferTypeArgument(method.Parameters[0].ReturnType, resolvedType, typeArguments); for (int i = 0; i < typeArguments.Length; i++) { if (typeArguments[i] != null) { ext = (IMethod)ext.Clone(); ext.ReturnType = ConstructedReturnType.TranslateType(ext.ReturnType, typeArguments, true); for (int j = 0; j < ext.Parameters.Count; ++j) { ext.Parameters[j].ReturnType = ConstructedReturnType.TranslateType(ext.Parameters[j].ReturnType, typeArguments, true); } break; } } } res.Add(ext); } }
static IReturnType[][] ExpandParametersAndSubstitute(IList <IMethodOrProperty> list, IReturnType[] arguments, int maxScore, int[] ranking, bool[] needToExpand, out IReturnType[][] inferredTypeParameters) { IReturnType[][] expandedParameters = new IReturnType[list.Count][]; inferredTypeParameters = new IReturnType[list.Count][]; for (int i = 0; i < ranking.Length; i++) { if (ranking[i] == maxScore) { IList <IParameter> parameters = list[i].Parameters; IReturnType[] typeParameters = (list[i] is IMethod) ? InferTypeArguments((IMethod)list[i], arguments) : null; inferredTypeParameters[i] = typeParameters; IReturnType paramsType = null; expandedParameters[i] = new IReturnType[arguments.Length]; for (int j = 0; j < arguments.Length; j++) { if (j < parameters.Count) { IParameter parameter = parameters[j]; if (parameter.IsParams && needToExpand[i]) { if (parameter.ReturnType.IsArrayReturnType) { paramsType = parameter.ReturnType.CastToArrayReturnType().ArrayElementType; paramsType = ConstructedReturnType.TranslateType(paramsType, typeParameters, true); } expandedParameters[i][j] = paramsType; } else { expandedParameters[i][j] = ConstructedReturnType.TranslateType(parameter.ReturnType, typeParameters, true); } } else { expandedParameters[i][j] = paramsType; } } } } return(expandedParameters); }
/// <summary> /// Gets the type parameter that was passed to a certain base class. /// For example, when <paramref name="returnType"/> is Dictionary(of string, int) /// this method will return KeyValuePair(of string, int) /// </summary> public static IReturnType GetTypeParameterPassedToBaseClass(IReturnType parentType, IClass baseClass, int baseClassTypeParameterIndex) { if (!parentType.IsConstructedReturnType) { return(null); } ConstructedReturnType returnType = parentType.CastToConstructedReturnType(); IClass c = returnType.GetUnderlyingClass(); if (c == null) { return(null); } if (baseClass.CompareTo(c) == 0) { if (baseClassTypeParameterIndex >= returnType.TypeArguments.Count) { return(null); } return(returnType.TypeArguments[baseClassTypeParameterIndex]); } foreach (IReturnType baseType in c.BaseTypes) { if (baseClass.CompareTo(baseType.GetUnderlyingClass()) == 0) { if (!baseType.IsConstructedReturnType) { return(null); } ConstructedReturnType baseTypeCRT = baseType.CastToConstructedReturnType(); if (baseClassTypeParameterIndex >= baseTypeCRT.TypeArguments.Count) { return(null); } IReturnType result = baseTypeCRT.TypeArguments[baseClassTypeParameterIndex]; if (returnType.TypeArguments != null) { result = ConstructedReturnType.TranslateType(result, returnType.TypeArguments, false); } return(result); } } return(null); }
public static IReturnType TranslateType(IReturnType input, IList <IReturnType> typeParameters, bool convertForMethod) { if (typeParameters == null || typeParameters.Count == 0) { return(input); // nothing to do when there are no type parameters specified } if (input.IsGenericReturnType) { GenericReturnType rt = input.CastToGenericReturnType(); if (convertForMethod ? (rt.TypeParameter.Method != null) : (rt.TypeParameter.Method == null)) { if (rt.TypeParameter.Index < typeParameters.Count) { IReturnType newType = typeParameters[rt.TypeParameter.Index]; if (newType != null) { return(newType); } } } } else if (input.IsArrayReturnType) { ArrayReturnType arInput = input.CastToArrayReturnType(); IReturnType e = arInput.ArrayElementType; IReturnType t = TranslateType(e, typeParameters, convertForMethod); if (e != t && t != null) { return(new ArrayReturnType(arInput.ProjectContent, t, arInput.ArrayDimensions)); } } else if (input.IsConstructedReturnType) { ConstructedReturnType cinput = input.CastToConstructedReturnType(); List <IReturnType> para = new List <IReturnType>(cinput.TypeArguments.Count); foreach (IReturnType argument in cinput.TypeArguments) { para.Add(TranslateType(argument, typeParameters, convertForMethod)); } return(new ConstructedReturnType(cinput.UnboundType, para)); } return(input); }
static void ApplyInferredTypeParameters(IList <IMethod> list, IReturnType[][] inferredTypeParameters) { if (inferredTypeParameters == null) { return; } for (int i = 0; i < list.Count; i++) { IReturnType[] inferred = inferredTypeParameters[i]; if (inferred != null && inferred.Length > 0) { IMethod m = (IMethod)list[i].Clone(); m.ReturnType = ConstructedReturnType.TranslateType(m.ReturnType, inferred, true); for (int j = 0; j < m.Parameters.Count; ++j) { m.Parameters[j].ReturnType = ConstructedReturnType.TranslateType(m.Parameters[j].ReturnType, inferred, true); } list[i] = m; } } }
/// <summary> /// Assigns a ranking score to each method in the <paramref name="list"/>. /// </summary> /// <param name="list">Link with the methods to check.<br/> /// <b>Generic methods in the input type are replaced by methods with have the types substituted!</b> /// </param> /// <param name="typeParameters">List with the type parameters passed to the method. /// Can be null (=no type parameters)</param> /// <param name="arguments">The types of the arguments passed to the method. /// A null return type means any argument type is allowed.</param> /// <param name="allowAdditionalArguments">Specifies whether the method can have /// more parameters than specified here. Useful for method insight scenarios.</param> /// <param name="acceptableMatch">Out parameter that is true when the best ranked /// method is acceptable for a method call (no invalid casts)</param> /// <returns>Integer array. Each value in the array </returns> public static int[] RankOverloads(IList <IMethod> list, IReturnType[] typeParameters, IReturnType[] arguments, bool allowAdditionalArguments, out bool acceptableMatch) { acceptableMatch = false; if (list.Count == 0) { return new int[] {} } ; List <IMethodOrProperty> l2 = new List <IMethodOrProperty>(list.Count); IReturnType[][] inferredTypeParameters; // See ECMA-334, § 14.3 // If type parameters are specified, remove all methods from the list that do not // use the specified number of parameters. if (typeParameters != null && typeParameters.Length > 0) { for (int i = 0; i < list.Count; i++) { IMethod m = list[i]; if (m.TypeParameters.Count == typeParameters.Length) { m = (IMethod)m.Clone(); m.ReturnType = ConstructedReturnType.TranslateType(m.ReturnType, typeParameters, true); for (int j = 0; j < m.Parameters.Count; ++j) { m.Parameters[j].ReturnType = ConstructedReturnType.TranslateType(m.Parameters[j].ReturnType, typeParameters, true); } list[i] = m; l2.Add(m); } } int[] innerRanking = RankOverloads(l2, arguments, allowAdditionalArguments, out acceptableMatch, out inferredTypeParameters); int[] ranking = new int[list.Count]; int innerIndex = 0; for (int i = 0; i < ranking.Length; i++) { if (list[i].TypeParameters.Count == typeParameters.Length) { ranking[i] = innerRanking[innerIndex++]; } else { ranking[i] = 0; } } return(ranking); } else { // Note that when there are no type parameters, methods having type parameters // are not removed, since the type inference process might be able to infer the // type arguments. foreach (IMethod m in list) { l2.Add(m); } int[] ranking = RankOverloads(l2, arguments, allowAdditionalArguments, out acceptableMatch, out inferredTypeParameters); ApplyInferredTypeParameters(list, inferredTypeParameters); return(ranking); } }