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