Search code examples
c#roslynsourcegenerators

Find modifiers with roslyn at semantic level


I can get MemberDeclarationSyntax.Modifiers at syntaxic level, but once I'm at semantic level, dealing with ISymbol, I don't know how to get back the modifiers of such given ISymbol ?

In my use case, a source generator, I want to fetch all contextual modifiers of a partial property declaration (especially including that partial keyword) to generate its implementation.

For reference here is my code with MemberDeclarationSyntax

var contextualModifiers = memberDeclarationSyntax?.Modifiers
  .Where(syntaxToken => syntaxToken.IsContextualKeyword());

I can't find a way when working with an IPropertySymbol instead.


Solution

  • Source generators are awesome, but super confusing! Let me shine a light on them, because I think you actually have a problem X, and you are looking to solution to problem Y.

    When you work with Syntax you will have access to every node of the syntax tree of this one file you are currently in. This probably is the better way you want to proceed.

    When you switch to semantic model and start working with Symbols compiler already did some processing on the source and combined all partial classes together.

    An example of two files:

    One.foo.cs

    public partial class One
    {
       public bool First { get; set; }
    }
    

    One.bar.cs

    public partial class One
    {
       public bool Second { get; set; }
    }
    

    When working with Syntax Those will be two separate syntax trees and you will not be able to see the One.Second property while working on file One.foo.cs.

    When switching to semantic model those two classes will be merged to one entity of type INamedTypeSymbol, and I'm not sure that this is what you actually want.

    Now to your Y problem

    You have memberDeclarationSyntax so you can do this:

    var symbol = context.SemanticModel.GetDeclaredSymbol(memberDeclarationSyntax);
    

    This will get you an ISymbol, because it's a common interface of all symbols, and in C# a method needs a return type. But in reality it's actually an object of class IPropertySymbol so all you need is to cast it.

    var propertySymbol = (IPropertySymbol)symbol;
    

    and now you can just check one of the properties to see if compiler detected it as a "partial" definition.

    if(propertySymbol.IsPartialDefinition)
    {
        // DO STUFF
    }