Robin Theilade Robin Theilade - 2 months ago 31
C# Question

Visual Studio Code Analyzer: Finding types with zero references

I'm trying to program a code analyzer that looks for types that isn't referenced from any other type in the Visual Studio 2015 solution.

My problem is that I cannot figure out how to find the list of unreferenced types.

I've tried through the DOM as you can see from the code below, but I don't know where to navigate and the current code already seems slow.

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using System.Collections.Immutable;
using System.Linq;

namespace AlphaSolutions.CodeAnalysis
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class ZeroReferencesDiagnosticAnalyzer : DiagnosticAnalyzer
{
public const string DiagnosticId = "ZeroReferences";

private static DiagnosticDescriptor rule = new DiagnosticDescriptor(
DiagnosticId,
title: "Type has zero code references",
messageFormat: "Type '{0}' is not referenced within the solution",
category: "Naming",
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true,
description: "Type should have references."
);

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
{
get
{
return ImmutableArray.Create(rule);
}
}

public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(this.AnalyzeSyntaxNode, SyntaxKind.ClassDeclaration);
}

private void AnalyzeSyntaxNode(SyntaxNodeAnalysisContext obj)
{
var classDeclaration = obj.Node as ClassDeclarationSyntax;
if(classDeclaration == null)
{
return;
}

var identifierNameSyntaxes = classDeclaration
.DescendantNodes()
.OfType<IdentifierNameSyntax>()
.ToArray()
;
if (identifierNameSyntaxes.Length == 0)
{
return;
}

//SymbolFinder.FindReferencesAsync(namedTypeSymbol, solution);
}
}
}


I have also tried
SymbolFinder.FindReferencesAsync(namedTypeSymbol, solution)
but I can't figure out how to obtain a reference to
Solution
.

A reply on Microsoft Answers even suggest using FindReferences method from the
Roslyn.Services
assembly. But it looks like that assembly is deprecated.

I know CodeLens i counting references, getting access to that counter might be an even better solution but I'm guessing that it is impossible.

Before anyone suggests duplicate post, this post is NOT a duplicate of this, this or this. My post is specific to analyzers for the Roslyn compiler.

Answer

Roslyn diagnostic analyzers don't currently allow you to do solution-wide (i.e. cross-project) analysis, which is why we don't give you a Solution object. This was partially for performance considerations: if you tried to call FindReferencesAsync everywhere your CPU would be pegged pretty heavily. For CodeLens there was large amount of feedback for how much CPU we were using, we didn't want 10 diagnostics all consuming that same amount of CPU. (Imagine your poor laptop battery...)

If you're OK with this being more limited, say finding internal types that are unused in the project they're within, take a look at this analyzer we wrote awhile back.

Comments