Most Anticipated Feature Implementation for C# 6.0 Survey Results

I wanted to post the results of the What is the most anticipated feature implementation for C# 6.0? survey that was recently posted.

Over 200 people contributed to the survey, however since I do not have licensed access to the underlying survey provider, the results I can analyze and report on are limited to 100.

Most Anticipated Features

  1. Null Propogation – 54%
  2. Auto Property Initializers – 13%
  3. Using Static Members – 6%

Least Anticipated Features

  1. Parameterless Struct Constructors – 0%
  2. Exception Filters – 0%
  3. Fast Integer Casts – 0%
  4. Checked and Unchecked Blocks – 0%

Enforcing Method Parameter Conventions Using Roslyn Diagnostics With C# Part 2: Code Fix Provider

Introduction and Recap

In my last post, Enforcing Method Parameter Conventions Using Roslyn Diagnostics With C# Part 1:Diagnostics , I showed how you can use the .NET Compiler Platform (Roslyn) to enforce conventions in your code base by implementing code diagnostics.

More specifically, we looked at enforcing method parameter conventions for a given user defined type (or interface). If you want additional insight on the sample convention, please refer to the previous post. To recap, our convention has the following properties.

  • Any public service method in the internal service layer must specify a parameter type of IInternalUser.
  • The IInternalUser parameter must be specified first in the method signature.
  • Only implemented members of service interfaces can be public. Everything else must be private.
Along with these properties are several assumptions that are mentioned in the previous article in order to keep this example short and to the point. The result of the last post left us with a diagnostic that gave us an error or warning if this convention was not followed. An example of this is shown in the screenshot below.

This was a very basic task and provided realistic benefits based on our convention. However, we want to also be able to provide suggested code fixes when this occurs. For this example we want to rearrange the parameters in the method signature to satisfy our convention. This is where the ICodeFixProvider helps.

Using ICodeFixProvider, we can specify instructions for replacing the existing syntax tree with an updated tree which includes our transformed fixes. This is not quite as trivial as implementing our DiagnosticAnalyzer.

The Implementation

We already have implemented our code diagnostic, so we just our code fix. Assuming you have followed the directions correctly in the first article, you should still have your template CodeFixProvider.cs in your project. It should look the same as the following screenshot.

The template code provides a fix that will make declarations all upper case, but we do not care about this.  Our goal is to take the improperly ordered parameter list and replace it with one that satisfies our convention.

Step 1: Implement GetFixesAsync

We need to rewrite the logic for GetFixesAsync to find the method declaration(s) that our implemented diagnostic was created for and return a code action for each that will invoke the fix that we implement. This leaves us with a fairly straight forward implementation for GetFixesAsync  as the logic for transforming the syntax tree will be housed in our own FixIInternalUserOrdinal which we will implement in the next step.

Go ahead and replace the GetFixesAsync with the following implementation.

I attempted to comment anything that was not straight forward and will not spend time going over each line of this implementation. If you would are having trouble understanding any of this, I would recommend spending a few minutes reviewing Getting-Started – Syntax Transformation (C#).

It is important to understand that we are grabbing the method declaration from the diagnostic that was provided, and then passing it into our FixIInternalUserOrdinal. 

Step 2: Implement FixIInternalUserOrdinal

Unlike GetFixesAsync which has no logic for transforming the syntax tree, FixIInternalUserOrdinal  is entirely responsible for this transformation and contains the logic for reordering the parameters in our method signature to satisfy our convention.

If you have not done it already, you can delete MakeUppercaseAsync  and add the following code.

Again, I am not going to spend time explaining each of these lines of code as I have done my best to explain it through the use of comments.

Instead, I will give a brief summary of the steps I took to reorder the parameters in the method signature. It is important to note that syntax trees are immutable. This means that even if the API exposes methods such as Replace(..) and WithXXX(…), it is actually creating a new object. The summary below uses terminology loosely but you should still keep this in mind.

  1. Grab a reference to the original parameter list node from the method declaration.
  2. Filter the list of parameter nodes to those with which use IdentifierNameSyntax so we can search for any tokens named “IInternalUser”.
  3. Iterate over each parameter in this filtered list until we find one that has a token matching “IInternalUser”.
  4. Create a new parameter list node and add the IInternalUser parameter node as the first item in the parameter node list.
  5. Iterate over the rest of the parameters and add to the new parameter list if not the IInternalUser  parameter node.
  6. Grab old syntax tree root and replace the old parameter list node with the new one that was just created with the correct parameter list.
  7. Return the new document with the transformed syntax tree.

Result!

You should now be able to test and even debug your new diagnostic by hittingControl + F5. This should spawn a new Visual Studio Instance in which you can use our previous project example that should use your diagnostic as an extension.

You should see the following diagnostic feedback.

Now that you have implemented a code fix, you should see a light bulb overlay appear in the left margin.

If you click on this, you should see our code fix Reorder Parameters.


The final result should look like the following in which we no longer see any diagnostic feedback because our convention is now satisfied!

Syntax Tree Visualizer

When you download the Roslyn preview, you can also utilize a useful tool within Visual Studio 2013, The Syntax Tree Visualizer. This proved to be very helpful as I was manipulating the syntax trees using transforms.  As an example, I have provided a before and after screenshot of our test code following the code fix. If you look closely, you will see the highlighted parameter (which represents our IInternalUser parameter) change positions under the method declaration syntax.

The screenshot below shows the syntax tree before the code fix.

Here is the same syntax tree after our code fix has been executed.

We have implemented a diagnostic and code fix to satisfy our convention. In our next article, I will probably try a more complex example.

Feedback Appreciated

I understand that there is several if not dozens of different ways that this example could have been accomplished. If you seem something I could have done more efficiently, or something is done incorrectly, let me know! This is all new to me and I am enjoying getting to know the Roslyn API. I appreciate any feedback that can be given on the subject matter. Additionally, if you have any ideas on conventions that you might have on your development team that you think would be a good example, let me know as well!

Enforcing Method Parameter Conventions Using Roslyn Diagnostics With C# Part 1: Diagnostics

Introduction

With all the hype coming off Microsoft’s BUILD 2014 Developer Conference and making The Roslyn Project open source, I wanted to take some time and familiarize myself with some of the concepts that were covered in Future of C# talk given by Mads Torgersen and Dustin Campbell.

Among several other announcements, they gave a demo on how to implement a ‘Diagnostic with Code Fix’.  In the example, they focus on implementing a diagnostic for conditionals used without braces and also provide the one click fix, similar to ReSharper.

When Roslyn was first announced, I did not quite see the benefit or need to implement custom code diagnostics and fixes. Having since then been a part of a larger enterprise team with a large code base and a strict set of standards and conventions, I now see a niche opportunity to experiment with this functionality.

Aside from the documented source code for Roslyn, it is still fairly early and not many examples are available. Additionally, I try to avoid spending too much of my free development time browsing source code (although I probably shouldn’t). Thus, I wanted to find something that I could easily implement and would provide a significant impact across our code base.

In this article, I am not going to show how to configure Roslyn or Visual Studio 2013. If you need help with this, then you can go use the two following links as resources.

The Convention

I wont get into too much detail on the conventions we use and for privacy reasons, I will modify our conventions for this example.

Our code base follows a service-oriented approach. Additionally, we break down our services into business,internal and external services.

For this example, I will assume that we have the following convention on our internal service layer.

  • Any public service method in the internal service layer must specify a parameter of type IInternalUser.
  • The IInternalUser parameter must be specified first in the method signature.
  • Only implemented members of service interfaces can be public. Everything else must be private.
Invalid Implementations:
Valid Implementations:
For this example, we are not going to worry about checking whether the method is an implementation of the service interface.
Pretty straight forward!

 The Implementation

For this article, we will only focus on the Diagnostic Analyzer and leave the Code Fix for Part 2.

Assuming that you have properly followed the directions that were provided for setting up Roslyn, you should have a Visual Studio instance loaded with a project containing the following template code files.

  • DiagnositcAnalyzer.cs
  • CodeFixProvider.cs
You may have some other files included, but they are not relevant for this article. We are going to only focus on DiagnosticAnalyzer.cs. If you open DiagnosticAnalyzer.cs, you should see template code such as the following:

It is nice that they provided us with template code, but we are going to move right along.

As mentioned earlier, we want to provide feedback in the form of a warning or error, for any method signature that contains a parameter of type IInternalUser that is not listed as the first parameter. This is of course a very basic example.

Step 1: Implement AnalyzeSymbol

We need to rewrite the logic for analyzing symbols from the templated code to what we want.

Replace the template AnalyzeSymbol  method with the following code:

This code simply checks to see if any method parameters are of type IInternalUser and checks the position if necessary. If it finds a parameter of type IInternalUser and it is not first in the list of parameters, it creates a diagnostic and invokes the addDiagnostic callback.

Step 2: Modify SymbolKindsOfInterest Auto Property Getter

In order to notify of the type of symbol(s) we want to analyze in AnalyzeSymbol , we need to modify the getter for the SymbolKindsOfInterest property to return an ImmutableArray<SymbolKind> representing SymbolKind.Method.  This is very simple and simply requires replacing the SymbolKindsOfInterest property with the following:

Step 3: Modify DiagnosticAnalyzer Meta Data Constants

The final step is the simplest and is only required to give proper context to the diagnostic you have just created. For this particular example, I simply want the feedback to the user that it is required that the IInternalUser parameter when present must be first in the parameter list. This can be done by changing the Description  and MessageFormat constants to the following:

You can of course provide a format string for the MessageFormat constant, but I see no need for this example.

Result!

You should now be able to test and even debug your new diagnostic by hitting Control + F5. This should spawn a new Visual Studio Instance in which you can create a new project that should use your diagnostic as an extension.

So why would somebody want to enforce conventions or standards on method signatures? You may not have realized it, but most of the common libraries we use also follow some type of pattern or standard for method signatures. This is why you can typically expect parameters to stay the same as you iterate over method overloads.

Some additional examples of why you might enforce method signatures and parameters are shown in the following list:

  • Ensure that one character parameter names are not used.
  • Ensure that parameter names are camel cased (or whatever).
  • Ensure that you are or aren’t using certain parameter types.
  • Utilize conventions for method names and return types (i.e. returns void is prefixed with “Is” or “Check”).
  • Restrict the maximum amount of parameters used in any method signature.

Stay tuned for the next article where we will implement a CodeFixProvider that will automatically rearrange the parameters so that they correctly match our convention!