Question

Given a MethodDeclarationSyntax object how can I find out the method's declaring type?

My actual problem is that I need to figure it out whether the referenced method is implementing an interface method or not.

For instance, given the code bellow, if I have a MethodDeclarationSyntax for the Dispose() method, how can conclude it is the implementation of the IDisposable.Dispose()?

using System;
abstract class InterfaceImplementation : IDisposable
{
    public abstract void Dispose();
}

I've tried to get the method's declaring type (and check the type) with no success (Parent property gives me back InterfaceImplementation class).

I also have tried to grab the semantic symbol for the method:

var methodSymbol = (MethodSymbol) semanticModel.GetDeclaredSymbol(methodDeclaration);

but could not spot anything that could help me.

Ideas?

Was it helpful?

Solution

Once you have the method symbol, you can ask if a given method is implementing an interface method within a given type. The code is fairly simple:

MethodSymbol method = ...;
TypeSymbol type = method.ContainingType;
MethodSymbol disposeMethod = (MethodSymbol)c.GetSpecialType(SpecialType.System_IDisposable).GetMembers("Dispose").Single();
bool isDisposeMethod = method.Equals(type.FindImplementationForInterfaceMember(disposeMethod));

It's important to note this assumes the type that contains the Dispose method is the type that states it implements IDisposable. In C#, it's possible for a method to implement an interface method that's only stated on a derived type. More concretely, if you ommtted the ": IDisposable" on your code above, and had a derived type of InterfaceImplementation that was IDisposable, that Dispose() method can still implement it.

OTHER TIPS

The syntax types (like MethodDeclarationSyntax) operate only on the syntactic level. At this level, there is no knowledge whether the method Dispose implements IDisposable. That's because you don't know yet what methods IDisposable has. What's more, you don't even know whether IDisposable exists, whether it's a class or interface, or what is its full name. (Is it System.IDisposable? Or MyNamespace.IDisposable?)

To get information like that, you need to get to the semantic level, as you guessed.

I didn't find any way to get from a method to the interface directly, unless it's an explicit interface implementation (EDIT: that's because it's not always possible, see Kevin's comment). But you can get from a type to the implementation of some specific interface method.

So, if you want to find out that a certain MethodSymbol implements IDisposable.Dispose(), you could do something like:

SyntaxTree unit = SyntaxTree.ParseCompilationUnit(code);

MethodDeclarationSyntax method = …;

var compilation = Compilation.Create("test")
    .AddReferences(new AssemblyFileReference(typeof(object).Assembly.Location))
    .AddSyntaxTrees(unit);

SemanticModel model = compilation.GetSemanticModel(unit);

MethodSymbol methodSymbol = (MethodSymbol)model.GetDeclaredSymbol(method);

var typeSymbol = methodSymbol.ContainingType;

var idisposableDisposeSymbol = model.BindExpression(
    0, Syntax.ParseExpression("System.IDisposable.Dispose()")).Symbol;

var implementation = typeSymbol.FindImplementationForInterfaceMember(
    idisposableDisposeSymbol);

bool methodImplementsDispose = methodSymbol == implementation;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top