Пример #1
0
        internal static ImmutableArray <AttributeSyntax> GetConfigurationAttributes(
            AttributedMembers attrMembers,
            ITypeSymbol attributeType,
            FrameworkTypes frameworkTypes,
            ISymbol member
            )
        {
            if (!attrMembers.AttributedSymbolsToAttributes.TryGetValue(member, out var attrs))
            {
                return(ImmutableArray <AttributeSyntax> .Empty);
            }

            var relevantAttributes = ImmutableArray.CreateBuilder <AttributeSyntax>();

            foreach (var(attr, attrType) in attrs)
            {
                if (attributeType.Equals(attrType, SymbolEqualityComparer.Default))
                {
                    relevantAttributes.Add(attr);
                }

                if (frameworkTypes.DataMemberAttribute != null && frameworkTypes.DataMemberAttribute.Equals(attrType, SymbolEqualityComparer.Default))
                {
                    relevantAttributes.Add(attr);
                }
            }

            return(relevantAttributes.ToImmutable());
        }
Пример #2
0
        internal static (SerializableMember?Member, ImmutableArray <Diagnostic> Diagnostics) ForField(
            Compilation compilation,
            AttributedMembers attrMembers,
            SerializerTypes types,
            INamedTypeSymbol serializingType,
            IFieldSymbol field,
            ImmutableArray <AttributeSyntax> attrs
            )
        {
            var diags = ImmutableArray <Diagnostic> .Empty;

            var fieldLoc = field.Locations.FirstOrDefault();

            var name     = field.Name;
            var attrName = Utils.GetNameFromAttributes(attrMembers, fieldLoc, attrs, ref diags);

            name = attrName ?? name;

            var getter = new Getter(field);

            int?order = Utils.GetOrderFromAttributes(attrMembers, fieldLoc, types.Framework, types.OurTypes.SerializerMemberAttribute, attrs, ref diags);

            var emitDefaultValue     = true;
            var attrEmitDefaultValue = GetEmitDefaultValueFromAttributes(attrMembers, fieldLoc, attrs, ref diags);

            emitDefaultValue = attrEmitDefaultValue ?? emitDefaultValue;

            var formatter       = GetFormatter(compilation, attrMembers, types, field.Type, fieldLoc, attrs, ref diags);
            var shouldSerialize = GetShouldSerialize(compilation, attrMembers, types, serializingType, fieldLoc, attrs, ref diags);

            return(MakeMember(fieldLoc, types, name, getter, formatter, shouldSerialize, emitDefaultValue, order, diags));
        }
Пример #3
0
        internal static (DeserializableMember?Member, ImmutableArray <Diagnostic> Diagnostics) ForField(
            Compilation compilation,
            AttributedMembers attrMembers,
            DeserializerTypes types,
            INamedTypeSymbol deserializingType,
            IFieldSymbol field,
            ImmutableArray <AttributeSyntax> attrs
            )
        {
            var diags = ImmutableArray <Diagnostic> .Empty;

            var fieldLoc = field.Locations.FirstOrDefault();

            var attrName = Utils.GetNameFromAttributes(attrMembers, fieldLoc, attrs, ref diags);
            var name     = attrName ?? field.Name;
            var setter   = new Setter(field);

            int?order = Utils.GetOrderFromAttributes(attrMembers, fieldLoc, types.Framework, types.OurTypes.DeserializerMemberAttribute, attrs, ref diags);

            var isRequired          = false;
            var attrIsRequiredValue = GetMemberRequiredFromAttributes(attrMembers, fieldLoc, attrs, ref diags);

            isRequired = attrIsRequiredValue ?? isRequired;

            var reset = GetReset(compilation, attrMembers, types, deserializingType, fieldLoc, attrs, ref diags);

            var parser = GetParser(compilation, attrMembers, types, setter.ValueType, fieldLoc, attrs, ref diags);

            return(MakeMember(fieldLoc, types, name, setter, parser, reset, isRequired, order, diags));
        }
Пример #4
0
 internal abstract ImmutableDictionary <INamedTypeSymbol, ImmutableArray <TMemberDescriber> > GetMembersToGenerateFor(
     GeneratorExecutionContext context,
     Compilation compilation,
     ImmutableArray <TypeDeclarationSyntax> toGenerateFor,
     AttributedMembers members,
     TNeededTypes types
     );
Пример #5
0
        internal static InstanceProvider?ForDefault(AttributedMembers attrMembers, INamedTypeSymbol type, ref ImmutableArray <Diagnostic> diags)
        {
            var(isRecord, recordCons, _) = type.IsRecord();
            if (isRecord)
            {
                recordCons = Utils.NonNull(recordCons);

                return(new InstanceProvider(true, recordCons, type));
            }

            var defaultCons = type.InstanceConstructors.SingleOrDefault(p => p.Parameters.Length == 0);

            if (defaultCons != null)
            {
                var accessible = defaultCons.IsAccessible(attrMembers);

                if (!accessible)
                {
                    var diag = Diagnostics.MethodNotPublicOrInternal(defaultCons.Locations.FirstOrDefault(), defaultCons);
                    diags = diags.Add(diag);

                    return(null);
                }

                return(new InstanceProvider(type));
            }
            else
            {
                var diag = Diagnostics.NoInstanceProvider(type.Locations.FirstOrDefault(), type);
                diags = diags.Add(diag);

                return(null);
            }
        }
Пример #6
0
        private static bool?GetMemberRequiredFromAttributes(
            AttributedMembers attrMembers,
            Location?location,
            ImmutableArray <AttributeSyntax> attrs,
            ref ImmutableArray <Diagnostic> diags
            )
        {
            var requiredByte = Utils.GetConstantsWithName <byte>(attrMembers, attrs, "MemberRequired", ref diags);
            var requiredBool = Utils.GetConstantsWithName <bool>(attrMembers, attrs, "IsRequired", ref diags);

            var total = requiredByte.Length + requiredBool.Length;

            if (total > 1)
            {
                var diag = Diagnostics.IsRequiredSpecifiedMultipleTimes(location);
                diags = diags.Add(diag);

                return(null);
            }

            if (total == 0)
            {
                return(null);
            }

            if (requiredByte.Length == 1)
            {
                var byteVal = requiredByte.Single();

                var logicalVal =
                    byteVal switch
                {
                    1 => true,
                    2 => false,
                    _ => default(bool?)
                };

                if (logicalVal == null)
                {
                    var diag = Diagnostics.UnexpectedConstantValue(location, byteVal.ToString(), new[] { "Yes", "No" });
                    diags = diags.Add(diag);

                    return(null);
                }

                return(logicalVal);
            }

            var boolVal = requiredBool.Single();

            return(boolVal);
        }
Пример #7
0
        internal static (SerializableMember?Member, ImmutableArray <Diagnostic> Diagnostics) ForProperty(
            Compilation compilation,
            AttributedMembers attrMembers,
            SerializerTypes types,
            INamedTypeSymbol serializingType,
            IPropertySymbol prop,
            ImmutableArray <AttributeSyntax> attrs
            )
        {
            var diags = ImmutableArray <Diagnostic> .Empty;

            var propLoc = prop.Locations.FirstOrDefault();

            if (prop.GetMethod == null)
            {
                var diag = Diagnostics.NoGetterOnSerializableProperty(propLoc);
                diags = diags.Add(diag);
            }

            if (prop.Parameters.Any())
            {
                var diag = Diagnostics.SerializablePropertyCannotHaveParameters(propLoc);
                diags = diags.Add(diag);
            }

            var name     = prop.Name;
            var attrName = Utils.GetNameFromAttributes(attrMembers, propLoc, attrs, ref diags);

            name = attrName ?? name;

            var getter = new Getter(prop);

            int?order = Utils.GetOrderFromAttributes(attrMembers, propLoc, types.Framework, types.OurTypes.SerializerMemberAttribute, attrs, ref diags);

            var emitDefaultValue     = true;
            var attrEmitDefaultValue = GetEmitDefaultValueFromAttributes(attrMembers, propLoc, attrs, ref diags);

            emitDefaultValue = attrEmitDefaultValue ?? emitDefaultValue;

            var formatter       = GetFormatter(compilation, attrMembers, types, prop.Type, propLoc, attrs, ref diags);
            var shouldSerialize = GetShouldSerialize(compilation, attrMembers, types, serializingType, propLoc, attrs, ref diags);

            // only do this for properties
            shouldSerialize ??= InferDefaultShouldSerialize(attrMembers, types, serializingType, prop.Name, attrs, propLoc, ref diags);

            return(MakeMember(propLoc, types, name, getter, formatter, shouldSerialize, emitDefaultValue, order, diags));
        }
Пример #8
0
        internal static (DeserializableMember?Member, ImmutableArray <Diagnostic> Diagnostics) ForConstructorParameter(
            Compilation compilation,
            AttributedMembers attrMembers,
            DeserializerTypes types,
            INamedTypeSymbol deserializingType,
            IParameterSymbol parameter,
            ImmutableArray <AttributeSyntax> attrs
            )
        {
            var diags = ImmutableArray <Diagnostic> .Empty;

            var parameterLoc = parameter.Locations.FirstOrDefault();

            var attrName = Utils.GetNameFromAttributes(attrMembers, parameterLoc, attrs, ref diags);
            var name     = attrName ?? parameter.Name;
            var setter   = new Setter(parameter);

            int?order = Utils.GetOrderFromAttributes(attrMembers, parameterLoc, types.Framework, types.OurTypes.DeserializerMemberAttribute, attrs, ref diags);

            // note that this defaults to TRUE
            var isRequired          = true;
            var attrIsRequiredValue = GetMemberRequiredFromAttributes(attrMembers, parameterLoc, attrs, ref diags);

            isRequired = attrIsRequiredValue ?? isRequired;

            if (!isRequired)
            {
                var diag = Diagnostics.ParametersMustBeRequired(parameterLoc, deserializingType, parameter);

                diags = diags.Add(diag);

                return(null, diags);
            }

            var reset = GetReset(compilation, attrMembers, types, deserializingType, parameterLoc, attrs, ref diags);

            if (reset != null && !reset.IsStatic)
            {
                var diag = Diagnostics.BadReset_MustBeStaticForParameters(parameterLoc, deserializingType, parameter, reset.Method);
                diags = diags.Add(diag);
                return(null, diags);
            }

            var parser = GetParser(compilation, attrMembers, types, setter.ValueType, parameterLoc, attrs, ref diags);

            return(MakeMember(parameterLoc, types, name, setter, parser, reset, isRequired, order, diags));
        }
Пример #9
0
        internal static (DeserializableMember?Member, ImmutableArray <Diagnostic> Diagnostics) ForProperty(
            Compilation compilation,
            AttributedMembers attrMembers,
            DeserializerTypes types,
            INamedTypeSymbol deserializingType,
            IPropertySymbol prop,
            ImmutableArray <AttributeSyntax> attrs
            )
        {
            var diags = ImmutableArray <Diagnostic> .Empty;

            var propLoc = prop.Locations.FirstOrDefault();

            if (prop.SetMethod == null)
            {
                var diag = Diagnostics.NoSetterOnDeserializableProperty(propLoc);
                diags = diags.Add(diag);
            }

            if (prop.Parameters.Any())
            {
                var diag = Diagnostics.DeserializablePropertyCannotHaveParameters(propLoc);
                diags = diags.Add(diag);
            }

            var attrName = Utils.GetNameFromAttributes(attrMembers, propLoc, attrs, ref diags);
            var name     = attrName ?? prop.Name;
            var setter   = new Setter(prop);

            int?order = Utils.GetOrderFromAttributes(attrMembers, propLoc, types.Framework, types.OurTypes.DeserializerMemberAttribute, attrs, ref diags);

            var isRequired          = false;
            var attrIsRequiredValue = GetMemberRequiredFromAttributes(attrMembers, propLoc, attrs, ref diags);

            isRequired = attrIsRequiredValue ?? isRequired;

            var reset = GetReset(compilation, attrMembers, types, deserializingType, propLoc, attrs, ref diags);

            var parser = GetParser(compilation, attrMembers, types, setter.ValueType, propLoc, attrs, ref diags);

            // only do this for properties
            reset ??= InferDefaultReset(attrMembers, types, deserializingType, prop.Name, attrs, propLoc, ref diags);

            return(MakeMember(propLoc, types, name, setter, parser, reset, isRequired, order, diags));
        }
Пример #10
0
        internal static (SerializableMember?Member, ImmutableArray <Diagnostic> Diagnostics) ForMethod(
            Compilation compilation,
            AttributedMembers attrMembers,
            SerializerTypes types,
            INamedTypeSymbol serializingType,
            IMethodSymbol mtd,
            ImmutableArray <AttributeSyntax> attrs
            )
        {
            var diags = ImmutableArray <Diagnostic> .Empty;

            var mtdLoc = mtd.Locations.FirstOrDefault();

            var attrName = Utils.GetNameFromAttributes(attrMembers, mtdLoc, attrs, ref diags);

            if (attrName == null)
            {
                var diag = Diagnostics.SerializableMemberMustHaveNameSetForMethod(mtdLoc, mtd);
                diags = diags.Add(diag);

                attrName = "--UNKNOWN--";
            }

            var getter = GetGetterForMethod(compilation, types, serializingType, mtd, mtdLoc, ref diags);

            int?order = Utils.GetOrderFromAttributes(attrMembers, mtdLoc, types.Framework, types.OurTypes.SerializerMemberAttribute, attrs, ref diags);

            var emitDefaultValue     = true;
            var attrEmitDefaultValue = GetEmitDefaultValueFromAttributes(attrMembers, mtdLoc, attrs, ref diags);

            emitDefaultValue = attrEmitDefaultValue ?? emitDefaultValue;

            var shouldSerialize = GetShouldSerialize(compilation, attrMembers, types, serializingType, mtdLoc, attrs, ref diags);

            // after this point, we need to know what we're working with
            if (getter == null)
            {
                return(null, diags);
            }

            var formatter = GetFormatter(compilation, attrMembers, types, getter.ForType, mtdLoc, attrs, ref diags);

            return(MakeMember(mtdLoc, types, attrName, getter, formatter, shouldSerialize, emitDefaultValue, order, diags));
        }
Пример #11
0
        internal static (DeserializableMember?Member, ImmutableArray <Diagnostic> Diagnostics) ForMethod(
            Compilation compilation,
            AttributedMembers attrMembers,
            DeserializerTypes types,
            INamedTypeSymbol deserializingType,
            IMethodSymbol mtd,
            ImmutableArray <AttributeSyntax> attrs
            )
        {
            var diags = ImmutableArray <Diagnostic> .Empty;

            var mtdLoc = mtd.Locations.FirstOrDefault();

            var attrName = Utils.GetNameFromAttributes(attrMembers, mtdLoc, attrs, ref diags);

            if (attrName == null)
            {
                var diag = Diagnostics.DeserializableMemberMustHaveNameSetForMethod(mtdLoc, mtd);
                diags = diags.Add(diag);

                attrName = "--UNKNOWN--";
            }

            var setter = GetSetterForMethod(compilation, types, deserializingType, mtd, mtdLoc, ref diags);

            int?order = Utils.GetOrderFromAttributes(attrMembers, mtdLoc, types.Framework, types.OurTypes.DeserializerMemberAttribute, attrs, ref diags);

            var isRequired          = false;
            var attrIsRequiredValue = GetMemberRequiredFromAttributes(attrMembers, mtdLoc, attrs, ref diags);

            isRequired = attrIsRequiredValue ?? isRequired;

            var reset = GetReset(compilation, attrMembers, types, deserializingType, mtdLoc, attrs, ref diags);

            // after this point, we need to know what we're working with
            if (setter == null)
            {
                return(null, diags);
            }

            var parser = GetParser(compilation, attrMembers, types, setter.ValueType, mtdLoc, attrs, ref diags);

            return(MakeMember(mtdLoc, types, attrName, setter, parser, reset, isRequired, order, diags));
        }
Пример #12
0
        internal static Reset?InferDefaultReset(
            AttributedMembers attrMembers,
            DeserializerTypes types,
            ITypeSymbol declaringType,
            string propertyName,
            ImmutableArray <AttributeSyntax> attrs,
            Location?location,
            ref ImmutableArray <Diagnostic> diags
            )
        {
            var ignoredDiags = ImmutableArray <Diagnostic> .Empty;
            var resetType    = Utils.GetTypeConstantWithName(attrMembers, attrs, "ResetType", ref ignoredDiags);
            var resetMethod  = Utils.GetConstantsWithName <string>(attrMembers, attrs, "ResetMethodName", ref ignoredDiags);

            // if anything _tried_ to set a non-default, don't include any defaults
            if (!resetType.IsEmpty || !resetMethod.IsEmpty)
            {
                return(null);
            }

            foreach (var candidate in declaringType.GetMembers("Reset" + propertyName))
            {
                var mtd = candidate as IMethodSymbol;
                if (mtd == null)
                {
                    continue;
                }

                if (mtd.ReturnType.SpecialType != SpecialType.System_Void)
                {
                    continue;
                }

                bool isStatic, takesContext;
                var  ps = mtd.Parameters;

                if (mtd.IsStatic)
                {
                    isStatic = true;

                    if (ps.Length == 0)
                    {
                        takesContext = false;
                    }
                    else if (ps.Length == 1)
                    {
                        takesContext = ps[0].IsInReadContext(types.OurTypes);

                        if (!takesContext && !ps[0].Equals(declaringType, SymbolEqualityComparer.Default))
                        {
                            var diag = Diagnostics.BadResetParameters_StaticOne(location, mtd, ps[0].Type);
                            diags = diags.Add(diag);
                            return(null);
                        }
                    }
                    else
                    {
                        continue;
                    }
                }
                else
                {
                    isStatic     = false;
                    takesContext = false;

                    if (ps.Length != 0)
                    {
                        continue;
                    }
                }

                return(new Reset(mtd, isStatic, false, false, takesContext));
            }

            return(null);
        }
Пример #13
0
        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));
        }
Пример #14
0
        private static Formatter?GetFormatter(
            Compilation compilation,
            AttributedMembers attrMembers,
            SerializerTypes types,
            ITypeSymbol toFormatType,
            Location?location,
            ImmutableArray <AttributeSyntax> attrs,
            ref ImmutableArray <Diagnostic> diags
            )
        {
            var formatter =
                Utils.GetMethodFromAttribute(
                    attrMembers,
                    "FormatterType",
                    Diagnostics.FormatterTypeSpecifiedMultipleTimes,
                    "FormatterMethodName",
                    Diagnostics.FormatterMethodNameSpecifiedMultipleTimes,
                    Diagnostics.FormatterBothMustBeSet,
                    location,
                    attrs,
                    ref diags
                    );

            if (formatter == null)
            {
                return(null);
            }

            var(type, mtd) = formatter.Value;

            var formatterMtd = Utils.GetMethod(type, mtd, location, ref diags);

            if (formatterMtd == null)
            {
                return(null);
            }

            if (formatterMtd.IsGenericMethod)
            {
                var diag = Diagnostics.MethodCannotBeGeneric(location, formatterMtd);
                diags = diags.Add(diag);

                return(null);
            }

            var accessible = formatterMtd.IsAccessible(attrMembers);

            if (!accessible)
            {
                var diag = Diagnostics.MethodNotPublicOrInternal(location, formatterMtd);
                diags = diags.Add(diag);

                return(null);
            }

            if (!formatterMtd.IsStatic)
            {
                var diag = Diagnostics.MethodNotStatic(location, formatterMtd);
                diags = diags.Add(diag);

                return(null);
            }

            if (!formatterMtd.ReturnType.Equals(types.BuiltIn.Bool, SymbolEqualityComparer.Default))
            {
                var diag = Diagnostics.MethodMustReturnBool(location, formatterMtd);
                diags = diags.Add(diag);

                return(null);
            }

            var formatterParams = formatterMtd.Parameters;

            if (formatterParams.Length != 3)
            {
                var diag = Diagnostics.BadFormatterParameters(location, formatterMtd, toFormatType);
                diags = diags.Add(diag);

                return(null);
            }

            var p0 = formatterParams[0];

            if (!p0.IsNormalParameterOfType(compilation, toFormatType))
            {
                var diag = Diagnostics.BadFormatterParameters(location, formatterMtd, toFormatType);
                diags = diags.Add(diag);

                return(null);
            }

            var p1 = formatterParams[1];

            if (!p1.IsInWriteContext(types.OurTypes))
            {
                var diag = Diagnostics.BadFormatterParameters(location, formatterMtd, toFormatType);
                diags = diags.Add(diag);

                return(null);
            }

            var p2 = formatterParams[2];

            if (!p2.IsNormalParameterOfType(compilation, types.Framework.IBufferWriterOfChar))
            {
                var diag = Diagnostics.BadFormatterParameters(location, formatterMtd, toFormatType);
                diags = diags.Add(diag);

                return(null);
            }

            return(new Formatter(formatterMtd, toFormatType));
        }
Пример #15
0
        private static ShouldSerialize?GetShouldSerialize(
            Compilation compilation,
            AttributedMembers attrMembers,
            SerializerTypes types,
            INamedTypeSymbol rowType,
            Location?location,
            ImmutableArray <AttributeSyntax> attrs,
            ref ImmutableArray <Diagnostic> diags
            )
        {
            var shouldSerialize =
                Utils.GetMethodFromAttribute(
                    attrMembers,
                    "ShouldSerializeType",
                    Diagnostics.ShouldSerializeTypeSpecifiedMultipleTimes,
                    "ShouldSerializeMethodName",
                    Diagnostics.ShouldSerializeMethodNameSpecifiedMultipleTimes,
                    Diagnostics.ShouldSerializeBothMustBeSet,
                    location,
                    attrs,
                    ref diags
                    );

            if (shouldSerialize == null)
            {
                return(null);
            }

            var(type, mtd) = shouldSerialize.Value;

            var shouldSerializeMtd = Utils.GetMethod(type, mtd, location, ref diags);

            if (shouldSerializeMtd == null)
            {
                return(null);
            }

            if (shouldSerializeMtd.IsGenericMethod)
            {
                var diag = Diagnostics.MethodCannotBeGeneric(location, shouldSerializeMtd);
                diags = diags.Add(diag);

                return(null);
            }

            var accessible = shouldSerializeMtd.IsAccessible(attrMembers);

            if (!accessible)
            {
                var diag = Diagnostics.MethodNotPublicOrInternal(location, shouldSerializeMtd);
                diags = diags.Add(diag);

                return(null);
            }

            if (!shouldSerializeMtd.ReturnType.Equals(types.BuiltIn.Bool, SymbolEqualityComparer.Default))
            {
                var diag = Diagnostics.MethodMustReturnBool(location, shouldSerializeMtd);
                diags = diags.Add(diag);

                return(null);
            }

            var shouldSerializeParams = shouldSerializeMtd.Parameters;

            var  isStatic = shouldSerializeMtd.IsStatic;
            bool takesContext;
            bool takesRow;

            if (isStatic)
            {
                // can legally take
                // 1. no parameters
                // 2. one parameter, a type which declares the annotated member
                // 3. one parameter, in WriteContext
                // 4. two parameters
                //    1. the type which declares the annotated member, or one which can be assigned to it, and
                //    2. in WriteContext

                if (shouldSerializeParams.Length == 0)
                {
                    // fine!
                    takesContext = false;
                    takesRow     = false;
                }
                else if (shouldSerializeParams.Length == 1)
                {
                    var p0 = shouldSerializeParams[0];

                    if (p0.IsInWriteContext(types.OurTypes))
                    {
                        takesRow     = false;
                        takesContext = true;
                    }
                    else
                    {
                        if (!p0.IsNormalParameterOfType(compilation, rowType))
                        {
                            var diag = Diagnostics.BadShouldSerializeParameters_StaticOne(location, shouldSerializeMtd, rowType);
                            diags = diags.Add(diag);

                            return(null);
                        }

                        takesRow     = true;
                        takesContext = false;
                    }
                }
                else if (shouldSerializeParams.Length == 2)
                {
                    var p0 = shouldSerializeParams[0];
                    if (!p0.IsNormalParameterOfType(compilation, rowType))
                    {
                        var diag = Diagnostics.BadShouldSerializeParameters_StaticTwo(location, shouldSerializeMtd, rowType);
                        diags = diags.Add(diag);

                        return(null);
                    }

                    var p1 = shouldSerializeParams[1];
                    if (!p1.IsInWriteContext(types.OurTypes))
                    {
                        var diag = Diagnostics.BadShouldSerializeParameters_StaticTwo(location, shouldSerializeMtd, rowType);
                        diags = diags.Add(diag);

                        return(null);
                    }

                    takesRow     = true;
                    takesContext = true;
                }
                else
                {
                    var diag = Diagnostics.BadShouldSerializeParameters_TooMany(location, shouldSerializeMtd);
                    diags = diags.Add(diag);

                    return(null);
                }
            }
            else
            {
                // can legally take
                //   1. no parameters
                //   2. one in WriteContext parameter

                var onType = shouldSerializeMtd.ContainingType;

                if (!onType.Equals(rowType, SymbolEqualityComparer.Default))
                {
                    var diag = Diagnostics.ShouldSerializeInstanceOnWrongType(location, shouldSerializeMtd, rowType);
                    diags = diags.Add(diag);

                    return(null);
                }

                takesRow = true;

                if (shouldSerializeParams.Length == 0)
                {
                    takesContext = false;
                }
                else if (shouldSerializeParams.Length == 1)
                {
                    var p0 = shouldSerializeParams[0];
                    if (!p0.IsInWriteContext(types.OurTypes))
                    {
                        var diag = Diagnostics.BadShouldSerializeParameters_InstanceOne(location, shouldSerializeMtd);
                        diags = diags.Add(diag);

                        return(null);
                    }

                    takesContext = true;
                }
                else
                {
                    var diag = Diagnostics.BadShouldSerializeParameters_TooMany(location, shouldSerializeMtd);
                    diags = diags.Add(diag);

                    return(null);
                }
            }

            return(new ShouldSerialize(shouldSerializeMtd, isStatic, takesRow, takesContext));
        }
Пример #16
0
        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));
        }
Пример #17
0
 internal abstract ImmutableArray <TypeDeclarationSyntax> GetTypesToGenerateFor(AttributedMembers attrMembers, TNeededTypes types);
Пример #18
0
 // todo: can this be made to handle InternalsVisibleTo?
 internal static bool IsAccessible(this IMethodSymbol mtd, AttributedMembers attrMembers)
 => mtd.DeclaredAccessibility == Accessibility.Public ||
 (attrMembers.CompilingAssembly.Equals(mtd.ContainingAssembly, SymbolEqualityComparer.Default) &&
  mtd.DeclaredAccessibility == Accessibility.Internal);
Пример #19
0
        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));
        }