7

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.

Community
  • 1
  • 1
Robin Theilade
  • 193
  • 1
  • 7

1 Answers1

5

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.

Jason Malinowski
  • 18,148
  • 1
  • 38
  • 55
  • The analyzer code you linked to looks quite interesting although I'm not sure what kind of internal scope you're referring to. Is it code accessibility, project wide, solution wide, non-referenced assemblies and not shared source projects? – Robin Theilade Sep 15 '15 at 09:10
  • It will only flag types that can be determined to be unused in a single project. So it'll flag types or members that are private or internal. Public types won't be flagged, since it can't find references in a different project. – Jason Malinowski Sep 15 '15 at 15:03
  • And for Roslyn our definition of "project" is really "invocation of the compiler". For shared projects, those work by contributing the files into two or more "real" projects that actually compile stuff. So it's analyzing those "real" projects, with the shared files included. – Jason Malinowski Sep 15 '15 at 15:04
  • Analyzer no longer exists – Cameron MacFarland Sep 23 '16 at 08:08
  • Serves me well for not using a permalink. Fixed. Thanks @CameronMacFarland. – Jason Malinowski Sep 27 '16 at 17:48