0

I have created a diagnostic analyzer which reports various issues with custom attributes for properties. However, I am having trouble get the location of only the attribute and/or attribute arguments (depending on the specific diagnostic being reported).

As there are (currently) two attributes that need to be analyzed, I created a helper method which determines if the attribute exists on the property:

private static bool HasAttribute(SyntaxNodeAnalysisContext context, string attributeName, out PropertyAttributeData data)
{
    var propertyDeclarationSyntax = (PropertyDeclarationSyntax)context.Node;

    data = new PropertyAttributeData
    {
        Type = propertyDeclarationSyntax.Type
    };

    var propertyAttribute = propertyDeclarationSyntax.AttributeLists.FirstOrDefault()
                ?.GetAttributes(context.Compilation)
                ?.FirstOrDefault(attr => attr.AttributeClass?.Name == attributeName);

    if (propertyAttribute == null)
    {
        return false;
    }

    data.AttributeData = propertyAttribute;
    data.ConstructorArg1 = propertyAttribute.ConstructorArguments.FirstOrDefault();
    if (propertyAttribute.ConstructorArguments.Length > 1)
    {
        data.ConstructorArg2 = propertyAttribute.ConstructorArguments.Skip(1).FirstOrDefault();
    }

    return true;
}

However, this is where I kind of get stuck. I have been using context.Node.GetLocation for testing purposes, but this underlines the attribute and property. I have also tried using the SemanticModel.GetSymbolInfo() and SemanticModel.GetDeclaredSymbol(), as well as a few other things. However, the location I get back is either from the start of the attribute to the end of the file or it is reporting the original location of the attribute (in a separate library).

How would I go about getting the location of just the attribute or the first/second argument of the it? Any guidance would be appreciated. TIA.

1 Answer 1

1

If you have tried ((AttributeSyntax)attribute).GetLocation() then try attribute.Name.GetLocation() or for argument ((AttributeArgumentSyntax)argument).Expression.GetLocation(). Pretty sure that is what worked for me.

Sign up to request clarification or add additional context in comments.

4 Comments

I looked into your suggestions however I can't figure out on which objects this methods/properties exist. For example, in the suggestion you provided (AttributeSyntax)attribute.GetLocation(), what type is attribute in the sample because I am unable to find any GetLocation method on any of the attribute-related objects I currently have.
@Dominick the AttributeSyntax objects is in the property.AttributeList.Attributes list, and those objects have a .Name which is a NameSyntax object that has the .GetLocation(). On that AttributeSyntax object, you can get the arguments with attribute.ArgumentList.Arguments, the objects in this list are of type AttributeArgumentSyntax, the .Expression on this object also has a .GetLocation(). These GetLocation()'s should be more accurate.
I made a "SyntaxAnalyzer" and i can see that this is what i have done, and i remember having trouble with exactly this too. Some of the attributes i was checking, had a "Type" argument, where parameter was "type = typeof(object)", so to get the "object" underlined, i forexample needed to find out that the expression here was a "PredefinedTypeSyntax", which then has a .Keyword with the correct location.
@Dominick how did it work?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.