예제 #1
0
        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);
        }
예제 #2
0
        /// <summary>
        /// Gets if the conversion from <paramref name="from"/> to <paramref name="to1"/> is better than
        /// the conversion from <paramref name="from"/> to <paramref name="to2"/>.
        /// </summary>
        /// <returns>
        /// 0 = neither conversion is better<br/>
        /// 1 = from -> to1 is the better conversion<br/>
        /// 2 = from -> to2 is the better conversion.
        /// </returns>
        public static int GetBetterConversion(IReturnType from, IReturnType to1, IReturnType to2)
        {
            if (from == null)
            {
                return(0);
            }
            if (to1 == null)
            {
                return(2);
            }
            if (to2 == null)
            {
                return(1);
            }

            // See ECMA-334, § 14.4.2.3

            // If T1 and T2 are the same type, neither conversion is better.
            if (to1.Equals(to2))
            {
                return(0);
            }
            // If S is T1, C1 is the better conversion.
            if (from.Equals(to1))
            {
                return(1);
            }
            // If S is T2, C2 is the better conversion.
            if (from.Equals(to2))
            {
                return(2);
            }
            bool canConvertFrom1To2 = ConversionExists(to1, to2);
            bool canConvertFrom2To1 = ConversionExists(to2, to1);

            // If an implicit conversion from T1 to T2 exists, and no implicit conversion
            // from T2 to T1 exists, C1 is the better conversion.
            if (canConvertFrom1To2 && !canConvertFrom2To1)
            {
                return(1);
            }
            // If an implicit conversion from T2 to T1 exists, and no implicit conversion
            // from T1 to T2 exists, C2 is the better conversion.
            if (canConvertFrom2To1 && !canConvertFrom1To2)
            {
                return(2);
            }
            if (to1.IsDefaultReturnType && to2.IsDefaultReturnType)
            {
                return(GetBetterPrimitiveConversion(to1, to2));
            }
            // Otherwise, neither conversion is better.
            return(0);
        }
예제 #3
0
        public override bool Equals(IReturnType rt)
        {
            if (rt == null)
            {
                return(false);
            }
            PointerReturnType prt = rt.CastToDecoratingReturnType <PointerReturnType>();

            if (prt == null)
            {
                return(false);
            }
            return(baseType.Equals(prt.baseType));
        }
예제 #4
0
        public override bool Equals(IReturnType rt)
        {
            if (rt == null || !rt.IsArrayReturnType)
            {
                return(false);
            }
            ArrayReturnType art = rt.CastToArrayReturnType();

            if (art.ArrayDimensions != dimensions)
            {
                return(false);
            }
            return(elementType.Equals(art.ArrayElementType));
        }
        IReturnType SearchTypeVB(string type, int typeParameterCount)
        {
            ICompilationUnit cu;

            cu = Prepare(LanguageProperties.VBNet, 0);
            IReturnType c0 = cu.ProjectContent.SearchType(new SearchTypeRequest(type, typeParameterCount, null, cu, 1, 1)).Result;

            Assert.IsNotNull(c0, type + "not found for mode=0");

            cu = Prepare(LanguageProperties.VBNet, 1);
            IReturnType c1 = cu.ProjectContent.SearchType(new SearchTypeRequest(type, typeParameterCount, null, cu, 1, 1)).Result;

            Assert.IsNotNull(c1, type + "not found for mode=1");

            cu = Prepare(LanguageProperties.VBNet, 2);
            IReturnType c2 = cu.ProjectContent.SearchType(new SearchTypeRequest(type, typeParameterCount, null, cu, 1, 1)).Result;

            Assert.IsNotNull(c2, type + "not found for mode=2");

            Assert.IsTrue(c0.Equals(c1) && c0.Equals(c2));

            return(c0);
        }
예제 #6
0
        public virtual bool Equals(IReturnType other)
        {
            // this check is necessary because the underlying Equals implementation
            // expects to be able to retrieve the base type of "other" - which fails when
            // this==other and therefore other.busy.
            if (other == this)
            {
                return(true);
            }

            IReturnType baseType = BaseType;

            using (var l = busyManager.Enter(this)) {
                return((l.Success && baseType != null) ? baseType.Equals(other) : false);
            }
        }
        public virtual bool Equals(IReturnType other)
        {
            // this check is necessary because the underlying Equals implementation
            // expects to be able to retrieve the base type of "other" - which fails when
            // this==other and therefore other.busy.
            if (other == this)
            {
                return(true);
            }

            IReturnType baseType = BaseType;
            bool        tmp      = (baseType != null && TryEnter()) ? baseType.Equals(other) : false;

            Leave();
            return(tmp);
        }
예제 #8
0
        public override bool Equals(object o)
        {
            IReturnType rt = o as IReturnType;

            if (rt == null || !rt.IsArrayReturnType)
            {
                return(false);
            }
            ArrayReturnType art = rt.CastToArrayReturnType();

            if (art.ArrayDimensions != _dimensions)
            {
                return(false);
            }
            return(_elementType.Equals(art.ArrayElementType));
        }
예제 #9
0
        /// <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>
        /// Tests if an implicit conversion exists from "from" to "to".
        /// Conversions from concrete types to generic types are only allowed when the generic type belongs to the
        /// method "allowGenericTargetsOnThisMethod".
        /// </summary>
        static bool ConversionExistsInternal(IReturnType from, IReturnType to, IMethod allowGenericTargetsOnThisMethod)
        {
            // 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 (from == NullReturnType.Instance)
            {
                IClass toClass = to.GetUnderlyingClass();
                if (toClass != null)
                {
                    switch (toClass.ClassType)
                    {
                    case ClassType.Class:
                    case ClassType.Delegate:
                    case ClassType.Interface:
                        return(true);

                    case ClassType.Struct:
                        return(toClass.FullyQualifiedName == "System.Nullable");
                    }
                }
                return(false);
            }

            if ((toIsDefault || to.IsConstructedReturnType || to.IsGenericReturnType) &&
                (fromIsDefault || from.IsArrayReturnType || from.IsConstructedReturnType))
            {
                foreach (IReturnType baseTypeOfFrom in GetTypeInheritanceTree(from))
                {
                    if (IsConstructedConversionToGenericReturnType(baseTypeOfFrom, to, allowGenericTargetsOnThisMethod))
                    {
                        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(ConversionExistsInternal(fromArt.ArrayElementType, toArt.ArrayElementType, allowGenericTargetsOnThisMethod));
                }
            }

            if (from.IsDecoratingReturnType <AnonymousMethodReturnType>() && (toIsDefault || to.IsConstructedReturnType))
            {
                AnonymousMethodReturnType amrt = from.CastToDecoratingReturnType <AnonymousMethodReturnType>();
                IMethod method = CSharp.TypeInference.GetDelegateOrExpressionTreeSignature(to, amrt.CanBeConvertedToExpressionTree);
                if (method != null)
                {
                    if (amrt.HasParameterList)
                    {
                        if (amrt.MethodParameters.Count != method.Parameters.Count)
                        {
                            return(false);
                        }
                        for (int i = 0; i < amrt.MethodParameters.Count; i++)
                        {
                            if (amrt.MethodParameters[i].ReturnType != null)
                            {
                                if (!object.Equals(amrt.MethodParameters[i].ReturnType,
                                                   method.Parameters[i].ReturnType))
                                {
                                    return(false);
                                }
                            }
                        }
                    }
                    IReturnType rt = amrt.ResolveReturnType(method.Parameters.Select(p => p.ReturnType).ToArray());
                    return(ConversionExistsInternal(rt, method.ReturnType, allowGenericTargetsOnThisMethod));
                }
            }

            return(false);
        }
예제 #11
0
		/// <summary>
		/// Gets if the conversion from <paramref name="from"/> to <paramref name="to1"/> is better than
		/// the conversion from <paramref name="from"/> to <paramref name="to2"/>.
		/// </summary>
		/// <returns>
		/// 0 = neither conversion is better<br/>
		/// 1 = from -> to1 is the better conversion<br/>
		/// 2 = from -> to2 is the better conversion.
		/// </returns>
		public static int GetBetterConversion(IReturnType from, IReturnType to1, IReturnType to2)
		{
			if (from == null) return 0;
			if (to1 == null) return 2;
			if (to2 == null) return 1;
			
			// See ECMA-334, § 14.4.2.3
			
			// If T1 and T2 are the same type, neither conversion is better.
			if (to1.Equals(to2)) {
				return 0;
			}
			// If S is T1, C1 is the better conversion.
			if (from.Equals(to1)) {
				return 1;
			}
			// If S is T2, C2 is the better conversion.
			if (from.Equals(to2)) {
				return 2;
			}
			bool canConvertFrom1To2 = ConversionExists(to1, to2);
			bool canConvertFrom2To1 = ConversionExists(to2, to1);
			// If an implicit conversion from T1 to T2 exists, and no implicit conversion
			// from T2 to T1 exists, C1 is the better conversion.
			if (canConvertFrom1To2 && !canConvertFrom2To1) {
				return 1;
			}
			// If an implicit conversion from T2 to T1 exists, and no implicit conversion
			// from T1 to T2 exists, C2 is the better conversion.
			if (canConvertFrom2To1 && !canConvertFrom1To2) {
				return 2;
			}
			if (to1.IsDefaultReturnType && to2.IsDefaultReturnType) {
				return GetBetterPrimitiveConversion(to1, to2);
			}
			// Otherwise, neither conversion is better.
			return 0;
		}
예제 #12
0
		/// <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;
		}