Exemple #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));
        }