title: Roslyn: How to get the ITypeSymbol associated with an identifier?
body: <p>I'm attempting to write a Roslyn analyzer to detect usages of <code>Enumerable.Count()</code> being called on arrays. Here is the relevant code in my analyzer:</p>
  
  <pre><code>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 &gt; 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;
      }
  
      // ???
  }
  </code></pre>
  
  <p>I'm stuck trying to determine whether the object that <code>Count()</code> is being invoked on is an array. I scanned the API a bit and I see there is an <code>ILocalSymbol</code> with a <code>Type</code> property, and also an <code>IFieldSymbol</code> with a <code>Type</code> 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 <code>IFieldSymbol</code> and <code>ILocalSymbol</code> to e.g. share some common base interface, say <code>IVariableSymbol</code>, that offers you the <code>Type</code> without having to know all the possible places the variable could have come from. However, it seems both interfaces derive directly from <code>ISymbol</code>.</p>
  
  <p>Is the best solution just to do something like this?</p>
  
  <pre><code>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;
          }
  
          ...
      }
  }
  </code></pre>