Search code examples
c#roslyn-code-analysis

Checking a property execution body for a particular method invocation


I am working on an analyzer for C# compiler. One of my tasks is to ensure that set method of every class property is calling a particular method in its execution body.

Assume I have the following simple classes:

public class SomeClass
{
    public void SetPropertyValue(int propertyValue)
    {
        // some code here
    }
}

public class MyClass : SomeClass
{
    public int MyProperty1
    {
        set => SetPropertyValue(value);
    }

    public int MyProperty2
    {
        set => AnotherMethod(value);
    }
}

Assume class declaration object is stored in myClassTypeSymbol with type INamedTypeSymbol.

I get all property objects for analysis via the call:

var propertyObjects = myClassTypeSymbol.OfType<IPropertySymbol>();

Now, propertyObjects contains Enumeration with MyProperty1 and MyProperty2 inside.

I iterate over this enumeration and get set method for every property.

 foreach (var onePropertyObject in propertyObjects)
 {
     IMethodSymbol setMethod = onePropertyObject.SetMethod;

     // setMethod contains "set" method of a processing property.

     // how can I test here, 
     // that setMethod contains invocation of SetPropertyValue() method?
 }

Solution

  • As far as I understood from the documentation there's no way to obtain method body from setMethod variable.

    But it is possible if we work with syntax tree and process syntax tree nodes.

    Use CSharpSyntaxTree to parse code, like that:

    var tree = CSharpSyntaxTree.ParseText(@"
       // code to be analyzed goes here
    ");
    

    Then get the root node for the syntax tree:

    SyntaxNode rootNode = tree.GetRoot();
    

    And then you can get declared classes, methods and properties:

    var classes = rootNode.DescendantNodes().OfType<ClassDeclarationSyntax>();
    var methods = rootNode.DescendantNodes().OfType<MethodDeclarationSyntax>();
    var properties = rootNode.DescendantNodes().OfType<PropertyDeclarationSyntax>();
    

    Then use DescendantNodes() call to get descendant syntax nodes and GetText() to get the node text to be analyzed.

    That's it.