Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save sixlettervariables/a75ebefbe889737e415174a801f83581 to your computer and use it in GitHub Desktop.
Save sixlettervariables/a75ebefbe889737e415174a801f83581 to your computer and use it in GitHub Desktop.
Sample code to run the .Net Framework Compatibility Diagnostics outside of VS
using System;
using System.Collections.Immutable;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Registration;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.MSBuild;
using Microsoft.CodeAnalysis.Text;
namespace FindCompatibilityProblems
{
class Program
{
private static void Main(string[] args)
{
foreach (var solutionPath in args)
{
using (var writer = File.CreateText(Path.GetFileName(solutionPath) + ".diags"))
{
MainAsync(solutionPath, writer).GetAwaiter().GetResult();
}
}
}
public static async Task MainAsync(string solutionPath, TextWriter writer)
{
var additionalFiles = ImmutableArray.Create<AdditionalText>(new FileAdditionalText(@"dotnet_compatibility.json"));
var analyzers = FindAllAnalyzers();
var solution = await MSBuildWorkspace.Create().OpenSolutionAsync(solutionPath).ConfigureAwait(false);
foreach (Project project in solution.Projects)
{
var compilation = await project.GetCompilationAsync().ConfigureAwait(false);
var compilationWithAnalyzers = compilation.WithAnalyzers(analyzers, new AnalyzerOptions(additionalFiles));
var diagnostics = await compilationWithAnalyzers.GetAnalyzerDiagnosticsAsync().ConfigureAwait(false);
writer.WriteLine($"{project.Name}: {diagnostics.Length} diagnostics");
foreach (Diagnostic diagnostic in diagnostics)
{
writer.WriteLine(diagnostic);
}
writer.WriteLine("----------------------------------------");
}
}
private static ImmutableArray<DiagnosticAnalyzer> FindAllAnalyzers()
{
var registrationBuilder = new RegistrationBuilder();
registrationBuilder.ForTypesDerivedFrom<DiagnosticAnalyzer>()
.SetCreationPolicy(CreationPolicy.NonShared)
.Export<DiagnosticAnalyzer>();
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new DirectoryCatalog(@".", "Microsoft.DotNet.*.dll", registrationBuilder));
var container = new CompositionContainer(catalog, true);
var analyzers = container.GetExportedValues<DiagnosticAnalyzer>().ToImmutableArray();
return analyzers;
}
public class FileAdditionalText : AdditionalText
{
private readonly SourceText _contents;
public FileAdditionalText(string path)
{
Path = path;
_contents = SourceText.From(File.ReadAllText(path));
}
public override string Path { get; }
public override SourceText GetText(CancellationToken cancellationToken = default(CancellationToken))
{
return _contents;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment