I'm attempting to write a Roslyn analyzer to detect usages of Enumerable.Count()
being called on arrays. Here is the relevant code in my analyzer:
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(AnalyzeInvocationExpression, SyntaxKind.InvocationExpression);
}
private static void AnalyzeInvocationExpression(SyntaxNodeAnalysisContext context)
{
var invocation = (InvocationExpressionSyntax)context.Node;
var memberAccess = invocation.Expression as MemberAccessExpressionSyntax;
if (!memberAccess.IsKind(SyntaxKind.SimpleMemberAccessExpression))
{
return;
}
Debug.Assert(memberAccess != null);
var ident = memberAccess.Name.Identifier;
// Check whether the method is Count() and there is no parameter list before we try to use the Symbol APIs.
if (ident.ToString() != nameof(Enumerable.Count))
{
return;
}
var arguments = invocation.ArgumentList.Arguments;
if (arguments.Count > 0)
{
return;
}
// Make sure that the subject is an array.
var subject = memberAccess.Expression;
var subjectSymbol = context.SemanticModel.GetSymbolInfo(subject).Symbol;
if (subjectSymbol == null)
{
return;
}
// ???
}
I'm stuck trying to determine whether the object that Count()
is being invoked on is an array. I scanned the API a bit and I see there is an ILocalSymbol
with a Type
property, and also an IFieldSymbol
with a Type
property that will both presumably get you the type of the object. However, I don't know whether the object I'm analyzing is a local/field/result of a method call/etc, so I would expect IFieldSymbol
and ILocalSymbol
to e.g. share some common base interface, say IVariableSymbol
, that offers you the Type
without having to know all the possible places the variable could have come from. However, it seems both interfaces derive directly from ISymbol
.
Is the best solution just to do something like this?
internal static class SymbolUtilities
{
public static ITypeSymbol GetType(ISymbol symbol)
{
if (symbol is IFieldSymbol)
{
return ((IFieldSymbol)symbol).Type;
}
if (symbol is ILocalSymbol)
{
return ((ILocalSymbol)symbol).Type;
}
...
}
}
You can get the information about the type, using the method GetTypeInfo
of the SemanticModel
class:
ITypeSymbol subjectType = context.SemanticModel.GetTypeInfo(subject).Type;
You will find more details about it in the article
"Introduction to Roslyn and its use in program development"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With