How to write a Roslyn Analyzer

Roslyn analyzers audit your code for style, quality, maintainability, design and other issues. Because they are powered by the .NET Compiler Platform, they can produce warnings in your code every bit you type even earlier you've finished the line. In other words, y'all don't have to build your code to find out that you made a fault. Analyzers can also surface an automatic lawmaking gear up through the Visual Studio light bulb prompt that allows you to make clean up your lawmaking immediately. With live, project-based code analyzers in Visual Studio, API authors can ship domain-specific code analysis as part of their NuGet packages.

You don't accept to be a professional API author to write an analyzer. In this post, I'll show you lot how to write your very first analyzer.

Getting started

In guild to create a Roslyn Analyzer project, you lot need to install the .NET Compiler Platform SDK via the Visual Studio Installer. There are two different ways to find the .Net Compiler Platform SDK in the Visual Studio Installer:

Install using the Visual Studio Installer – Workloads view:

  1. Run the Visual Studio Installer and select Change.
    Visual Studio Installer
  2. Bank check the Visual Studio extension development workload.
    Visual Studio Extension Development Workload

Install using the Visual Studio Installer – Private components tab:

  1. Run the Visual Studio Installer and select Change.
  2. Select the Individual components tab.
  3. Check the box for .Net Compiler Platform SDK.
    Visual Studio Individual Components

Writing an analyzer

Let's begin past creating a syntax tree analyzer. This analyzer generates a syntax warning for any statement that is non enclosed in a cake that has curly braces { and }. For instance, the following code generates a alert for both the if-statement and the System.Console.WriteLine invocation statement, but the while statement is not flagged:


Brace Analyzer Diagnostic

  1. Open Visual Studio.
  2. On the Create a new project dialog search VSIX and select Analyzer with Lawmaking Set up (.Internet Standard) in C# and click Next.
    Create New Project Dialog
  3. Name your project BraceAnalyzer and click OK. The solution should incorporate 3 projects: BraceAnalyzer, BraceAnalyzer.Test, BraceAnalyzer.Vsix.
    Analyzer Solution Layout
    • BraceAnalyzer: This is the core analyzer project that contains the default analyzer implementation that reports a diagnostic for all blazon names that incorporate any lowercase letter.
    • BraceAnalyzer.Test: This is a unit test projection that lets you make sure your analyzer is producing the right diagnostics and fixes.
    • BraceAnalyzer. Vsix: The VSIX project bundles the analyzer into an extension parcel (.vsix file). This is the startup project in the solution.
  4. In the Solution Explorer, open Resources.resx in the BraceAnalyzer project. This displays the resources editor.
  5. Replace the existing resource string values for AnalyzerDescription, AnalyzerMessageFormat, and AnalyzerTitle with the following strings:
    • Change AnalyzerDescription to Enclose statement with curly braces.
    • Alter AnalyzerMessageFormat to `{` brace expected.
    • Change AnalyzerTitle to Enclose argument with curly braces.


    Resources Resx

  6. Inside the BraceAnalyzerAnalyzer.cs file, supervene upon the Initialize method implementation with the post-obit code:
  7. public override void Initialize(AnalysisContext context) {     context.RegisterSyntaxTreeAction(syntaxTreeContext =>     {         // Iterate through all statements in the tree         var root = syntaxTreeContext.Tree.GetRoot(syntaxTreeContext.CancellationToken);         foreach (var statement in root.DescendantNodes().OfType<StatementSyntax>())         {             // Skip analyzing cake statements              if (argument is BlockSyntax)             {                 continue;             }              // Report issues for all statements that are nested inside a statement             // but non a block statement             if (statement.Parent is StatementSyntax && !(statement.Parent is BlockSyntax))             {                 var diagnostic = Diagnostic.Create(Rule, statement.GetFirstToken().GetLocation());                 syntaxTreeContext.ReportDiagnostic(diagnostic);             }         }     }); }
  8. Check your progress by pressing F5 to run your analyzer. Make certain that the BraceAnalyzer.Vsix projection is the startup project earlier pressing F5. Running the VSIX project loads an experimental instance of Visual Studio, which lets Visual Studio proceed track of a carve up set of Visual Studio extensions.
  9. In the Visual Studio instance, create a new C# form library with the following lawmaking to verify that the analyzer diagnostic is neither reported for the method block nor the while argument, only is reported for the if statement and Organisation.Console.WriteLine invocation statement:
    Brace Analyzer Diagnostic
  10. Now, add curly braces around the Organization.Console.WriteLine invocation statement and verify that the only single warning is at present reported for the if argument:
    Brace Diagnostic For If Statement

Writing a lawmaking ready

An analyzer tin can provide 1 or more code fixes. A lawmaking fix defines an edit that addresses the reported upshot. For the analyzer that you created, yous can provide a code fix that encloses a statement with a curly brace.

  1. Open up the BraceAnalyzerCodeFixProvider.cs file. This code fix is already wired upwardly to the Diagnostic ID produced past your diagnostic analyzer, but it doesn't yet implement the right lawmaking transform.
  2. Change the title string to "Add brace":
  3. private const string title = "Add caryatid";
  4. Change the following line to register a code fix. Your gear up will create a new document that results from adding braces.
  5. context.RegisterCodeFix(         CodeAction.Create(             title: title,             createChangedDocument: c => AddBracesAsync(context.Document, diagnostic, root),             equivalenceKey: championship),         diagnostic);
  6. Y'all'll notice scarlet squiggles in the code yous but added on the AddBracesAsync symbol. Add a proclamation for AddBracesAsync by replacing the MakeUpperCaseAsync method with the post-obit code:
  7. Task<Document>              AddBracesAsync(Document document, Diagnostic diagnostic, SyntaxNode root)         {             var statement = root.FindNode(diagnostic.Location.SourceSpan).FirstAncestorOrSelf<StatementSyntax>();             var newRoot = root.ReplaceNode(argument, SyntaxFactory.Block(statement));             return Task.FromResult(document.WithSyntaxRoot(newRoot));         }          
  8. Press F5 to run the analyzer projection in a second instance of Visual Studio. Identify your cursor on the diagnostic and printing (Ctrl+.) to trigger the Quick Actions and Refactorings card. Find your code fix to add a brace!
    Image brace analyzer code fix2

Conclusion

Congratulations! You've created your beginning Roslyn analyzer that performs on-the-fly code assay to detect an issue and provides a code set to correct it. Now that you're familiar with the .Cyberspace Compiler Platform SDK (Roslyn APIs), writing your next analyzer will exist a breeze.