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 if (rt.IsDecoratingReturnType <PointerReturnType>()) { writer.Write(PointerRTCode); WriteType(rt.CastToDecoratingReturnType <PointerReturnType>().BaseType); } else { writer.Write(NullRTReferenceCode); LoggingService.Warn("Unknown return type: " + rt.ToString()); } }
public override bool Equals(IReturnType rt) { if (rt == null || !rt.IsGenericReturnType) { return(false); } GenericReturnType grt = rt.CastToGenericReturnType(); if ((typeParameter.Method == null) != (grt.typeParameter.Method == null)) { return(false); } return(typeParameter.Index == grt.typeParameter.Index); }
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); }
/// <summary> /// Infers type arguments specified by passing expectedArgument as parameter where passedArgument /// was expected. The resulting type arguments are written to outputArray. /// Returns false when expectedArgument and passedArgument are incompatible, otherwise true /// is returned (true is used both for successful inferring and other kind of errors). /// /// Warning: This method for single-argument type inference doesn't support lambdas! /// </summary> /// <remarks> /// The C# spec (§ 25.6.4) has a bug: it says that type inference works if the passedArgument is IEnumerable{T} /// and the expectedArgument is an array; passedArgument and expectedArgument must be swapped here. /// </remarks> public static bool InferTypeArgument(IReturnType expectedArgument, IReturnType passedArgument, IReturnType[] outputArray) { if (expectedArgument == null) { return(true); } if (passedArgument == null || passedArgument == NullReturnType.Instance) { return(true); } if (passedArgument.IsArrayReturnType) { IReturnType passedArrayElementType = passedArgument.CastToArrayReturnType().ArrayElementType; if (expectedArgument.IsArrayReturnType && expectedArgument.CastToArrayReturnType().ArrayDimensions == passedArgument.CastToArrayReturnType().ArrayDimensions) { return(InferTypeArgument(expectedArgument.CastToArrayReturnType().ArrayElementType, passedArrayElementType, outputArray)); } else if (expectedArgument.IsConstructedReturnType) { switch (expectedArgument.FullyQualifiedName) { case "System.Collections.Generic.IList": case "System.Collections.Generic.ICollection": case "System.Collections.Generic.IEnumerable": return(InferTypeArgument(expectedArgument.CastToConstructedReturnType().TypeArguments[0], passedArrayElementType, outputArray)); } } // If P is an array type, and A is not an array type of the same rank, // or an instantiation of IList<>, ICollection<>, or IEnumerable<>, then // type inference fails for the generic method. return(false); } if (expectedArgument.IsGenericReturnType) { GenericReturnType methodTP = expectedArgument.CastToGenericReturnType(); if (methodTP.TypeParameter.Method != null) { if (methodTP.TypeParameter.Index < outputArray.Length) { outputArray[methodTP.TypeParameter.Index] = passedArgument; } return(true); } } if (expectedArgument.IsConstructedReturnType) { // The spec for this case is quite complex. // For our purposes, we can simplify enourmously: if (!passedArgument.IsConstructedReturnType) { return(false); } IList <IReturnType> expectedTA = expectedArgument.CastToConstructedReturnType().TypeArguments; IList <IReturnType> passedTA = passedArgument.CastToConstructedReturnType().TypeArguments; int count = Math.Min(expectedTA.Count, passedTA.Count); for (int i = 0; i < count; i++) { InferTypeArgument(expectedTA[i], passedTA[i], outputArray); } } return(true); }