Joe Hummel, the compiler is at your service Chicago Coder Conference, June 2016
Joe Hummel, PhD Professor:U. of Illinois, Chicago Consultant:Joe Hummel, Inc. Trainer:Pluralsight Microsoft MVP Visual C++ Chicago-based, one daughter adopted from China (now 14!) Avid Lake Michigan sailor Chicago Coder Conf Project Roslyn
Chicago Coder Conf Project Roslyn
What is Project Roslyn? The ".NET Compiler Platform" Replacement of previous.NET compilers with new ones csc for C# vbc for VB.NET Chicago Coder Conf Project Roslyn csc
Risky if Microsoft gets this wrong, they break a lot of code --- including their own Chicago Coder Conf Project Roslyn
So why did Microsoft do this? Open up the compiler Now folks can… Extend C# and VB with new features Target other platforms --- e.g. Raspberry PI? Take advantage of the rich information the compiler has about programs --- e.g. better refactoring, analysis, testing? Chicago Coder Conf Project Roslyn
What's the benefit? Faster turnaround on new features inside and outside MSFT Grow the Visual Studio ecosystem MUCH easier to build new tools MUCH easier to extend Visual Studio, C# and VB MUCH easier to try out new ideas Chicago Coder Conf Project Roslyn
Status Integrated into Visual Studio 2015 Additional.NET Compiler Platform SDK Shipped as a VS extension Chicago Coder Conf Project Roslyn
Open source? Yes, open source! Apache license 2.0 You are free to GIT, fork, modify, rebuild, deploy Anders released on Build 2014 Chicago Coder Conf Project Roslyn
Chicago Coder Conf Project Roslyn
C# and VB compilers were black boxes predefined switches only way to interact… Chicago Coder Conf Project Roslyn csc > csc.exe main.cs /o /warn:4
Chicago Coder Conf Project Roslyn
The compilers are now white boxes You can: obtain information about a program modify a program syntactically / semantically impact the compilation process change the compiler itself! 13 Chicago Coder Conf 2016 Project Roslyn csc Roslyn
Roslyn APIs Chicago Coder Conf June Project Roslyn
15 Chicago Coder Conf 2016 Project Roslyn csc "Call me every time you see an identifier…" (because I'm renaming all global variables) "Emit this code instead…" (I'm targeting specific HW) // translate project resource strings: foreach(Project p) foreach(Document d) foreach(Resource r) replace (r, r'); // translate project resource strings: foreach(Project p) foreach(Document d) foreach(Resource r) replace (r, r'); Roslyn
Many of the features in Visual Studio are driven by Roslyn… Chicago Coder Conf June Project Roslyn
What can we do with this capability? Infinite possibilities: better tools — refactoring, analysis, … better enforcement of coding standards integrate C# / VB into your app target new platforms language research — DSLs, … compiler research …… Chicago Coder Conf Project Roslyn ? ?
Chicago Coder Conf Project Roslyn
Front-end vs. Back-end Front-end deals with syntax ― "grammar" Back-end deals with semantics ― "meaning" Chicago Coder Conf Project Roslyn
Chicago Coder Conf Project Roslyn Source language Parsing Assembly language Lexical Analysis Compiler Semantic Analysis High-level Optimizer Code Gen Low-level Optimizer tokens IRIR'IR'' IR''' // comment if (x>100) x = 100; // comment if (x>100) x = 100; if, (, x, >, 100, ), x, =, … syntax errors semantic errors
Roslyn Intermediate Representation (IR) Abstract Syntax Tree (AST) Symbol Table Chicago Coder Conf Project Roslyn + GCD program 0"int", type, … 1"void", type, … 2… 3"getint", funct, type: 0, … 4"putint", funct, type: 1, … 5"i", var, type: 0, … 6"j", var, type: 0, … ……
How to learn Roslyn AST? Use the Roslyn Syntax Visualizer! Install.NET Compiler Platform SDK Open a project Open a source file View menu… >> Other Windows >> Syntax Visualizer Chicago Coder Conf Project Roslyn
Chicago Coder Conf Project Roslyn
Roslyn is BIG There are many APIs… There is the source code itself… Chicago Coder Conf Project Roslyn +
Start small Let’s create a simple diagnostic that warns about empty catch blocks… Chicago Coder Conf Project Roslyn
Step 1: Install.NET Compiler Platform SDK Create new project… >> Extensibility >> Diagnostic with Code Fix Name >> EmptyCatchDiagnostic Chicago Coder Conf Project Roslyn `
Step 2: Create Analyzer to detect empty catch blocks Chicago Coder Conf Project Roslyn public class CatchBlockDiagnosticAnalyzer : DiagnosticAnalyzer {. public override void Initialize(AnalysisContext context) { context.RegisterSyntaxNodeAction (AnalyzeNode, SyntaxKind.CatchClause); } // only called for things of interest: public void AnalyzeNode(SyntaxNodeAnalysisContext context) { var node = context.Node; var catchBlock = node as CatchClauseSyntax; if (catchBlock.Block.Statements.Count == 0) // empty! { var diagnostic = Diagnostic.Create(...); // create warning: context.ReportDiagnostic(diagnostic); // display: } public class CatchBlockDiagnosticAnalyzer : DiagnosticAnalyzer {... public override void Initialize(AnalysisContext context) { context.RegisterSyntaxNodeAction (AnalyzeNode, SyntaxKind.CatchClause); } // only called for things of interest: public void AnalyzeNode(SyntaxNodeAnalysisContext context) { var node = context.Node; var catchBlock = node as CatchClauseSyntax; if (catchBlock.Block.Statements.Count == 0) // empty! { var diagnostic = Diagnostic.Create(...); // create warning: context.ReportDiagnostic(diagnostic); // display: } }
Step 3: Create Code Fix Provider to optionally correct problem… Chicago Coder Conf Project Roslyn internal class CatchBlockDiagnosticCodeFixProvider : CodeFixProvider { // only called for things of interest: public … async Task RegisterCodeFixesAsync(CodeFixContext context) { var root = await context.Document.GetSyntaxRootAsync(…); var diagnostic = context.Diagnostics.First(); var diagnosticSpan = diagnostic.Location.SourceSpan; var catch = root.FindToken(…).Parent.AncestorsAndSelf(). OfType.First(); context.RegisterCodeFix(CodeAction.Create("throw", c => UpdateCatchBlock(context.Document, catch, c)), diagnostic); } private async Task UpdateCatchBlock(Document doc, …) { var throwStmt = SyntaxFactory.ThrowStatement(); var newStmts = new SyntaxList ().Add(throwStmt); var newBlock = SyntaxFactory.Block().WithStatements(newStmts); var newCatchBlock = SyntaxFactory.CatchClause(). WithBlock(newBlock). WithAdditionalAnnotations(Formatter.Annotation); var root = await document.GetSyntaxRootAsync(); var newRoot = root.ReplaceNode(catchBlock, newCatchBlock); var newDocument = document.WithSyntaxRoot(newRoot); return newDocument; } internal class CatchBlockDiagnosticCodeFixProvider : CodeFixProvider { // only called for things of interest: public … async Task RegisterCodeFixesAsync(CodeFixContext context) { var root = await context.Document.GetSyntaxRootAsync(…); var diagnostic = context.Diagnostics.First(); var diagnosticSpan = diagnostic.Location.SourceSpan; var catch = root.FindToken(…).Parent.AncestorsAndSelf(). OfType.First(); context.RegisterCodeFix(CodeAction.Create("throw", c => UpdateCatchBlock(context.Document, catch, c)), diagnostic); } private async Task UpdateCatchBlock(Document doc, …) { var throwStmt = SyntaxFactory.ThrowStatement(); var newStmts = new SyntaxList ().Add(throwStmt); var newBlock = SyntaxFactory.Block().WithStatements(newStmts); var newCatchBlock = SyntaxFactory.CatchClause(). WithBlock(newBlock). WithAdditionalAnnotations(Formatter.Annotation); var root = await document.GetSyntaxRootAsync(); var newRoot = root.ReplaceNode(catchBlock, newCatchBlock); var newDocument = document.WithSyntaxRoot(newRoot); return newDocument; }
Step 4: Run! A.vsix installer is built A new instance of VS is started The.vsix is installed Open a project and test… Chicago Coder Conf Project Roslyn
Chicago Coder Conf Project Roslyn
Roslyn compilers are part of Visual Studio 2015 You’ll also want.NET Compiler Platform SDK Visual Studio extension Tools >> Updates and Extensions Chicago Coder Conf Project Roslyn
Chicago Coder Conf Project Roslyn
Thank you for attending! Joe Hummel, PhD Materials: For more information on Roslyn: MSDN: “C# - Adding a Code Fix to Your Roslyn Analyzer”, by Alex Turner, Feb 2015 Docs / FAQ: Microsoft’s Channel 9 Chicago Coder Conf Project Roslyn