dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
18.71k stars 3.98k forks source link

IEventSymbol.DeclaringSyntaxReferences Syntax is VariableDeclaratorSyntax not EventDeclarationSyntax #74187

Closed LWehmschulteAtRosenxt closed 1 week ago

LWehmschulteAtRosenxt commented 1 week ago

Version Used: Microsoft.CodeAnalysis.CSharp" Version="4.9.2" Microsoft.CodeAnalysis.Analyzers" Version="3.3.4"

Steps to Reproduce:

  1. Create a class with a simple event declaration
  2. Get Event Symbols from class
// Dummy Class with Event
partial class SomeClass
{
    public event EventHandler? SomeEvent;
}
// SourceGenerator
private static void GetEvent(ITypeSymbol classSymbol) {
    classSymbol
        .GetAllMembers()
        .Where(x => x.Kind == SymbolKind.Event)
        .OfType<IEventSymbol>()
        .Where(x => x.DeclaredAccessibility == Accessibility.Public)
        .Where(x => !x.IsStatic)
        .ToList()
        .ForEach(evt =>
        {
            var syntax = evt.DeclaringSyntaxReferences.First().GetSyntax(); // VariableDeclaratorSyntax
        });
}

Expected Behavior: The syntax variable should be of type EventDeclarationSyntax

Actual Behavior: See the syntax variable is of type VariableDeclaratorSyntax and not of type EventDeclarationSyntax

Additional info When I declare the event with the add/remove body, the syntax is a EventDeclarationSyntax:

// Dummy Class with Event Property
partial class SomeClass
{
    public event EventHandler? SomeEvent { add => /*...*/; remove => /*...*/; }
}
CyrusNajmabadi commented 1 week ago

This is by design. The following is legal/expected in C#:

    public event Action a, b, c;

The declaring syntax reference points to the respective variabledeclarators for a, b, or c to uniquely identify them.

CyrusNajmabadi commented 1 week ago

When I declare the event with the add/remove body, the syntax is a EventDeclarationSyntax:

Right, in this form, you can only have one event, so the entire declaration is returned.

This is the same with fields versus properties. Fields give you back the variable declarators. Properties give back the full declaration.