static bool IsConstructedConversionToGenericReturnType(IReturnType from, IReturnType to, IMethod allowGenericTargetsOnThisMethod) { // null could be passed when type arguments could not be resolved/inferred if (from == to) // both are null or { return(true); } if (from == null || to == null) { return(false); } if (from.Equals(to)) { return(true); } if (allowGenericTargetsOnThisMethod == null) { return(false); } if (to.IsGenericReturnType) { ITypeParameter typeParameter = to.CastToGenericReturnType().TypeParameter; if (typeParameter.Method == allowGenericTargetsOnThisMethod) { return(true); } // applicability ignores constraints // foreach (IReturnType constraintType in typeParameter.Constraints) { // if (!ConversionExistsInternal(from, constraintType, allowGenericTargetsOnThisMethod)) { // return false; // } // } return(false); } // for conversions like from IEnumerable<string> to IEnumerable<T>, where T is a GenericReturnType ConstructedReturnType cFrom = from.CastToConstructedReturnType(); ConstructedReturnType cTo = to.CastToConstructedReturnType(); if (cFrom != null && cTo != null) { if (cFrom.FullyQualifiedName == cTo.FullyQualifiedName && cFrom.TypeArguments.Count == cTo.TypeArguments.Count) { for (int i = 0; i < cFrom.TypeArguments.Count; i++) { if (!IsConstructedConversionToGenericReturnType(cFrom.TypeArguments[i], cTo.TypeArguments[i], allowGenericTargetsOnThisMethod)) { return(false); } } return(true); } } return(false); }
/// <summary> /// Gets 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); }
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)); }
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); }
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); }
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)); }
/// <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); }
/// <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; }
/// <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; }