C# Analyzers: How to enforce XML doc on interface members (and not everything else)?

130 Views Asked by At

I would like to enforce the usage of XML documentation on interface members in C# projects.

I'm looking for the same kind of behavior as SA1600 or CS1591 but limited to interfaces instead of all types.

How can I achieve this?

1

There are 1 best solutions below

1
nalka On BEST ANSWER

You can use a custom DiagnosticSuppressor similar to this :

[DiagnosticAnalyzer(LanguageNames.CSharp)]
internal sealed class MyDiagnosticSuppressor : DiagnosticSuppressor
{
    private static readonly SuppressionDescriptor Rule = new SuppressionDescriptor("SUPCS1591", "CS1591", "Justification");

    public override ImmutableArray<SuppressionDescriptor> SupportedSuppressions => ImmutableArray.Create(Rule);

    public override void ReportSuppressions(SuppressionAnalysisContext context)
    {
        foreach (var diagnostic in context.ReportedDiagnostics)
        {
            if (!context.CancellationToken.IsCancellationRequested)
            {
                Location location = diagnostic.Location;
                SyntaxNode node = location.SourceTree.GetRoot(context.CancellationToken).FindNode(location.SourceSpan);
                if (!(node is InterfaceDeclarationSyntax || HasParentOfType<InterfaceDeclarationSyntax>(node)))
                {
                    context.ReportSuppression(Suppression.Create(Rule, diagnostic));
                }
            }
        }
    }

    public bool HasParentOfType<TSearched>(SyntaxNode syntaxNode) where TSearched : SyntaxNode
    {
        return syntaxNode != null && (syntaxNode.Parent is TSearched || HasParentOfType<TSearched>(syntaxNode.Parent));
    }
}

A few things that you could want to customize based on your question :

  • The rule you're targetting, here we're targetting CS1591 (the second constructor parameter for our SuppressionDescriptor)
  • When to suppress the warning, here we're suppressing it whenever we're not on an interface declaration (node is InterfaceDeclarationSyntax) or within an interface declaration (HasParentOfType<InterfaceDeclarationSyntax>(node))

Note that the current code probably won't behave like you wish in a few edge cases like classes declared within an interface declaration but I think it's a pretty solid basis to start with.