protected override bool DoesConversionExist(Compilation compilation, ITypeSymbol source, ITypeSymbol destination) { return compilation.ClassifyConversion(source, destination).Exists; }
private bool IsBaseOrIdentity(ITypeSymbol source, ITypeSymbol dest) { Conversion conversion = _compilation.ClassifyConversion(source, dest); return(conversion.IsIdentity || (conversion.IsReference && conversion.IsImplicit)); }
protected override bool DoesConversionExist(Compilation compilation, ITypeSymbol source, ITypeSymbol destination) { return(compilation.ClassifyConversion(source, destination).Exists); }
protected override bool IsImplicitReferenceConversion(Compilation compilation, ITypeSymbol sourceType, ITypeSymbol targetType) { var conversion = compilation.ClassifyConversion(sourceType, targetType); return(conversion.IsImplicit && conversion.IsReference); }
protected override bool IsAssignableTo(Compilation compilation, ITypeSymbol fromSymbol, ITypeSymbol toSymbol) { var conversion = compilation.ClassifyConversion(fromSymbol, toSymbol); return(conversion.Exists && conversion.IsExplicit == false && conversion.IsNumeric == false); }
protected override bool IsReferenceConversion(Compilation compilation, ITypeSymbol sourceType, ITypeSymbol targetType) { return(compilation.ClassifyConversion(sourceType, targetType).IsReference); }
private static Parser?GetParser( Compilation compilation, AttributedMembers attrMembers, DeserializerTypes types, ITypeSymbol toParseType, Location?location, ImmutableArray <AttributeSyntax> attrs, ref ImmutableArray <Diagnostic> diags ) { var parser = Utils.GetMethodFromAttribute( attrMembers, "ParserType", Diagnostics.ParserTypeSpecifiedMultipleTimes, "ParserMethodName", Diagnostics.ParserMethodNameSpecifiedMultipleTimes, Diagnostics.ParserBothMustBeSet, location, attrs, ref diags ); if (parser == null) { return(null); } var(type, name) = parser.Value; var parserMtd = Utils.GetMethod(type, name, location, ref diags); if (parserMtd == null) { return(null); } var methodReturnType = parserMtd.ReturnType; if (methodReturnType.SpecialType != SpecialType.System_Boolean) { var diag = Diagnostics.MethodMustReturnBool(location, parserMtd); diags = diags.Add(diag); return(null); } if (!parserMtd.IsStatic) { var diag = Diagnostics.MethodNotStatic(location, parserMtd); diags = diags.Add(diag); return(null); } var accessible = parserMtd.IsAccessible(attrMembers); if (!accessible) { var diag = Diagnostics.MethodNotPublicOrInternal(location, parserMtd); diags = diags.Add(diag); return(null); } var ps = parserMtd.Parameters; if (ps.Length != 3) { var diag = Diagnostics.BadParserParameters(location, parserMtd); diags = diags.Add(diag); return(null); } // Parameters // * ReadOnlySpan(char) // * in ReadContext, // * out assignable to outputType var p0 = ps[0]; if (!p0.IsNormalParameterOfType(compilation, types.Framework.ReadOnlySpanOfChar)) { var diag = Diagnostics.BadParserParameters(location, parserMtd); diags = diags.Add(diag); return(null); } var p1 = ps[1]; if (!p1.IsInReadContext(types.OurTypes)) { var diag = Diagnostics.BadParserParameters(location, parserMtd); diags = diags.Add(diag); return(null); } var p2 = ps[2]; if (p2.RefKind != RefKind.Out) { var diag = Diagnostics.BadParserParameters(location, parserMtd); diags = diags.Add(diag); return(null); } var conversion = compilation.ClassifyConversion(p2.Type, toParseType); var canConvert = conversion.IsImplicit || conversion.IsIdentity; if (!canConvert) { var diag = Diagnostics.BadParserParameters(location, parserMtd); diags = diags.Add(diag); return(null); } return(new Parser(parserMtd, p2.Type)); }
private static bool IsAssignable(Compilation compilation, ITypeSymbol fromSymbol, ITypeSymbol toSymbol) { var conversion = compilation.ClassifyConversion(fromSymbol, toSymbol); return(conversion.IsImplicit && !conversion.IsUserDefined); }
protected override bool IsConvertible(Compilation compilation, ITypeSymbol source, ITypeSymbol destination) { var conversion = compilation.ClassifyConversion(source, destination); return(conversion.Exists && conversion.IsImplicit); }
private static Reset?GetReset( Compilation compilation, AttributedMembers attrMembers, DeserializerTypes types, INamedTypeSymbol rowType, Location?location, ImmutableArray <AttributeSyntax> attrs, ref ImmutableArray <Diagnostic> diags ) { var reset = Utils.GetMethodFromAttribute( attrMembers, "ResetType", Diagnostics.ResetTypeSpecifiedMultipleTimes, "ResetMethodName", Diagnostics.ResetMethodNameSpecifiedMultipleTimes, Diagnostics.ResetBothMustBeSet, location, attrs, ref diags ); if (reset == null) { return(null); } var(type, name) = reset.Value; var resetMtd = Utils.GetMethod(type, name, location, ref diags); if (resetMtd == null) { return(null); } var methodReturnType = resetMtd.ReturnType; if (methodReturnType.SpecialType != SpecialType.System_Void) { var diag = Diagnostics.MethodMustReturnVoid(location, resetMtd); diags = diags.Add(diag); return(null); } if (resetMtd.IsGenericMethod) { var diag = Diagnostics.MethodCannotBeGeneric(location, resetMtd); diags = diags.Add(diag); return(null); } var accessible = resetMtd.IsAccessible(attrMembers); if (!accessible) { var diag = Diagnostics.MethodNotPublicOrInternal(location, resetMtd); diags = diags.Add(diag); return(null); } var ps = resetMtd.Parameters; bool isStatic; bool takesRow; bool takesRowByRef; bool takesContext; if (resetMtd.IsStatic) { isStatic = true; // Options: // - zero parameters or // - a single parameter of the row type or // - a single parameter of `in ReadContext` or // - two parameters, the first of the row type (which may be by ref) and the second of `in ReadContext` if (ps.Length == 0) { // zero parameters takesRow = false; takesRowByRef = false; takesContext = false; } else if (ps.Length == 1) { var p0 = ps[0]; if (p0.RefKind == RefKind.In) { // a single parameter of `in ReadContext` if (!p0.IsInReadContext(types.OurTypes)) { var diag = Diagnostics.BadResetParameters_StaticOne(location, resetMtd, rowType); diags = diags.Add(diag); return(null); } takesRow = false; takesRowByRef = false; takesContext = true; } else if (p0.RefKind == RefKind.None) { // a single parameter of the row type if (!p0.IsNormalParameterOfType(compilation, rowType)) { var diag = Diagnostics.BadResetParameters_StaticOne(location, resetMtd, rowType); diags = diags.Add(diag); return(null); } takesRow = true; takesRowByRef = false; takesContext = false; } else { var diag = Diagnostics.BadResetParameters_StaticOne(location, resetMtd, rowType); diags = diags.Add(diag); return(null); } } else if (ps.Length == 2) { // two parameters, the first of the row type (which may be by ref) and the second of `in ReadContext` var p0 = ps[0]; if (!p0.RefKind.IsNormalOrByRef()) { var diag = Diagnostics.BadResetParameters_StaticTwo(location, resetMtd, rowType); diags = diags.Add(diag); return(null); } if (!p0.Type.Equals(rowType, SymbolEqualityComparer.Default)) { var diag = Diagnostics.BadResetParameters_StaticTwo(location, resetMtd, rowType); diags = diags.Add(diag); return(null); } var p1 = ps[1]; if (!p1.IsInReadContext(types.OurTypes)) { var diag = Diagnostics.BadResetParameters_StaticTwo(location, resetMtd, rowType); diags = diags.Add(diag); return(null); } takesRow = true; takesRowByRef = p0.RefKind == RefKind.Ref; takesContext = true; } else { var diag = Diagnostics.BadResetParameters_TooMany(location, resetMtd); diags = diags.Add(diag); return(null); } } else { isStatic = false; // be on the row type... var declaredOn = Utils.NonNull(resetMtd.ContainingType); var conversion = compilation.ClassifyConversion(rowType, declaredOn); var canConvert = conversion.IsImplicit || conversion.IsIdentity; if (!canConvert) { var diag = Diagnostics.BadReset_NotOnRow(location, resetMtd, rowType); diags = diags.Add(diag); return(null); } // Options: // - zero parameters or // - a single `in ReadContext` parameter. if (ps.Length == 0) { takesRow = true; takesRowByRef = false; takesContext = false; } else if (ps.Length == 1) { var p0 = ps[0]; if (!p0.IsInReadContext(types.OurTypes)) { var diag = Diagnostics.BadResetParameters_InstanceOne(location, resetMtd); diags = diags.Add(diag); return(null); } takesRow = true; takesRowByRef = false; takesContext = true; } else { var diag = Diagnostics.BadResetParameters_TooMany(location, resetMtd); diags = diags.Add(diag); return(null); } } return(new Reset(resetMtd, isStatic, takesRow, takesRowByRef, takesContext)); }
/// <summary> /// Takes a set of types and returns the most "constrained" type that all of them can be converted to. /// /// Worst case, it returns a TypeSyntax for `object`. /// /// If the appropriate type is an anonymous one, `replaceType` contains a Tuple of that anonymous type and the /// name of a new one that should be created to take its place. /// </summary> private static TypeSyntax FindCommonType(IEnumerable<TypeInfo> info, Compilation comp, out Tuple<NamedTypeSymbol, string> replaceType) { if (info.Any(a => a.Equals(TypeInfo.None))) { replaceType = null; return null; } var allPossibilities = info.SelectMany(i => i.Type.AllInterfaces).OfType<NamedTypeSymbol>().ToList(); allPossibilities.AddRange(info.Select(s => s.Type).OfType<NamedTypeSymbol>()); foreach (var i in info) { var @base = i.Type.BaseType; while (@base != null) { allPossibilities.Add(@base); @base = @base.BaseType; } } // Order so that subclasses are before superclasses, classes are before interfaces, // special interfaces first, and generic types are before non-generic ones // with the special case that System.Object is always the *last* option // uses type name as a tie-breaker for ordering // // Special interfaces are anything that gets special treatment in the language, which for now is IEnumerable<T> and IEnumerable allPossibilities.Sort( (a, b) => { var aIsNotObject = a.TypeKind != TypeKind.Class || a.BaseType != null; var bIsNotObject = b.TypeKind != TypeKind.Class || b.BaseType != null; var aIsNotInterface = a.TypeKind != TypeKind.Interface; var bIsNotInferface = b.TypeKind != TypeKind.Interface; // Get both IEnumerable && IEnumerable<T> var aIsSpecial = a.Name == "IEnumerable"; var bIsSpecial = b.Name == "IEnumerable"; var aIsSubclassOfB = IsSubclass(a, b); var bIsSubclassOfA = IsSubclass(b, a); if (aIsNotObject && !bIsNotObject) return -1; if (bIsNotObject && !aIsNotObject) return 1; if (aIsSubclassOfB) return -1; if (bIsSubclassOfA) return 1; if (aIsNotInterface && !bIsNotInferface) return -1; if (bIsNotInferface && !aIsNotInterface) return 1; if (!aIsNotInterface && !bIsNotInferface) { if (aIsSpecial && !bIsSpecial) return -1; if (bIsSpecial && !aIsSpecial) return 1; } if (a.IsGenericType && !b.IsGenericType) return -1; if (b.IsGenericType && !a.IsGenericType) return 1; return a.MetadataName.CompareTo(b.MetadataName); } ); var commonType = allPossibilities.First( t => { var conversions = info.Select(a => comp.ClassifyConversion(a.Type, t)).ToList(); return conversions.All(a => a.Exists && a.IsImplicit); } ); string fullName; // we actually need to *replace* this type so we can put it in the returns if (commonType.IsAnonymousType) { fullName = "__FTI" + Guid.NewGuid().ToString().Replace("-", ""); replaceType = Tuple.Create(commonType, fullName); } else { fullName = commonType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); replaceType = null; } return Syntax.ParseTypeName(fullName); }
internal static InstanceProvider?ForMethod( Compilation compilation, AttributedMembers attrMembers, DeserializerTypes types, Location?loc, INamedTypeSymbol rowType, INamedTypeSymbol hostType, string mtdName, ref ImmutableArray <Diagnostic> diags ) { var instanceProviderMtd = Utils.GetMethod(hostType, mtdName, loc, ref diags); if (instanceProviderMtd == null) { return(null); } var instanceProviderLoc = instanceProviderMtd.Locations.FirstOrDefault(); var methodReturnType = instanceProviderMtd.ReturnType; if (methodReturnType.SpecialType != SpecialType.System_Boolean) { var diag = Diagnostics.MethodMustReturnBool(instanceProviderLoc, instanceProviderMtd); diags = diags.Add(diag); return(null); } if (!instanceProviderMtd.IsStatic) { var diag = Diagnostics.MethodNotStatic(instanceProviderLoc, instanceProviderMtd); diags = diags.Add(diag); return(null); } var accessible = instanceProviderMtd.IsAccessible(attrMembers); if (!accessible) { var diag = Diagnostics.MethodNotPublicOrInternal(instanceProviderLoc, instanceProviderMtd); diags = diags.Add(diag); return(null); } var ps = instanceProviderMtd.Parameters; if (ps.Length != 2) { var diag = Diagnostics.BadInstanceProviderParameters(instanceProviderLoc, instanceProviderMtd); diags = diags.Add(diag); return(null); } var p0 = ps[0]; if (!p0.IsInReadContext(types.OurTypes)) { var diag = Diagnostics.BadInstanceProviderParameters(instanceProviderLoc, instanceProviderMtd); diags = diags.Add(diag); return(null); } var p1 = ps[1]; if (p1.RefKind != RefKind.Out) { var diag = Diagnostics.BadInstanceProviderParameters(instanceProviderLoc, instanceProviderMtd); diags = diags.Add(diag); return(null); } var conversion = compilation.ClassifyConversion(p1.Type, rowType); var canConvert = conversion.IsImplicit || conversion.IsIdentity; if (!canConvert) { var diag = Diagnostics.BadInstanceProviderParameters(instanceProviderLoc, instanceProviderMtd); diags = diags.Add(diag); return(null); } return(new InstanceProvider(false, instanceProviderMtd, p1.Type)); }
private static bool CanBeSameType(ITypeSymbol actualType, ITypeSymbol expectedType, Compilation compilation) { var conversion = compilation.ClassifyConversion(actualType, expectedType); return(conversion.IsIdentity || conversion.IsReference); }
protected override bool IsConversionImplicit(Compilation compilation, ITypeSymbol sourceType, ITypeSymbol targetType) { return(compilation.ClassifyConversion(sourceType, targetType).IsImplicit); }
protected override bool CanCast(Compilation compilation, ITypeSymbol sourceSymbol, ITypeSymbol destinationSymbol) { return(compilation.ClassifyConversion(sourceSymbol, destinationSymbol).Exists); }
public static bool IsImplicitConversion(Compilation compilation, ITypeSymbol source, ITypeSymbol destination) => compilation.ClassifyConversion(source: source, destination: destination).IsImplicit;
internal static bool AreEquivalent(TypeSymbol a, TypeSymbol b, Compilation comp) { var aMembers = a.GetMembers().OfType<PropertySymbol>().ToList(); var bMembers = b.GetMembers().OfType<PropertySymbol>().ToList(); if (aMembers.Count != bMembers.Count) return false; for (var i = 0; i < aMembers.Count; i++) { var aMember = aMembers[i]; var bMember = bMembers[i]; if (aMember.Name != bMember.Name) return false; if (aMember.DeclaredAccessibility != bMember.DeclaredAccessibility) return false; var aType = aMember.Type; var bType = bMember.Type; var aName = aType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); var bName = bType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); if (aName == bName) continue; var conv = comp.ClassifyConversion(aType, bType); if (!conv.IsIdentity) return false; } return true; }