private static MethodDeclarationSyntax GenerateMethodDeclaration()
        {
            return(MethodDeclaration(
                       Modifiers.Protected_Virtual(),
                       PredefinedBoolType(),
                       Identifier("ShouldVisit"),
                       ParameterList(Parameter(IdentifierName("IPropertySymbol"), "propertySymbol")),
                       Block(
                           SwitchStatement(
                               SimpleMemberAccessExpression(
                                   SimpleMemberAccessExpression(
                                       IdentifierName("propertySymbol"),
                                       IdentifierName("ContainingType")),
                                   IdentifierName("Name")),
                               GenerateSections().ToSyntaxList().Add(DefaultSwitchSection(Block(ThrowNewInvalidOperationException(ParseExpression(@"$""Unrecognized type '{propertySymbol.ContainingType.Name}'""")))))))));

            IEnumerable <SwitchSectionSyntax> GenerateSections()
            {
                foreach (INamedTypeSymbol typeSymbol in Symbols.SyntaxSymbols)
                {
                    if (typeSymbol.IsAbstract)
                    {
                        continue;
                    }

                    SyntaxList <SwitchSectionSyntax> sections = default;

                    foreach (IGrouping <bool, IPropertySymbol> grouping in Symbols.GetPropertySymbols(typeSymbol, skipObsolete: false)
                             .GroupBy(f => f.HasAttribute(MetadataNames.System_ObsoleteAttribute) ||
                                      (typeSymbol.Name == "AnonymousMethodExpressionSyntax" && f.Name == "Block"))
                             .OrderBy(f => f.Key))
                    {
                        if (!grouping.Key)
                        {
                            sections = sections.Add(SwitchSection(GenerateLabels(grouping).ToSyntaxList(), ReturnStatement(TrueLiteralExpression())));
                        }
                        else
                        {
                            sections = sections.Add(SwitchSection(GenerateLabels(grouping).ToSyntaxList(), ReturnStatement(FalseLiteralExpression())));
                        }
                    }

                    Debug.Assert(sections.Any());

                    sections = sections.Add(DefaultSwitchSection(ThrowNewInvalidOperationException(ParseExpression(@"$""Unrecognized property '{propertySymbol.ContainingType.Name}.{propertySymbol.Name}'"""))));

                    yield return(SwitchSection(
                                     CaseSwitchLabel(StringLiteralExpression(typeSymbol.Name)),
                                     Block(
                                         SwitchStatement(
                                             SimpleMemberAccessExpression(IdentifierName("propertySymbol"), IdentifierName("Name")),
                                             sections))));
                }
                static IEnumerable <SwitchSectionSyntax> GenerateSections2(INamedTypeSymbol typeSymbol)
                {
                    int i = 0;

                    foreach (IPropertySymbol propertySymbol in Symbols.GetPropertySymbols(typeSymbol))
                    {
                        yield return(SwitchSection(
                                         CaseSwitchLabel(StringLiteralExpression(propertySymbol.Name)),
                                         ReturnStatement(NumericLiteralExpression(i))));

                        i++;
                    }
                }
        private static MethodDeclarationSyntax GenerateMethodDeclaration()
        {
            return(MethodDeclaration(
                       Modifiers.Public_Static(),
                       PredefinedIntType(),
                       Identifier("GetRank"),
                       ParameterList(Parameter(IdentifierName("IPropertySymbol"), "x")),
                       Block(
                           SwitchStatement(
                               SimpleMemberAccessExpression(
                                   SimpleMemberAccessExpression(
                                       IdentifierName("x"),
                                       IdentifierName("ContainingType")),
                                   IdentifierName("Name")),
                               GenerateSections().ToSyntaxList().Add(DefaultSwitchSection(Block(ThrowNewInvalidOperationException())))))));

            IEnumerable <SwitchSectionSyntax> GenerateSections()
            {
                foreach (INamedTypeSymbol typeSymbol in Symbols.SyntaxSymbols)
                {
                    SyntaxList <SwitchSectionSyntax> sections = GenerateSections2(typeSymbol).ToSyntaxList();

                    if (sections.Count > 1)
                    {
                        yield return(SwitchSection(
                                         CaseSwitchLabel(StringLiteralExpression(typeSymbol.Name)),
                                         Block(
                                             SwitchStatement(
                                                 SimpleMemberAccessExpression(IdentifierName("x"), IdentifierName("Name")),
                                                 sections.Add(DefaultSwitchSection(Block(ThrowNewInvalidOperationException())))))));
                    }
                }

                IEnumerable <SwitchSectionSyntax> GenerateSections2(INamedTypeSymbol typeSymbol)
                {
                    int i = 0;

                    foreach (IPropertySymbol propertySymbol in Symbols.GetPropertySymbols(typeSymbol))
                    {
                        yield return(SwitchSection(
                                         CaseSwitchLabel(StringLiteralExpression(propertySymbol.Name)),
                                         ReturnStatement(NumericLiteralExpression(i))));

                        i++;
                    }
                }
            }
        }