Sample anaylzer code for Dev14/CTP3

Topics: APIs, General
Coordinator
Aug 26, 2014 at 11:33 PM
I wrote an sample analyzer for Dev14/CTP3/Roslyn. Thought it would be a useful example to work from.

VIDEO: on channel9
SOURCE CODE: AnalyzerSample.zip
  • UseNameof analyzer -- detects where you have used a string literal that has the same name as a member of the containing class, and the suggested code-fix changes it into the nameof operator
  • ?. analyzer -- detects where you do var tmp=PropertyChanged; if (tmp!=null) tmp(args), and the suggested codefix turns it into PropertyChanged?.Invoke(args)
  • PrimaryConstructor analyzer -- detects where you have a constructor that merely assigns to fields/properties, and the suggested code-fix turns it into a primary constructor
  • Static PropertyChangedEventArgs -- detects where you construct an instance of PropertyChangedEventArgs inside an instance method/field, and the suggested code-fix allocates it just once in a static field initializer.
These analyzers are all written in C#, and only analyze C# source code. I'll do them in VB for a future Dev14 release once VB gets more language features.
Aug 27, 2014 at 7:56 AM
Thanks for posting this. However, I wonder if this is really the best practice? For instance, consider UseStaticPropertyChangedEventArgs.AnalyzeNode: To figure out whether an instance of System.ComponentModel.PropertyChangedEventArgs is created, you use the following code:
var objectCreation = node as ObjectCreationExpressionSyntax;
var objectCreationType = objectCreation.Type as IdentifierNameSyntax;
if (objectCreationType == null || objectCreationType.Identifier.ValueText != "PropertyChangedEventArgs") return;
However, the code does not really guarantee that an instance of System.ComponentModel.PropertyChangedEventArgs is created. It could be any class - or struct, for that matter - called PropertyChangedEventArgs.

Shouldn't you be using the semantic model to figure out the actual type that is being created? You might get away with this shortcut in that case, as System.ComponentModel.PropertyChangedEventArgs is a well-known class from the .NET base library and it is unlikely that something else called PropertyChangedEventArgs is declared in a project. However, for people writing their own analyzers and quick fixes, such situations might be more likely to occur. So I guess what I'm saying is: At least add a comment that warns about the potential pitfalls of your shortcut.
Aug 28, 2014 at 12:03 AM
Great video. The source code link doesn't appear on the Channel 9 page.
Coordinator
Sep 3, 2014 at 7:59 PM
Thanks Jesper. I added the source-code link to channel9.

Expeandable, I agree it should be more robust. I wonder if it should be robust merely by looking for the fully qualified name of the type? Or should it also stipulate which assembly-name the type came from?
Sep 3, 2014 at 8:06 PM
lwischik wrote:
Expeandable, I agree it should be more robust. I wonder if it should be robust merely by looking for the fully qualified name of the type? Or should it also stipulate which assembly-name the type came from?
Hmm. I probably would have used a semantic model to get the symbol for the type that you're checking. Then I would've looked up the symbol of the assembly of the System.dll assembly within the compilation that contains System.ComponentModel.PropertyChangedEventArgs. From there, you should be able to find the actual type symbol for System.ComponentModel.PropertyChangedEventArgs. Using the Equals method to compare the two symbols should tell you if that's the type you're looking for.

I don't think that you have to compare names at all (although that might be what Equals does internally, I don't know).