0

I am following this tutorial, https://learn.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/tutorials/how-to-write-csharp-analyzer-code-fix

What I really want is to detect if a method in a ASP.Net Web API controller is missing my Custom attribute and give hints to the developer to add it.

In my Analyzer's Initilize method, I have chosen MethodDeclaration as the SyntaxKind like this

context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.MethodDeclaration);

In the AnalyzeNode method, I want to detect if the method in question already has the Custom attribute added to it.

    private void AnalyzeNode(SyntaxNodeAnalysisContext context)
    {
        var methodDeclaration = (MethodDeclarationSyntax)context.Node;

        // make sure the declaration isn't already const:
        if (methodDeclaration.AttributeLists.Any(x=> x. ))
        {
            return;
        }

Not sure what needs to be done in this piece of code to find if Custom attribute is already applied.

Eventually I want my code analyzer to let the user add the missing attribute

    [Route("/routex")]
    [Custom()]
    public async Task<IHttpActionResult> AlreadyHasCustomAttribute()
    {
        //everything is good, no hint shown to the user
    }

    [Route("/routey")]
    public async Task<IHttpActionResult> DoesNotHaveCustomAttribute()
    {
        //missing Custom attribute, show hint to the user and add the attribute as a code fix
    }

Please suggest a solution. Thanks.

Danish
  • 694
  • 1
  • 7
  • 15

2 Answers2

2

The easiest thing might be to simply call methodDeclaration.AttributeLists.Any()) just to verify it has attributes at all before proceeding for performance reasons. Once it does, you can call context.SemanticModel.GetDeclaredSymbol(methodDeclaration) and that'll give you an IMethodSymbol which you can call GetAttributes() on. From there, you can walk the list of attributes and find the one you're looking for (or in this casel, find the lack of it.)

Jason Malinowski
  • 18,148
  • 1
  • 38
  • 55
0

There isn't one way to do it. The way I'd personally do this is to first register a compilation start action and get the attribute symbol. Then register a symbol action, and for each method check if any of the attributes match the attribute obtained in compilation start.

This would look similar to the following

context.RegisterCompilationStartAction(context =>
{
    var targetAttribute = context.Compilation.GetTypeByMetadataName("FullyQualifiedAttributeName");
    if (targetAttribute is null)
    {
        // Do whatever you want if the attribute doesn't exist in the first place.
        // Stopping the analysis is probably the best option?
        return;
    }

    context.RegisterSymbolAction(context =>
    {
        var methodSymbol = (IMethodSymbol)context.Symbol;
        if (!methodSymbol.GetAttributes().Any(attrData => targetAttribute.Equals(attrData.AttributeClass, SymbolEqualityComparer.Default))
        {
            // attribute is missing.
            // though it doesn't make sense to report a missing attribute for all methods in a compilation, so you'll likely need extra checks based on the logic of your analyzer.
        }
    }, SymbolKind.Method);
});
Youssef13
  • 3,836
  • 3
  • 24
  • 41