I'm trying to write a Roslyn analyzer that detects a method call from a specific implementation of an interface but I am having issues with the detection of type of the implementation.
It correctly identifies the method when I use a variable typed as the concrete implementation but not when I use a variable typed as the interface. Mostly trying to figure out how to get the type of the underlying implementation of an interface using the Roslyn Code Analysis Apis
This is the example code to analyze. It correctly detects the second Operate method call but not the first, even though both are using the concrete implementation in Operable
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
IOperable ioperable = new Operable();
ioperable.Operate();
Operable operable = new Operable();
operable.Operate();
}
}
public interface IOperable
{
void Operate();
}
public class Operable : IOperable
{
public void Operate()
{
}
}
}
This is my current source:
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(AnalyzeInvocation, SyntaxKind.InvocationExpression);
}
private static void AnalyzeInvocation(SyntaxNodeAnalysisContext context)
{
var invocation = (InvocationExpressionSyntax)context.Node;
var memberAccess = invocation.Expression as MemberAccessExpressionSyntax;
if (memberAccess == null || !memberAccess.IsKind(SyntaxKind.SimpleMemberAccessExpression))
{
return;
}
var ident = memberAccess.Name.Identifier;
if (ident.ToString().ToLower() != "operate")
{
return;
}
var calledFromType = context.SemanticModel.GetTypeInfo(memberAccess.Expression).Type;
if (calledFromType.MetadataName != "Operable")
{
return;
}
context.ReportDiagnostic(Diagnostic.Create(Rule, context.Node.GetLocation()));
}