C# Corner

Roslyn Update: The State of the .NET Compiler Platform

Now that Visual Studio 2015 is upon us, here's a brief overview of the capabilities of the .NET Compiler Platform.

"Project Roslyn," formally known as the Microsoft .NET Compiler Platform, has been in incubation since 2008. Well, it's ready for inception in Visual Studio 2015.

Roslyn is a compiler API for both C# and Visual Basic. What this means is that you have full access to the internal compilation structure of your code now. This allows for many interesting use cases such as static code analysis, code generation and read-eval-print-loop (REPL) functionality for C# and Visual Basic.

In this article, I'll cover how to use the C# Roslyn API to create a code diagnostic, as well as a quick-fix that can uppercase constant field members.

To get started, install the .NET Compiler Platform SDK Templates for Visual Studio 2015 RC from the Visual Studio Gallery. You can also install the .NET Compiler Platform SDK from the Visual Studio Extensions and Updates window (see Figure 1).

[Click on image for larger view.] Figure 1. .NET Compiler Platform SDK Installation

Next, install the Visual Studio 2015 RC SDK from the download page.

Then, create a new Analyzer with Code Fix project as seen in Figure 2.

[Click on image for larger view.] Figure 2. New Analyzer with Code Fix Project

First, open up the Resources.resx resource file and update the values for each key (Figure 3) to reflect that the fix is for constant field names.

[Click on image for larger view.] Figure 3. Updated Resources.resx Resource File

Then open up the DiagnosticAnalyzer.cs code file. The DiagnosticAnalayzer class is responsible for generating the code fix warning for Visual Studio. Next, update the Initialize method to analyze only field symbols:

public override void Initialize(AnalysisContext context)
{
  context.RegisterSymbolAction(AnalyzeSymbol, SymbolKind.Field);
}

Next, update the AnalyzeSymbol method to create a diagnostic for only field symbols that contain lowercase letters and have a constant value:

private static void AnalyzeSymbol(SymbolAnalysisContext context)
{
  var fieldSymbol = (IFieldSymbol)context.Symbol;
  if (fieldSymbol.Name.ToCharArray().Any(char.IsLower) && fieldSymbol.ConstantValue != null)
  {
    var diagnostic = Diagnostic.Create(Rule, fieldSymbol.Locations[0], fieldSymbol.Name);
    context.ReportDiagnostic(diagnostic);
  }
}

Now it's time to update the CodeFixProvider class to allow the fix to be previewed and fixed. First, update the RegisterCodeFixesAsync method to find the field declarations that need to be fixed, as shown in Listing 1.

Listing 1: Updating the RegisterCodeFixesAsync Method
public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
  var root = await context.Document.GetSyntaxRootAsync(
    context.CancellationToken).ConfigureAwait(false);
  var diagnostic = context.Diagnostics.First();
  var diagnosticSpan = diagnostic.Location.SourceSpan;
  var declaration = root.FindToken(
    diagnosticSpan.Start).Parent.AncestorsAndSelf().OfType<FieldDeclarationSyntax>().First();
  context.RegisterCodeFix(
    CodeAction.Create("Make uppercase", c => 
    MakeUppercaseAsync(context.Document, declaration, c)),
    diagnostic);
}

Then update the MakeUppercaseAsync method to fix the given field declaration syntax by making the type name be uppercase. First, get the semantic model:

var semanticModel = await document.GetSemanticModelAsync(cancellationToken);

Then get the field symbol for the field declaration from the semantic model:

IFieldSymbol fieldSybmol = null;
fieldSybmol = 
  semanticModel.GetDeclaredSymbol(
  fieldDecl.Declaration.Variables.First()) as IFieldSymbol;

Then generate the uppercased field symbol name:

string newName = fieldSybmol.Name.ToUpperInvariant();
Next, get the original solution and workspace options:
var originalSolution = document.Project.Solution;
var optionSet = originalSolution.Workspace.Options;
Last, create and return a new solution with the field symbol renamed:
var newSolution = await Renamer.RenameSymbolAsync(
  document.Project.Solution, fieldSybmol, newName, optionSet, 
  cancellationToken).ConfigureAwait(false);
return newSolution;

Now you should be able to run the solution and test out the fix by creating a constant private field as seen in Figure 4.

[Click on image for larger view.] Figure 4. Code Fix in Action

Next you can click on the light bulb and preview the fix (Figure 5).

[Click on image for larger view.] Figure 5. Code Fix Preview in Action

Finally, you can apply the code fix and see it applied by clicking on the Make uppercase option as seen in Figure 6.

[Click on image for larger view.] Figure 6. Make Uppercase Option

I've covered creating a new diagnostic analyzer and code fix. You can analyze one or many symbol or syntax types using Rosyln. After the code fix is created you can deploy it either as a NuGet package or as a .vsix installer.

As you can see, Roslyn opens up Visual Studio to be extended with custom static code analysis and refactoring plug-ins.

About the Author

Eric Vogel is a Senior Software Developer for Red Cedar Solutions Group in Okemos, Michigan. He is the president of the Greater Lansing User Group for .NET. Eric enjoys learning about software architecture and craftsmanship, and is always looking for ways to create more robust and testable applications. Contact him at [email protected].

comments powered by Disqus

Featured

  • Cloud-Focused .NET Aspire 9.1 Released

    Along with .NET 10 Preview 1, Microsoft released.NET Aspire 9.1, the latest update to its opinionated, cloud-ready stack for building resilient, observable, and configurable cloud-native applications with .NET.

  • Microsoft Ships First .NET 10 Preview

    Microsoft shipped .NET 10 Preview 1, introducing a raft of improvements and fixes across performance, libraries, and the developer experience.

  • C# Dev Kit Previews .NET Aspire Orchestration

    Microsoft's dev team has been busy updating the C# Dev Kit, a Visual Studio Code extension that enhances the C# development experience by providing tools for managing, debugging, and editing C# projects.

  • Hands On: New VS Code Insiders Build Creates Web Page from Image in Seconds

    New Vision support with GitHub Copilot in the latest Visual Studio Code Insiders build takes a user-supplied mockup image and creates a web page from it in seconds, handling all the HTML and CSS.

  • Naive Bayes Regression Using C#

    Dr. James McCaffrey from Microsoft Research presents a complete end-to-end demonstration of the naive Bayes regression technique, where the goal is to predict a single numeric value. Compared to other machine learning regression techniques, naive Bayes regression is usually less accurate, but is simple, easy to implement and customize, works on both large and small datasets, is highly interpretable, and doesn't require tuning any hyperparameters.

Subscribe on YouTube

Upcoming Training Events