Example #1
0
 void AddExternalType(IReturnType rt, List <ClassNameTypeCountPair> externalTypes, int classCount)
 {
     if (rt.IsDefaultReturnType)
     {
         ClassNameTypeCountPair pair = new ClassNameTypeCountPair(rt);
         if (!classIndices.ContainsKey(pair))
         {
             classIndices.Add(pair, externalTypes.Count + classCount);
             externalTypes.Add(pair);
         }
     }
     else if (rt.IsGenericReturnType)
     {
         // ignore
     }
     else if (rt.IsArrayReturnType)
     {
         AddExternalType(rt.CastToArrayReturnType().ArrayElementType, externalTypes, classCount);
     }
     else if (rt.IsConstructedReturnType)
     {
         AddExternalType(rt.CastToConstructedReturnType().UnboundType, externalTypes, classCount);
         foreach (IReturnType typeArgument in rt.CastToConstructedReturnType().TypeArguments)
         {
             AddExternalType(typeArgument, externalTypes, classCount);
         }
     }
     else
     {
         LoggingService.Warn("Unknown return type: " + rt.ToString());
     }
 }
Example #2
0
 void UnpackNestedType(StringBuilder builder, IReturnType returnType)
 {
     if (returnType.IsArrayReturnType)
     {
         builder.Append('[');
         int dimensions = returnType.CastToArrayReturnType().ArrayDimensions;
         for (int i = 1; i < dimensions; ++i)
         {
             builder.Append(',');
         }
         builder.Append(']');
         UnpackNestedType(builder, returnType.CastToArrayReturnType().ArrayElementType);
     }
     else if (returnType.IsConstructedReturnType)
     {
         UnpackNestedType(builder, returnType.CastToConstructedReturnType().UnboundType);
         builder.Append('<');
         IList <IReturnType> ta = returnType.CastToConstructedReturnType().TypeArguments;
         for (int i = 0; i < ta.Count; ++i)
         {
             if (i > 0)
             {
                 builder.Append(", ");
             }
             builder.Append(Convert(ta[i]));
         }
         builder.Append('>');
     }
 }
        private void AppendReturnType(StringBuilder builder, IReturnType returnType, bool forceFullyQualifiedName)
        {
            var arrayReturnType = returnType;

            returnType = GetElementType(returnType);

            if (returnType == null)
            {
                return;
            }

            var    fullName = returnType.FullyQualifiedName;
            string shortName;
            var    isConstructedType = returnType.IsConstructedReturnType;

            if (fullName != null && !isConstructedType && TypeConversionTable.TryGetValue(fullName, out shortName))
            {
                builder.Append(shortName);
            }
            else
            {
                IClass c = returnType.GetUnderlyingClass();

                if (c != null)
                {
                    IList <IReturnType> ta = isConstructedType
                                                ? returnType.CastToConstructedReturnType().TypeArguments
                                                : null;
                    AppendClassNameWithTypeParameters(builder, c, forceFullyQualifiedName || UseFullyQualifiedTypeNames,
                                                      false, ta);
                }
                else
                {
                    if (UseFullyQualifiedTypeNames || forceFullyQualifiedName)
                    {
                        builder.Append(fullName);
                    }
                    else
                    {
                        builder.Append(returnType.Name);
                    }
                    if (isConstructedType)
                    {
                        builder.Append('<');
                        IList <IReturnType> ta = returnType.CastToConstructedReturnType().TypeArguments;
                        for (int i = 0; i < ta.Count; ++i)
                        {
                            if (i > 0)
                            {
                                builder.Append(", ");
                            }
                            AppendReturnType(builder, ta[i], false);
                        }
                        builder.Append('>');
                    }
                }
            }

            UnpackArrayType(builder, arrayReturnType);
        }
Example #4
0
 /// <summary>
 /// Gets if <paramref name="t"/> is/contains a generic return type referring to a class type parameter.
 /// </summary>
 bool CheckReturnType(IReturnType t)
 {
     if (t == null)
     {
         return(false);
     }
     if (t.IsGenericReturnType)
     {
         return(t.CastToGenericReturnType().TypeParameter.Method == null);
     }
     else if (t.IsArrayReturnType)
     {
         return(CheckReturnType(t.CastToArrayReturnType().ArrayElementType));
     }
     else if (t.IsConstructedReturnType)
     {
         foreach (IReturnType para in t.CastToConstructedReturnType().TypeArguments)
         {
             if (CheckReturnType(para))
             {
                 return(true);
             }
         }
         return(false);
     }
     else
     {
         return(false);
     }
 }
Example #5
0
        /// <summary>
        /// Returns true if the short name of a type is valid in the given context.
        /// Returns false for primitive types because they should be passed around using their
        /// fully qualified names to allow the ambience or output visitor to use the intrinsic
        /// type name.
        /// </summary>
        public static bool CanUseShortTypeName(IReturnType returnType, ClassFinder context)
        {
            switch (returnType.FullyQualifiedName)
            {
            case "System.Void":
            case "System.String":
            case "System.Char":
            case "System.Boolean":
            case "System.Single":
            case "System.Double":
            case "System.Decimal":
            case "System.Byte":
            case "System.SByte":
            case "System.Int16":
            case "System.Int32":
            case "System.Int64":
            case "System.UInt16":
            case "System.UInt32":
            case "System.UInt64":
                // don't use short name -> output visitor will use the instrinsic name
                return(false);
            }
            int         typeArgumentCount   = (returnType.IsConstructedReturnType) ? returnType.CastToConstructedReturnType().TypeArguments.Count : 0;
            IReturnType typeInTargetContext = context.SearchType(returnType.Name, typeArgumentCount);

            return(typeInTargetContext != null && typeInTargetContext.FullyQualifiedName == returnType.FullyQualifiedName);
        }
Example #6
0
        /// <summary>
        /// Returns true if the short name of a type is valid in the given context.
        /// Returns false for primitive types because they should be passed around using their
        /// fully qualified names to allow the ambience or output visitor to use the intrinsic
        /// type name.
        /// </summary>
        public static bool CanUseShortTypeName(IReturnType returnType, ClassFinder context)
        {
            int         typeArgumentCount   = (returnType.IsConstructedReturnType) ? returnType.CastToConstructedReturnType().TypeArguments.Count : 0;
            IReturnType typeInTargetContext = context.SearchType(returnType.Name, typeArgumentCount);

            return(typeInTargetContext != null && typeInTargetContext.FullyQualifiedName == returnType.FullyQualifiedName);
        }
        public static string FormatName(this IReturnType type)
        {
            if (type == null)
            {
                return(string.Empty);
            }

            if (type.Name == "Nullable")
            {
                return(string.Format("{0}?", type.CastToConstructedReturnType().TypeArguments[0].FormatName()));
            }

            var formattedName = type.GetFormattedNameOrNull();

            if (formattedName != null)
            {
                return(formattedName);
            }

            var underlyingClass = type.GetUnderlyingClass();

            if (underlyingClass != null)
            {
                return(underlyingClass.FormatName());
            }

            return(type.Name);
        }
Example #8
0
 static int GetMoreSpecific(IReturnType r, IReturnType s)
 {
     if (r == null && s == null)
     {
         return(0);
     }
     if (r == null)
     {
         return(2);
     }
     if (s == null)
     {
         return(1);
     }
     if (r.IsGenericReturnType && !(s.IsGenericReturnType))
     {
         return(2);
     }
     if (s.IsGenericReturnType && !(r.IsGenericReturnType))
     {
         return(1);
     }
     if (r.IsArrayReturnType && s.IsArrayReturnType)
     {
         return(GetMoreSpecific(r.CastToArrayReturnType().ArrayElementType, s.CastToArrayReturnType().ArrayElementType));
     }
     if (r.IsConstructedReturnType && s.IsConstructedReturnType)
     {
         return(GetMoreSpecific(r.CastToConstructedReturnType().TypeArguments, s.CastToConstructedReturnType().TypeArguments));
     }
     return(0);
 }
Example #9
0
 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());
     }
 }
        static bool IsConstructedConversionToGenericReturnType(IReturnType from, IReturnType to, IMethod allowGenericTargetsOnThisMethod)
        {
            // null could be passed when type arguments could not be resolved/inferred
            if (from == null && to == null)
            {
                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(false);
                }
                foreach (IReturnType constraintType in typeParameter.Constraints)
                {
                    if (!ConversionExistsInternal(from, constraintType, allowGenericTargetsOnThisMethod))
                    {
                        return(false);
                    }
                }
                return(true);
            }

            // 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);
        }
Example #11
0
        public void TypeParameterPassedToBaseClassTestDictionary()
        {
            IReturnType[] stringInt = { msc.SystemTypes.String, msc.SystemTypes.Int32 };
            IReturnType   rrt       = new ConstructedReturnType(DictionaryRT, stringInt);
            IReturnType   res       = MemberLookupHelper.GetTypeParameterPassedToBaseClass(rrt, EnumerableClass, 0);

            Assert.AreEqual("System.Collections.Generic.KeyValuePair", res.FullyQualifiedName);
            ConstructedReturnType resc = res.CastToConstructedReturnType();

            Assert.AreEqual("System.String", resc.TypeArguments[0].FullyQualifiedName);
            Assert.AreEqual("System.Int32", resc.TypeArguments[1].FullyQualifiedName);
        }
Example #12
0
 void UnpackNestedType(StringBuilder builder, IReturnType returnType)
 {
     if (returnType.IsArrayReturnType)
     {
         ArrayReturnType art = returnType.CastToArrayReturnType();
         builder.Append('(');
         UnpackNestedType(builder, art.ArrayElementType);
         if (art.ArrayDimensions > 1)
         {
             builder.Append(',');
             builder.Append(art.ArrayDimensions);
         }
         builder.Append(')');
     }
     else if (returnType.IsConstructedReturnType)
     {
         ConstructedReturnType crt = returnType.CastToConstructedReturnType();
         UnpackNestedType(builder, crt.UnboundType);
         builder.Append("[of ");
         for (int i = 0; i < crt.TypeArguments.Count; ++i)
         {
             if (i > 0)
             {
                 builder.Append(", ");
             }
             builder.Append(Convert(crt.TypeArguments[i]));
         }
         builder.Append(']');
     }
     else
     {
         string fullName = returnType.FullyQualifiedName;
         if (fullName != null && typeConversionTable.ContainsKey(fullName))
         {
             builder.Append(typeConversionTable[fullName].ToString());
         }
         else
         {
             if (UseFullyQualifiedTypeNames)
             {
                 builder.Append(fullName);
             }
             else
             {
                 builder.Append(returnType.Name);
             }
         }
     }
 }
Example #13
0
        public virtual ConstructedReturnType CastToConstructedReturnType()
        {
            IReturnType           baseType = BaseType;
            ConstructedReturnType temp;

            if (baseType != null && TryEnter())
            {
                temp = baseType.CastToConstructedReturnType();
            }
            else
            {
                throw new InvalidCastException("Cannot cast " + ToString() + " to expected type.");
            }
            _busy = false;
            return(temp);
        }
Example #14
0
			/// <summary>
			/// Gets whether this type parameter occurs in the specified return type.
			/// </summary>
			public bool OccursIn(IReturnType rt)
			{
				ArrayReturnType art = rt.CastToArrayReturnType();
				if (art != null) {
					return OccursIn(art.ArrayElementType);
				}
				ConstructedReturnType crt = rt.CastToConstructedReturnType();
				if (crt != null) {
					return crt.TypeArguments.Any(ta => OccursIn(ta));
				}
				GenericReturnType grt = rt.CastToGenericReturnType();
				if (grt != null) {
					return this.TypeParameter.Equals(grt.TypeParameter);
				}
				return false;
			}
		bool CheckReturnType(IReturnType t)
		{
			if (t.IsGenericReturnType) {
				return t.CastToGenericReturnType().TypeParameter.Method == null;
			} else if (t.IsArrayReturnType) {
				return CheckReturnType(t.CastToArrayReturnType().ArrayElementType);
			} else if (t.IsConstructedReturnType) {
				foreach (IReturnType para in t.CastToConstructedReturnType().TypeArguments) {
					if (para != null) {
						if (CheckReturnType(para)) return true;
					}
				}
				return false;
			} else {
				return false;
			}
		}
        /// <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);
            }
        }
Example #17
0
        /// <summary>
        /// Make exact inference from U for V.
        /// </summary>
        void MakeExactInference(IReturnType U, IReturnType V)
        {
            Log(" MakeExactInference from " + U + " for " + V);
            if (U == null || V == null)
            {
                return;
            }

            // If V is one of the unfixed Xi then U is added to the set of bounds for Xi.
            TP tp = GetTPForType(V);

            if (tp != null && tp.Fixed == false)
            {
                Log(" Add bound '" + U.DotNetName + "' to " + tp);
                tp.Bounds.Add(U);
                return;
            }
            // Otherwise if U is an array type Ue[…] and V is an array type Ve[…] of the same rank
            // then an exact inference from Ue to Ve is made
            ArrayReturnType arrU = U.CastToArrayReturnType();
            ArrayReturnType arrV = V.CastToArrayReturnType();

            if (arrU != null && arrV != null && arrU.ArrayDimensions == arrV.ArrayDimensions)
            {
                MakeExactInference(arrU.ArrayElementType, arrV.ArrayElementType);
                return;
            }
            // Otherwise if V is a constructed type C<V1…Vk> and U is a constructed
            // type C<U1…Uk> then an exact inference is made from each Ui to the corresponding Vi.
            ConstructedReturnType CU = U.CastToConstructedReturnType();
            ConstructedReturnType CV = V.CastToConstructedReturnType();

            if (CU != null && CV != null &&
                object.Equals(CU.UnboundType, CV.UnboundType) &&
                CU.TypeArgumentCount == CV.TypeArgumentCount &&
                CU.TypeArguments.Count == CU.TypeArgumentCount &&
                CV.TypeArguments.Count == CV.TypeArgumentCount)
            {
                for (int i = 0; i < CU.TypeArgumentCount; i++)
                {
                    MakeExactInference(CU.TypeArguments[i], CV.TypeArguments[i]);
                }
                return;
            }
        }
Example #18
0
 internal static IMethod GetDelegateOrExpressionTreeSignature(IReturnType rt, bool allowExpressionTree)
 {
     if (rt == null)
         return null;
     IClass c = rt.GetUnderlyingClass();
     if (allowExpressionTree && c != null && c.FullyQualifiedName == "System.Linq.Expressions.Expression") {
         ConstructedReturnType crt = rt.CastToConstructedReturnType();
         if (crt != null && crt.TypeArguments.Count == 1) {
             // get delegate type from expression type
             rt = crt.TypeArguments[0];
             c = rt != null ? rt.GetUnderlyingClass() : null;
         }
     }
     if (c != null && c.ClassType == ClassType.Delegate) {
         return rt.GetMethods().FirstOrDefault((IMethod m) => m.Name == "Invoke");
     }
     return null;
 }
        /// <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);
        }
Example #20
0
 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);
 }
Example #21
0
        public static TypeReference ConvertType(IReturnType returnType, ClassFinder context)
        {
            if (returnType == null)
            {
                return(TypeReference.Null);
            }
            if (returnType is NullReturnType)
            {
                return(TypeReference.Null);
            }

            TypeReference typeRef;

            if (IsPrimitiveType(returnType))
            {
                typeRef = new TypeReference(returnType.FullyQualifiedName, true);
            }
            else if (context != null && CanUseShortTypeName(returnType, context))
            {
                typeRef = new TypeReference(returnType.Name);
            }
            else
            {
                typeRef = new TypeReference(returnType.FullyQualifiedName);
            }
            while (returnType.IsArrayReturnType)
            {
                int[] rank = typeRef.RankSpecifier ?? new int[0];
                Array.Resize(ref rank, rank.Length + 1);
                rank[rank.Length - 1] = returnType.CastToArrayReturnType().ArrayDimensions - 1;
                typeRef.RankSpecifier = rank;
                returnType            = returnType.CastToArrayReturnType().ArrayElementType;
            }
            if (returnType.IsConstructedReturnType)
            {
                foreach (IReturnType typeArgument in returnType.CastToConstructedReturnType().TypeArguments)
                {
                    typeRef.GenericTypes.Add(ConvertType(typeArgument, context));
                }
            }
            return(typeRef);
        }
        public void AssemblyAttribute()
        {
            var attributes = GetAssemblyAttributes(typeof(TypeTestAttribute).Assembly);
            var typeTest   = attributes.First(a => a.AttributeType.FullyQualifiedName == typeof(TypeTestAttribute).FullName);

            Assert.AreEqual(3, typeTest.PositionalArguments.Count);
            // first argument is (int)42
            Assert.AreEqual(42, (int)typeTest.PositionalArguments[0]);
            // second argument is typeof(System.Action<>)
            IReturnType rt = (IReturnType)typeTest.PositionalArguments[1];

            Assert.IsNull(rt.CastToConstructedReturnType());             // rt must not be constructed - it's just an unbound type
            Assert.AreEqual("System.Action", rt.FullyQualifiedName);
            Assert.AreEqual(1, rt.TypeArgumentCount);
            // third argument is typeof(IDictionary<string, IList<TestAttribute>>)
            ConstructedReturnType crt = ((IReturnType)typeTest.PositionalArguments[2]).CastToConstructedReturnType();

            Assert.AreEqual("System.Collections.Generic.IDictionary", crt.FullyQualifiedName);
            Assert.AreEqual("System.String", crt.TypeArguments[0].FullyQualifiedName);
            Assert.AreEqual("System.Collections.Generic.IList{NUnit.Framework.TestAttribute}", crt.TypeArguments[1].DotNetName);
        }
Example #23
0
            /// <summary>
            /// Gets whether this type parameter occurs in the specified return type.
            /// </summary>
            public bool OccursIn(IReturnType rt)
            {
                ArrayReturnType art = rt.CastToArrayReturnType();

                if (art != null)
                {
                    return(OccursIn(art.ArrayElementType));
                }
                ConstructedReturnType crt = rt.CastToConstructedReturnType();

                if (crt != null)
                {
                    return(crt.TypeArguments.Any(ta => OccursIn(ta)));
                }
                GenericReturnType grt = rt.CastToGenericReturnType();

                if (grt != null)
                {
                    return(this.TypeParameter.Equals(grt.TypeParameter));
                }
                return(false);
            }
Example #24
0
        public override object VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data)
        {
            IReturnType type = ResolveType(unaryOperatorExpression.Expression);

            if (type == null)
            {
                return(null);
            }
            switch (unaryOperatorExpression.Op)
            {
            case UnaryOperatorType.AddressOf:
                return(CreateResolveResult(new PointerReturnType(type)));

            case UnaryOperatorType.Dereference:
                PointerReturnType prt = type.CastToDecoratingReturnType <PointerReturnType>();
                if (prt != null)
                {
                    return(CreateResolveResult(prt.BaseType));
                }
                else
                {
                    return(null);
                }

            case UnaryOperatorType.Await:
                var crt = type.CastToConstructedReturnType();
                if (crt != null && crt.Name == "Task" && crt.TypeArguments.Count == 1)
                {
                    return(CreateResolveResult(crt.TypeArguments[0]));
                }
                else
                {
                    return(null);
                }

            default:
                return(CreateResolveResult(type));
            }
        }
Example #25
0
        internal static IMethod GetDelegateOrExpressionTreeSignature(IReturnType rt, bool allowExpressionTree)
        {
            if (rt == null)
            {
                return(null);
            }
            IClass c = rt.GetUnderlyingClass();

            if (allowExpressionTree && c != null && c.FullyQualifiedName == "System.Linq.Expressions.Expression")
            {
                ConstructedReturnType crt = rt.CastToConstructedReturnType();
                if (crt != null && crt.TypeArguments.Count == 1)
                {
                    // get delegate type from expression type
                    rt = crt.TypeArguments[0];
                    c  = rt != null?rt.GetUnderlyingClass() : null;
                }
            }
            if (c != null && c.ClassType == ClassType.Delegate)
            {
                return(rt.GetMethods().FirstOrDefault((IMethod m) => m.Name == "Invoke"));
            }
            return(null);
        }
Example #26
0
		void UnpackNestedType(StringBuilder builder, IReturnType returnType)
		{
			if (returnType.IsArrayReturnType) {
				builder.Append('(');
				int dimensions = returnType.CastToArrayReturnType().ArrayDimensions;
				for (int i = 1; i < dimensions; ++i) {
					builder.Append(',');
				}
				builder.Append(')');
				UnpackNestedType(builder, returnType.CastToArrayReturnType().ArrayElementType);
			} else if (returnType.IsConstructedReturnType) {
				UnpackNestedType(builder, returnType.CastToConstructedReturnType().UnboundType);
				builder.Append("(Of ");
				IList<IReturnType> ta = returnType.CastToConstructedReturnType().TypeArguments;
				for (int i = 0; i < ta.Count; ++i) {
					if (i > 0) builder.Append(", ");
					builder.Append(Convert(ta[i]));
				}
				builder.Append(')');
			}
		}
Example #27
0
		/// <summary>
		/// Make exact inference from U for V.
		/// </summary>
		void MakeExactInference(IReturnType U, IReturnType V)
		{
			Log(" MakeExactInference from " + U + " for " + V);
			if (U == null || V == null)
				return;
			
			// If V is one of the unfixed Xi then U is added to the set of bounds for Xi.
			TP tp = GetTPForType(V);
			if (tp != null && tp.Fixed == false) {
				Log(" Add bound '" + U.DotNetName + "' to " + tp);
				tp.Bounds.Add(U);
				return;
			}
			// Otherwise if U is an array type Ue[…] and V is an array type Ve[…] of the same rank
			// then an exact inference from Ue to Ve is made
			ArrayReturnType arrU = U.CastToArrayReturnType();
			ArrayReturnType arrV = V.CastToArrayReturnType();
			if (arrU != null && arrV != null && arrU.ArrayDimensions == arrV.ArrayDimensions) {
				MakeExactInference(arrU.ArrayElementType, arrV.ArrayElementType);
				return;
			}
			// Otherwise if V is a constructed type C<V1…Vk> and U is a constructed
			// type C<U1…Uk> then an exact inference is made from each Ui to the corresponding Vi.
			ConstructedReturnType CU = U.CastToConstructedReturnType();
			ConstructedReturnType CV = V.CastToConstructedReturnType();
			if (CU != null && CV != null
			    && object.Equals(CU.UnboundType, CV.UnboundType)
			    && CU.TypeArgumentCount == CV.TypeArgumentCount
			    && CU.TypeArguments.Count == CU.TypeArgumentCount
			    && CV.TypeArguments.Count == CV.TypeArgumentCount)
			{
				for (int i = 0; i < CU.TypeArgumentCount; i++) {
					MakeExactInference(CU.TypeArguments[i], CV.TypeArguments[i]);
				}
				return;
			}
		}
Example #28
0
        /// <summary>
        /// Make lower bound inference from U for V.
        /// </summary>
        void MakeLowerBoundInference(IReturnType U, IReturnType V)
        {
            Log(" MakeLowerBoundInference from " + U + " for " + V);
            if (U == null || V == null)
            {
                return;
            }

            // If V is one of the unfixed Xi then U is added to the set of bounds for Xi.
            TP tp = GetTPForType(V);

            if (tp != null && tp.Fixed == false)
            {
                Log("  Add bound '" + U.DotNetName + "' to " + tp);
                tp.Bounds.Add(U);
                return;
            }
            // Otherwise if U is an array type Ue[…] and V is either an array type Ve[…]of the
            // same rank, or if U is a one­dimensional array type Ue[]and V is one of
            // IEnumerable<Ve>, ICollection<Ve> or IList<Ve> then
            ArrayReturnType       arrU = U.CastToArrayReturnType();
            ArrayReturnType       arrV = V.CastToArrayReturnType();
            ConstructedReturnType CV   = V.CastToConstructedReturnType();

            if (arrU != null &&
                (arrV != null && arrU.ArrayDimensions == arrV.ArrayDimensions ||
                 (arrU.ArrayDimensions == 1 && IsIEnumerableCollectionOrList(CV))))
            {
                IReturnType Ue = arrU.ArrayElementType;
                IReturnType Ve = arrV != null ? arrV.ArrayElementType : CV.TypeArguments[0];
                // If Ue is known to be a reference type then a lower­bound inference from Ue to Ve is made
                if (IsReferenceType(Ue) ?? false)
                {
                    MakeLowerBoundInference(Ue, Ve);
                }
                else
                {
                    // Otherwise an exact inference from Ue to Ve is made
                    MakeExactInference(Ue, Ve);
                }
                return;
            }
            // Otherwise if V is a constructed type C<V1…Vk> and there is a unique set of
            // types U1…Uk such that a standard implicit conversion exists from U to C<U1…Uk>
            // then an exact inference is made from each Ui for the corresponding Vi.
            if (CV != null)
            {
                foreach (IReturnType U2 in MemberLookupHelper.GetTypeInheritanceTree(U))
                {
                    ConstructedReturnType CU2 = U2.CastToConstructedReturnType();
                    if (CU2 != null &&
                        object.Equals(CU2.UnboundType, CV.UnboundType) &&
                        CU2.TypeArgumentCount == CV.TypeArgumentCount &&
                        CU2.TypeArguments.Count == CU2.TypeArgumentCount &&                     // unfortunately these might not be the same...
                        CV.TypeArguments.Count == CV.TypeArgumentCount)
                    {
                        for (int i = 0; i < CU2.TypeArgumentCount; i++)
                        {
                            MakeExactInference(CU2.TypeArguments[i], CV.TypeArguments[i]);
                        }
                        return;
                    }
                }
            }
        }
			void AddExternalType(IReturnType rt, List<ClassNameTypeCountPair> externalTypes, int classCount)
			{
				if (rt.IsDefaultReturnType) {
					ClassNameTypeCountPair pair = new ClassNameTypeCountPair(rt);
					if (!classIndices.ContainsKey(pair)) {
						classIndices.Add(pair, externalTypes.Count + classCount);
						externalTypes.Add(pair);
					}
				} else if (rt.IsGenericReturnType) {
					// ignore
				} else if (rt.IsArrayReturnType) {
					AddExternalType(rt.CastToArrayReturnType().ArrayElementType, externalTypes, classCount);
				} else if (rt.IsConstructedReturnType) {
					AddExternalType(rt.CastToConstructedReturnType().UnboundType, externalTypes, classCount);
					foreach (IReturnType typeArgument in rt.CastToConstructedReturnType().TypeArguments) {
						AddExternalType(typeArgument, externalTypes, classCount);
					}
				} else if (rt.IsDecoratingReturnType<PointerReturnType>()) {
					AddExternalType(rt.CastToDecoratingReturnType<PointerReturnType>().BaseType, externalTypes, classCount);
				} else {
					LoggingService.Warn("Unknown return type: " + rt.ToString());
				}
			}
			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());
				}
			}
        /// <summary>
        /// Checks if an implicit conversion exists from <paramref name="from"/> to <paramref name="to"/>.
        /// </summary>
        public static bool ConversionExists(IReturnType from, IReturnType to)
        {
            // ECMA-334, § 13.1 Implicit conversions

            // Identity conversion:
            if (from == to)
            {
                return(true);
            }
            if (from == null || to == null)
            {
                return(false);
            }
            if (from.Equals(to))
            {
                return(true);
            }

            bool fromIsDefault = from.IsDefaultReturnType;
            bool toIsDefault   = to.IsDefaultReturnType;

            if (fromIsDefault && toIsDefault)
            {
                // Implicit numeric conversions:
                int f = GetPrimitiveType(from);
                int t = GetPrimitiveType(to);
                if (f == SByte && (t == Short || t == Int || t == Long || t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if (f == Byte && (t == Short || t == UShort || t == Int || t == UInt || t == Long || t == ULong || t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if (f == Short && (t == Int || t == Long || t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if (f == UShort && (t == Int || t == UInt || t == Long || t == ULong || t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if (f == Int && (t == Long || t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if (f == UInt && (t == Long || t == ULong || t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if ((f == Long || f == ULong) && (t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if (f == Char && (t == UShort || t == Int || t == UInt || t == Long || t == ULong || t == Float || t == Double || t == Decimal))
                {
                    return(true);
                }
                if (f == Float && t == Double)
                {
                    return(true);
                }
            }
            // Implicit reference conversions:

            if (toIsDefault && to.FullyQualifiedName == "System.Object")
            {
                return(true);                // from any type to object
            }
            if (toIsDefault && (fromIsDefault || from.IsArrayReturnType))
            {
                IClass c1 = from.GetUnderlyingClass();
                IClass c2 = to.GetUnderlyingClass();
                if (c1 != null && c1.IsTypeInInheritanceTree(c2))
                {
                    return(true);
                }
            }
            if (from.IsArrayReturnType && to.IsArrayReturnType)
            {
                ArrayReturnType fromArt = from.CastToArrayReturnType();
                ArrayReturnType toArt   = to.CastToArrayReturnType();
                // from array to other array type
                if (fromArt.ArrayDimensions == toArt.ArrayDimensions)
                {
                    return(ConversionExists(fromArt.ArrayElementType, toArt.ArrayElementType));
                }
            }

            if (from.IsConstructedReturnType && to.IsConstructedReturnType)
            {
                if (from.FullyQualifiedName == to.FullyQualifiedName)
                {
                    IList <IReturnType> fromTypeArguments = from.CastToConstructedReturnType().TypeArguments;
                    IList <IReturnType> toTypeArguments   = to.CastToConstructedReturnType().TypeArguments;
                    if (fromTypeArguments.Count == toTypeArguments.Count)
                    {
                        for (int i = 0; i < fromTypeArguments.Count; i++)
                        {
                            if (fromTypeArguments[i] == toTypeArguments[i])
                            {
                                continue;
                            }
                            if (object.Equals(fromTypeArguments[i], toTypeArguments[i]))
                            {
                                continue;
                            }
                            if (!(toTypeArguments[i].IsGenericReturnType))
                            {
                                return(false);
                            }
                        }
                        return(true);
                    }
                }
            }

            return(false);
        }
		/// <summary>
		/// Checks if an implicit conversion exists from <paramref name="from"/> to <paramref name="to"/>.
		/// </summary>
		public static bool ConversionExists(IReturnType from, IReturnType to)
		{
			// ECMA-334, § 13.1 Implicit conversions
			
			// Identity conversion:
			if (from == to) return true;
			if (from == null || to == null) return false;
			if (from.Equals(to)) {
				return true;
			}
			
			bool fromIsDefault = from.IsDefaultReturnType;
			bool toIsDefault = to.IsDefaultReturnType;
			
			if (fromIsDefault && toIsDefault) {
				// Implicit numeric conversions:
				int f = GetPrimitiveType(from);
				int t = GetPrimitiveType(to);
				if (f == SByte && (t == Short || t == Int || t == Long || t == Float || t == Double || t == Decimal))
					return true;
				if (f == Byte && (t == Short || t == UShort || t == Int || t == UInt || t == Long || t == ULong || t == Float || t == Double || t == Decimal))
					return true;
				if (f == Short && (t == Int || t == Long || t == Float || t == Double || t == Decimal))
					return true;
				if (f == UShort && (t == Int || t == UInt || t == Long || t == ULong || t == Float || t == Double || t == Decimal))
					return true;
				if (f == Int && (t == Long || t == Float || t == Double || t == Decimal))
					return true;
				if (f == UInt && (t == Long || t == ULong || t == Float || t == Double || t == Decimal))
					return true;
				if ((f == Long || f == ULong) && (t == Float || t == Double || t == Decimal))
					return true;
				if (f == Char && (t == UShort || t == Int || t == UInt || t == Long || t == ULong || t == Float || t == Double || t == Decimal))
					return true;
				if (f == Float && t == Double)
					return true;
			}
			// Implicit reference conversions:
			
			if (toIsDefault && to.FullyQualifiedName == "System.Object") {
				return true; // from any type to object
			}
			if (toIsDefault && (fromIsDefault || from.IsArrayReturnType)) {
				IClass c1 = from.GetUnderlyingClass();
				IClass c2 = to.GetUnderlyingClass();
				if (c1 != null && c1.IsTypeInInheritanceTree(c2)) {
					return true;
				}
			}
			if (from.IsArrayReturnType && to.IsArrayReturnType) {
				ArrayReturnType fromArt = from.CastToArrayReturnType();
				ArrayReturnType toArt   = to.CastToArrayReturnType();
				// from array to other array type
				if (fromArt.ArrayDimensions == toArt.ArrayDimensions) {
					return ConversionExists(fromArt.ArrayElementType, toArt.ArrayElementType);
				}
			}
			
			if (from.IsConstructedReturnType && to.IsConstructedReturnType) {
				if (from.FullyQualifiedName == to.FullyQualifiedName) {
					IList<IReturnType> fromTypeArguments = from.CastToConstructedReturnType().TypeArguments;
					IList<IReturnType> toTypeArguments = to.CastToConstructedReturnType().TypeArguments;
					if (fromTypeArguments.Count == toTypeArguments.Count) {
						for (int i = 0; i < fromTypeArguments.Count; i++) {
							if (fromTypeArguments[i] == toTypeArguments[i])
								continue;
							if (object.Equals(fromTypeArguments[i], toTypeArguments[i]))
								continue;
							if (!(toTypeArguments[i].IsGenericReturnType))
								return false;
						}
						return true;
					}
				}
			}
			
			return false;
		}
Example #33
0
		void UnpackNestedType(StringBuilder builder, IReturnType returnType)
		{
			if (returnType.IsArrayReturnType) {
				ArrayReturnType art = returnType.CastToArrayReturnType();
				builder.Append('(');
				UnpackNestedType(builder, art.ArrayElementType);
				if (art.ArrayDimensions > 1) {
					builder.Append(',');
					builder.Append(art.ArrayDimensions);
				}
				builder.Append(')');
			} else if (returnType.IsConstructedReturnType) {
				ConstructedReturnType crt = returnType.CastToConstructedReturnType();
				UnpackNestedType(builder, crt.UnboundType);
				builder.Append("[of ");
				for (int i = 0; i < crt.TypeArguments.Count; ++i) {
					if (i > 0) builder.Append(", ");
					builder.Append(Convert(crt.TypeArguments[i]));
				}
				builder.Append(']');
			} else {
				string fullName = returnType.FullyQualifiedName;
				if (fullName != null && typeConversionTable.ContainsKey(fullName)) {
					builder.Append(typeConversionTable[fullName].ToString());
				} else {
					if (UseFullyQualifiedTypeNames) {
						builder.Append(fullName);
					} else {
						builder.Append(returnType.Name);
					}
				}
			}
		}
        /// <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).
        /// </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);
        }
		static int GetMoreSpecific(IReturnType r, IReturnType s)
		{
			if (r == null && s == null) return 0;
			if (r == null) return 2;
			if (s == null) return 1;
			if (r.IsGenericReturnType && !(s.IsGenericReturnType))
				return 2;
			if (s.IsGenericReturnType && !(r.IsGenericReturnType))
				return 1;
			if (r.IsArrayReturnType && s.IsArrayReturnType)
				return GetMoreSpecific(r.CastToArrayReturnType().ArrayElementType, s.CastToArrayReturnType().ArrayElementType);
			if (r.IsConstructedReturnType && s.IsConstructedReturnType)
				return GetMoreSpecific(r.CastToConstructedReturnType().TypeArguments, s.CastToConstructedReturnType().TypeArguments);
			return 0;
		}
        public static TypeReference ConvertType(IReturnType returnType, ClassFinder context)
        {
            if (returnType == null)
            {
                return(TypeReference.Null);
            }
            if (returnType is NullReturnType)
            {
                return(TypeReference.Null);
            }

            ArrayReturnType arrayReturnType = returnType.CastToArrayReturnType();

            if (arrayReturnType != null)
            {
                TypeReference typeRef = ConvertType(arrayReturnType.ArrayElementType, context);
                int[]         rank    = typeRef.RankSpecifier ?? new int[0];
                Array.Resize(ref rank, rank.Length + 1);
                rank[rank.Length - 1] = arrayReturnType.ArrayDimensions - 1;
                typeRef.RankSpecifier = rank;
                return(typeRef);
            }
            PointerReturnType pointerReturnType = returnType.CastToDecoratingReturnType <PointerReturnType>();

            if (pointerReturnType != null)
            {
                TypeReference typeRef = ConvertType(pointerReturnType.BaseType, context);
                typeRef.PointerNestingLevel++;
                return(typeRef);
            }

            IList <IReturnType> typeArguments = EmptyList <IReturnType> .Instance;

            if (returnType.IsConstructedReturnType)
            {
                typeArguments = returnType.CastToConstructedReturnType().TypeArguments;
            }
            IClass c = returnType.GetUnderlyingClass();

            if (c != null)
            {
                return(CreateTypeReference(c, typeArguments, context));
            }
            else
            {
                TypeReference typeRef;
                if (IsPrimitiveType(returnType))
                {
                    typeRef = new TypeReference(returnType.FullyQualifiedName, true);
                }
                else if (context != null && CanUseShortTypeName(returnType, context))
                {
                    typeRef = new TypeReference(returnType.Name);
                }
                else
                {
                    string fullName = returnType.FullyQualifiedName;
                    if (string.IsNullOrEmpty(fullName))
                    {
                        fullName = returnType.Name;
                    }
                    typeRef = new TypeReference(fullName);
                }
                foreach (IReturnType typeArgument in typeArguments)
                {
                    typeRef.GenericTypes.Add(ConvertType(typeArgument, context));
                }
                return(typeRef);
            }
        }
		/// <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).
		/// </summary>
		public static bool InferTypeArgument(IReturnType expectedArgument, IReturnType passedArgument, IReturnType[] outputArray)
		{
			if (expectedArgument == null) return true;
			if (passedArgument == null) return true; // TODO: NullTypeReference
			if (expectedArgument.IsArrayReturnType) {
				IReturnType expectedArrayElementType = expectedArgument.CastToArrayReturnType().ArrayElementType;
				if (passedArgument.IsArrayReturnType && expectedArgument.CastToArrayReturnType().ArrayDimensions == passedArgument.CastToArrayReturnType().ArrayDimensions) {
					return InferTypeArgument(expectedArrayElementType, passedArgument.CastToArrayReturnType().ArrayElementType, outputArray);
				} else if (passedArgument.IsConstructedReturnType) {
					switch (passedArgument.FullyQualifiedName) {
						case "System.Collections.Generic.IList":
						case "System.Collections.Generic.ICollection":
						case "System.Collections.Generic.IEnumerable":
							return InferTypeArgument(expectedArrayElementType, passedArgument.CastToConstructedReturnType().TypeArguments[0], 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;
		}
		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;
		}
Example #39
0
		/// <summary>
		/// Make lower bound inference from U for V.
		/// </summary>
		void MakeLowerBoundInference(IReturnType U, IReturnType V)
		{
			Log(" MakeLowerBoundInference from " + U + " for " + V);
			if (U == null || V == null)
				return;
			
			// If V is one of the unfixed Xi then U is added to the set of bounds for Xi.
			TP tp = GetTPForType(V);
			if (tp != null && tp.Fixed == false) {
				Log("  Add bound '" + U.DotNetName + "' to " + tp);
				tp.Bounds.Add(U);
				return;
			}
			// Otherwise if U is an array type Ue[…] and V is either an array type Ve[…]of the
			// same rank, or if U is a one­dimensional array type Ue[]and V is one of
			// IEnumerable<Ve>, ICollection<Ve> or IList<Ve> then
			ArrayReturnType arrU = U.CastToArrayReturnType();
			ArrayReturnType arrV = V.CastToArrayReturnType();
			ConstructedReturnType CV = V.CastToConstructedReturnType();
			if (arrU != null &&
			    (arrV != null && arrU.ArrayDimensions == arrV.ArrayDimensions
			     || (arrU.ArrayDimensions == 1 && IsIEnumerableCollectionOrList(CV))))
			{
				IReturnType Ue = arrU.ArrayElementType;
				IReturnType Ve = arrV != null ? arrV.ArrayElementType : CV.TypeArguments[0];
				// If Ue is known to be a reference type then a lower­bound inference from Ue to Ve is made
				if (IsReferenceType(Ue) ?? false) {
					MakeLowerBoundInference(Ue, Ve);
				} else {
					// Otherwise an exact inference from Ue to Ve is made
					MakeExactInference(Ue, Ve);
				}
				return;
			}
			// Otherwise if V is a constructed type C<V1…Vk> and there is a unique set of
			// types U1…Uk such that a standard implicit conversion exists from U to C<U1…Uk>
			// then an exact inference is made from each Ui for the corresponding Vi.
			if (CV != null) {
				foreach (IReturnType U2 in MemberLookupHelper.GetTypeInheritanceTree(U)) {
					ConstructedReturnType CU2 = U2.CastToConstructedReturnType();
					if (CU2 != null &&
					    object.Equals(CU2.UnboundType, CV.UnboundType) &&
					    CU2.TypeArgumentCount == CV.TypeArgumentCount
					    && CU2.TypeArguments.Count == CU2.TypeArgumentCount // unfortunately these might not be the same...
					    && CV.TypeArguments.Count == CV.TypeArgumentCount)
					{
						for (int i = 0; i < CU2.TypeArgumentCount; i++) {
							MakeExactInference(CU2.TypeArguments[i], CV.TypeArguments[i]);
						}
						return;
					}
				}
			}
		}
Example #40
0
		void AppendReturnType(StringBuilder builder, IReturnType returnType, bool forceFullyQualifiedName)
		{
			IReturnType arrayReturnType = returnType;
			returnType = GetElementType(returnType);
			
			if (returnType == null)
				return;
			
			string fullName = returnType.FullyQualifiedName;
			string shortName;
			bool isConstructedType = returnType.IsConstructedReturnType;
			if (fullName != null && !isConstructedType && TypeConversionTable.TryGetValue(fullName, out shortName)) {
				builder.Append(shortName);
			} else {
				IClass c = returnType.GetUnderlyingClass();
				
				if (c != null) {
					IList<IReturnType> ta = isConstructedType ? returnType.CastToConstructedReturnType().TypeArguments : null;
					AppendClassNameWithTypeParameters(builder, c, forceFullyQualifiedName || UseFullyQualifiedTypeNames, false, ta);
				} else {
					if (UseFullyQualifiedTypeNames || forceFullyQualifiedName) {
						builder.Append(fullName);
					} else {
						builder.Append(returnType.Name);
					}
					if (isConstructedType) {
						builder.Append('<');
						IList<IReturnType> ta = returnType.CastToConstructedReturnType().TypeArguments;
						for (int i = 0; i < ta.Count; ++i) {
							if (i > 0) builder.Append(", ");
							AppendReturnType(builder, ta[i], false);
						}
						builder.Append('>');
					}
				}
			}
			
			UnpackArrayType(builder, arrayReturnType);
		}
		/// <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;
		}