Esempio n. 1
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));
        }
Esempio n. 2
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));
        }
Esempio n. 3
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));
        }
Esempio n. 4
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));
        }