Beispiel #1
0
        private static Setter?GetSetterForMethod(
            Compilation compilation,
            DeserializerTypes types,
            ITypeSymbol rowType,
            IMethodSymbol method,
            Location?location,
            ref ImmutableArray <Diagnostic> diags
            )
        {
            var methodReturnType = method.ReturnType;

            if (methodReturnType.SpecialType != SpecialType.System_Void)
            {
                var diag = Diagnostics.MethodMustReturnVoid(location, method);
                diags = diags.Add(diag);

                return(null);
            }

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

                return(null);
            }

            ITypeSymbol takesValue;
            bool        takesRow;
            bool        takesRowByRef;
            bool        takesContext;

            var ps = method.Parameters;

            if (method.IsStatic)
            {
                // Options:
                //  - take 1 parameter (the result of the parser) or
                //  - take 2 parameters, the result of the parser and an `in ReadContext` or
                //  - take 2 parameters, the row type (which may be passed by ref), and the result of the parser or
                //  - take 3 parameters, the row type (which may be passed by ref), the result of the parser, and `in ReadContext`

                if (ps.Length == 0)
                {
                    var diag = Diagnostics.BadSetterParameters_TooFew(location, method);
                    diags = diags.Add(diag);

                    return(null);
                }
                else if (ps.Length == 1)
                {
                    // take 1 parameter (the result of the parser)

                    var p0 = ps[0];
                    if (p0.RefKind != RefKind.None)
                    {
                        var diag = Diagnostics.BadSetterParameters_StaticOne(location, method);
                        diags = diags.Add(diag);

                        return(null);
                    }

                    takesValue    = p0.Type;
                    takesRow      = false;
                    takesRowByRef = false;
                    takesContext  = false;
                }
                else if (ps.Length == 2)
                {
                    var p1 = ps[1];
                    if (p1.IsInReadContext(types.OurTypes))
                    {
                        // take 2 parameters, the result of the parser and an `in ReadContext`
                        var p0 = ps[0];
                        if (p0.RefKind != RefKind.None)
                        {
                            var diag = Diagnostics.BadSetterParameters_StaticTwo(location, method, rowType);
                            diags = diags.Add(diag);

                            return(null);
                        }

                        takesValue    = p0.Type;
                        takesRow      = false;
                        takesRowByRef = false;
                        takesContext  = true;
                    }
                    else
                    {
                        // take 2 parameters, the row type (which may be passed by ref), and the result of the parser

                        var p0 = ps[0];
                        if (!p0.Type.Equals(rowType, SymbolEqualityComparer.Default))
                        {
                            var diag = Diagnostics.BadSetterParameters_StaticTwo(location, method, rowType);
                            diags = diags.Add(diag);

                            return(null);
                        }

                        var p0RefKind = p0.RefKind;

                        if (!p0RefKind.IsNormalOrByRef())
                        {
                            var diag = Diagnostics.BadSetterParameters_StaticTwo(location, method, rowType);
                            diags = diags.Add(diag);

                            return(null);
                        }

                        if (p1.RefKind != RefKind.None)
                        {
                            var diag = Diagnostics.BadSetterParameters_StaticTwo(location, method, rowType);
                            diags = diags.Add(diag);

                            return(null);
                        }

                        takesValue    = p1.Type;
                        takesRow      = true;
                        takesRowByRef = p0RefKind == RefKind.Ref;
                        takesContext  = false;
                    }
                }
                else if (ps.Length == 3)
                {
                    // take 3 parameters, the row type (which may be passed by ref), the result of the parser, and `in ReadContext`

                    var p0 = ps[0];
                    if (!p0.RefKind.IsNormalOrByRef())
                    {
                        var diag = Diagnostics.BadSetterParameters_StaticThree(location, method, rowType);
                        diags = diags.Add(diag);

                        return(null);
                    }

                    if (!p0.Type.Equals(rowType, SymbolEqualityComparer.Default))
                    {
                        var diag = Diagnostics.BadSetterParameters_StaticThree(location, method, rowType);
                        diags = diags.Add(diag);

                        return(null);
                    }

                    var p1 = ps[1];
                    if (p1.RefKind != RefKind.None)
                    {
                        var diag = Diagnostics.BadSetterParameters_StaticThree(location, method, rowType);
                        diags = diags.Add(diag);

                        return(null);
                    }

                    var p2 = ps[2];
                    if (!p2.IsInReadContext(types.OurTypes))
                    {
                        var diag = Diagnostics.BadSetterParameters_StaticThree(location, method, rowType);
                        diags = diags.Add(diag);

                        return(null);
                    }

                    takesValue    = p1.Type;
                    takesRow      = true;
                    takesRowByRef = p0.RefKind == RefKind.Ref;
                    takesContext  = true;
                }
                else
                {
                    var diag = Diagnostics.BadSetterParameters_TooMany(location, method);
                    diags = diags.Add(diag);

                    return(null);
                }
            }
            else
            {
                takesRow      = false;
                takesRowByRef = false;

                // Options:
                //  - be on the row type, and take 1 parameter (the result of the parser) or
                //  - be on the row type, and take 2 parameters, the result of the parser and an `in ReadContext`

                if (ps.Length == 0)
                {
                    var diag = Diagnostics.BadSetterParameters_TooFew(location, method);
                    diags = diags.Add(diag);

                    return(null);
                }
                else if (ps.Length == 1)
                {
                    // take 1 parameter (the result of the parser) or

                    var p0 = ps[0];
                    if (p0.RefKind != RefKind.None)
                    {
                        var diag = Diagnostics.BadSetterParameters_InstanceOne(location, method);
                        diags = diags.Add(diag);

                        return(null);
                    }

                    takesValue   = p0.Type;
                    takesContext = false;
                }
                else if (ps.Length == 2)
                {
                    // take 2 parameters, the result of the parser and an `in ReadContext`

                    var p0 = ps[0];
                    if (p0.RefKind != RefKind.None)
                    {
                        var diag = Diagnostics.BadSetterParameters_InstanceTwo(location, method);
                        diags = diags.Add(diag);

                        return(null);
                    }

                    var p1 = ps[1];
                    if (!p1.IsInReadContext(types.OurTypes))
                    {
                        var diag = Diagnostics.BadSetterParameters_InstanceTwo(location, method);
                        diags = diags.Add(diag);

                        return(null);
                    }

                    takesValue   = p0.Type;
                    takesContext = true;
                }
                else
                {
                    var diag = Diagnostics.BadSetterParameters_TooMany(location, method);
                    diags = diags.Add(diag);

                    return(null);
                }
            }

            return(new Setter(method, takesValue, takesRow, takesRowByRef, takesContext));
        }