Search code examples
msbuildroslyncode-analysisroslyn-code-analysismicrosoft.codeanalysis

How to add custom roslyn analyzer from locally placed DLL?


I have created a Roslyn Analyzer project which generates a nuget package and DLL of it. I want to use that DLL in a standalone code analysis project. How can i do that? For example i have following code:

MSBuildLocator.RegisterDefaults();
var filePath = @"C:\Users\user\repos\ConsoleApp\ConsoleApp.sln";
var msbws = MSBuildWorkspace.Create();
var soln = await msbws.OpenSolutionAsync(filePath);
var errors = new List<Diagnostic>();
foreach (var proj in soln.Projects)
{
    var analyzer = //Here i want to load analyzer from DLL present locally.
    var compilation = await proj.GetCompilationAsync();
    var compWithAnalyzer = compilation.WithAnalyzers(analyzer.GetAnalyzersForAllLanguages());
    var res = compWithAnalyzer.GetAllDiagnosticsAsync().Result;
    errors.AddRange(res.Where(r => r.Severity == DiagnosticSeverity.Error).ToList());
}

I have tried following

var analyzer = new AnalyzerFileReference("Path to DLL", new AnalyzerAssemblyLoader());

But here AnalyzerAssemblyLoader shows error as it is inaccessible to to its protection level (class is internal).

Kindly suggest me if we can do this.


Solution

  • the .WithAnalyzers() option will allow you to pass an instance of an analyzer. If you're referencing the DLL locally, you can just create the analyzer like you would any other object and pass it to the compilation.

        var analyzer = new MyAnalyzer();
        var compilation = await proj.GetCompilationAsync();
        var compWithAnalyzer = compilation.WithAnalyzers(ImmutableArray.Create<DiagnosticAnalyzer>(analyzer));
    

    If you're not referencing the assembly, but want to load it at runtime, you can use the usual System.Reflection based methods to get an instance of the analyzer:

    var assembly = Assembly.LoadFrom(@"<path to assembly>.dll");
    var analyzers = assembly.GetTypes()
                            .Where(t => t.GetCustomAttribute<DiagnosticAnalyzerAttribute>() is object)
                            .Select(t => (DiagnosticAnalyzer) Activator.CreateInstance(t))
                            .ToArray();
    
    compWithAnalyzers = compilation.WithAnalyzers(ImmutableArray.Create(analyzers));