Reputation: 33
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()));
}
Upvotes: 3
Views: 606
Reputation: 2936
I will disappoint you, but Roslyn is a static analyzer and it doesn't have possibility to retrieves dynamic info for types, calls and etc by default.
To achive that, you need to implement a custom dynamic analyzing under roslyn that will investigate all assignment to variable, passing of arguments and etc, to determine all info about object (type, methods and so on) that it can have at the current time in a code.
Just to be clear in the example bellow:
public interface IOperable
{
void Operate();
}
public class Operable : IOperable
{
...
}
public class OperableOther : IOperable
{
...
}
...
IOperable ioperable = new Operable();
ioperable.Operate(); // at this time will invoke Operable.Operate();
ioperable = new OperableOther();
ioperable.Operate(); // at this time will OperableOther.Operate();
Roslyn can retrieve the compile time info about variable ioperable
that it's a IOperable
, but can not give that it will Operable
from first assign and OperableOther
from the second. But you can do that by yourself if you will accumulate all variable modification and etc.
Upvotes: 1