static void TryAddExtension(LanguageProperties language, Action <IMethodOrProperty> methodFound, IMethodOrProperty ext, IReturnType resolvedType) { // now add the extension method if it fits the type if (MemberLookupHelper.IsApplicable(resolvedType, ext.Parameters[0].ReturnType, ext as IMethod)) { 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.CreateSpecializedMember(); 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; } } } methodFound(ext); } }
static bool IsConstructedConversionToGenericReturnType(IReturnType from, IReturnType to, IMethod allowGenericTargetsOnThisMethod) { // null could be passed when type arguments could not be resolved/inferred if (from == to) // both are null or { return(true); } if (from == null || to == null) { return(false); } if (from.Equals(to)) { return(true); } if (allowGenericTargetsOnThisMethod == null) { return(false); } if (to.IsGenericReturnType) { ITypeParameter typeParameter = to.CastToGenericReturnType().TypeParameter; if (typeParameter.Method == allowGenericTargetsOnThisMethod) { return(true); } // applicability ignores constraints // foreach (IReturnType constraintType in typeParameter.Constraints) { // if (!ConversionExistsInternal(from, constraintType, allowGenericTargetsOnThisMethod)) { // return false; // } // } return(false); } // for conversions like from IEnumerable<string> to IEnumerable<T>, where T is a GenericReturnType ConstructedReturnType cFrom = from.CastToConstructedReturnType(); ConstructedReturnType cTo = to.CastToConstructedReturnType(); if (cFrom != null && cTo != null) { if (cFrom.FullyQualifiedName == cTo.FullyQualifiedName && cFrom.TypeArguments.Count == cTo.TypeArguments.Count) { for (int i = 0; i < cFrom.TypeArguments.Count; i++) { if (!IsConstructedConversionToGenericReturnType(cFrom.TypeArguments[i], cTo.TypeArguments[i], allowGenericTargetsOnThisMethod)) { return(false); } } return(true); } } return(false); }
/// <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) { foreach (IReturnType rt in GetTypeInheritanceTree(parentType)) { ConstructedReturnType crt = rt.CastToConstructedReturnType(); if (crt != null && baseClass.CompareTo(rt.GetUnderlyingClass()) == 0) { if (baseClassTypeParameterIndex < crt.TypeArguments.Count) { return(crt.TypeArguments[baseClassTypeParameterIndex]); } } } return(null); }
/// <summary> /// Translates typeToTranslate using the type arguments from parentType; /// </summary> static IReturnType TranslateIfRequired(IReturnType parentType, IReturnType typeToTranslate) { if (typeToTranslate == null) { return(null); } ConstructedReturnType parentConstructedType = parentType.CastToConstructedReturnType(); if (parentConstructedType != null) { return(ConstructedReturnType.TranslateType(typeToTranslate, parentConstructedType.TypeArguments, false)); } else { return(typeToTranslate); } }
public static IReturnType TranslateType(IReturnType input, IList <IReturnType> typeParameters, bool convertForMethod) { if (input == null || 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); }
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 if (name == "dynamic") { writer.Write(DynamicRTCode); } 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 if (rt.IsDecoratingReturnType <PointerReturnType>()) { writer.Write(PointerRTCode); WriteType(rt.CastToDecoratingReturnType <PointerReturnType>().BaseType); } else { writer.Write(NullRTReferenceCode); LoggingService.Warn("Unknown return type: " + rt.ToString()); } }