//--- Class Methods --- private static void AnalyzeSwitchStatement(SyntaxNodeAnalysisContext context) { var semanticModel = context.SemanticModel; IdentifierNameSyntax switchVariable; var missingMembers = EnumSwitchAnalysis.GetMissingEnumMembers((SwitchStatementSyntax)context.Node, semanticModel, out switchVariable); if (missingMembers.Any()) { var switchVariableTypeInfo = semanticModel.GetTypeInfo(switchVariable); var diagnostic = Diagnostic.Create(Rule, context.Node.GetLocation(), switchVariableTypeInfo.Type.Name, string.Join(", ", missingMembers.Select(x => x.Name).ToImmutableArray())); context.ReportDiagnostic(diagnostic); } }
//--- Class Methods --- private static async Task <Document> AddMissingEnumFields(Document document, SyntaxToken typeDecl, CancellationToken cancellationToken) { var semanticModel = await document.GetSemanticModelAsync(cancellationToken); var node = (SwitchStatementSyntax)typeDecl.Parent; IdentifierNameSyntax switchVariable; var missingMembers = EnumSwitchAnalysis.GetMissingEnumMembers(node, semanticModel, out switchVariable); if (missingMembers.Any()) { // get existing switchSections var existingSections = node.DescendantNodes().OfType <SwitchSectionSyntax>().ToImmutableArray(); SwitchSectionSyntax defaultSection = null; if (existingSections.Any() && existingSections.Last().DescendantNodes().OfType <DefaultSwitchLabelSyntax>().Any()) { defaultSection = existingSections.Last(); existingSections = existingSections.Take(existingSections.Length - 1).ToImmutableArray(); } // generate missing case statements var switchVariableTypeInfo = semanticModel.GetTypeInfo(switchVariable); var newCaseStatements = missingMembers.Select(missingMember => SyntaxFactory.CaseSwitchLabel( SyntaxFactory.Token(SyntaxKind.CaseKeyword), SyntaxFactory.MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, SyntaxFactory.IdentifierName(switchVariableTypeInfo.Type.Name), SyntaxFactory.IdentifierName(missingMember.Name) ), SyntaxFactory.Token(SyntaxKind.ColonToken) ) ).Select(caseSection => SyntaxFactory.SwitchSection( SyntaxFactory.List <SwitchLabelSyntax>(new[] { caseSection }), SyntaxFactory.List <StatementSyntax>().Add( SyntaxFactory.ThrowStatement( SyntaxFactory.ObjectCreationExpression( SyntaxFactory.ParseTypeName(nameof(NotImplementedException)), SyntaxFactory.ArgumentList(), null ) ) ) )).ToImmutableArray(); // insert case statements after the last one var tree = await document.GetSyntaxTreeAsync(cancellationToken); var root = (CompilationUnitSyntax)tree.GetRoot(cancellationToken); var switchStatement = SyntaxFactory.SwitchStatement( SyntaxFactory.IdentifierName(switchVariable.Identifier) .WithLeadingTrivia(switchVariable.GetLeadingTrivia()) .WithTrailingTrivia(switchVariable.GetTrailingTrivia()) ).WithSections( new SyntaxList <SwitchSectionSyntax>() .AddRange(existingSections) .AddRange(newCaseStatements) .AddRange(defaultSection == null ? Enumerable.Empty <SwitchSectionSyntax>() : new [] { defaultSection }) ).WithLeadingTrivia(node.GetLeadingTrivia()) .WithTrailingTrivia(node.GetTrailingTrivia()); root = root.ReplaceNode(node, switchStatement); return(document.WithSyntaxRoot(root)); } return(document); }