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.Name}'""")))); yield return(SwitchSection( CaseSwitchLabel(StringLiteralExpression(typeSymbol.Name)), Block( SwitchStatement( SimpleMemberAccessExpression(IdentifierName("propertySymbol"), IdentifierName("Name")), sections)))); } IEnumerable <SwitchLabelSyntax> GenerateLabels(IEnumerable <IPropertySymbol> propertySymbols) { foreach (IPropertySymbol propertySymbol in propertySymbols) { yield return(CaseSwitchLabel(StringLiteralExpression(propertySymbol.Name))); } } } }