Search code examples
c#roslynmicrosoft.codeanalysis

How to get SynthesizedIntrinsicOperatorSymbol instead of SourceUserDefinedOperatorSymbol when doing model.GetDeclaredSymbol


I was having trouble with operator resolution as seen in this question (take a look at this .NET fiddle).

In summary, I had code like the following:

bool a = 3 > 5;
namespace System
{
    public struct Int32
    {
        public static extern bool operator > (int a, int b);
    }
    public struct Boolean { }
}

but when I used GetDeclaredSymbol on the declaration of the operator it gave me a different IMethodSymbol than when I used it in the first line (bool a = 3 > 5;).

I was looking for a method like GetDeclaredSymbol but that would generate the same symbol that is used in the code as in the declaration.

Actual

  • GetDeclaredSymbol -> SourceUserDefinedOperatorSymbol
  • GetSymbolInfo -> SynthesizedIntrinsicOperatorSymbol

Wanted (Expected)

  • GetDeclaredSymbol -> SynthesizedIntrinsicOperatorSymbol
  • GetSymbolInfo -> SynthesizedIntrinsicOperatorSymbol

Basically, I need a way to convert the SourceUserDefinedOperatorSymbol into SynthesizedIntrinsicOperatorSymbol.

Eg.

public static IMethodSymbol GetDeclaredSymbol (OperatorDeclarationSyntax ods)
{
    IMethodSymbol opSym = model.GetDeclaredSymbol(ods) ?? throw E;
    if (opSym is SourceUserDefinedOperatorSymbol)
    {
        // convert it to a SynthesizedIntrinsicOperatorSymbol instead
    }
}

Solution

  • The solution I have gone with (unless I get a better answer) is to declare my operator declarations like the following:

    public static bool operator > (int a, int b) => a > b;
    

    and then to get the symbol for the operator I have the following function:

    public static ISymbol GetDeclaredSymbol(CSharpSyntaxNode? declaration) =>
        declaration is OperatorDeclarationSyntax { ExpressionBody: {} bod } } m &&
        bod.DescendantNodes().OfType<BinaryExpressionSyntax>().SingleOrDefault() is {} bes ?
            model.GetSymbolInfo(bes).Symbol! : model.GetDeclaredSymbol(declaration);