In this article, we will introduce Roslyn compiler and analyzers in .NET. Moreover, we will delve into utilizing Roslyn to compile C# code and explore various types of Roslyn analyzers.
Roslyn is an open-source compiler for C# and Visual Basic. Roslyn exposes a wide range of APIs that provide information about the source code we write as developers. Those APIs enable us to write customized build tools and analyzers.
Let’s dive into more details about Roslyn compiler and analyzers.
Compiling C# With Roslyn
Roslyn compiler platform is available in two formats. The first one is as a command line application, and the second format is as a set of compiler APIs. In the following sections, we will start by looking at where we can find Roslyn compiler CLI and how to use it to compile C#, and in a later section, we will look at analyzers that leverage the compiler APIs.
Roslyn Compiler in Visual Studio
The csc
is the compiler for C#, and it ships with Visual Studio. As a result, if we install Visual Studio, we should be able to locate it. The Roslyn path on Windows is inside the Visual Studio installation directory. On the other hand, to find the compilers on MacOS, we use the where
command:
where csc
Firstly, let’s create a text file SampleMain.txt
that contains valid C# code:
using System; internal class Program { private static void Main(string[] args) { Console.WriteLine("Hello, from SampleMain.txt!"); } }
Secondly, let’s see how we can use the csc
command line tool to compile the source code on Windows:
csc.exe /target:exe /out:SampleMain.exe SampleMain.txt
To compile the source code on MacOS:
csc /target:exe /out:SampleMain SampleMain.txt
When using the csc
CLI, /target
specifies the file format of the output assembly, which in this case, is exe
. There are other possible values for /target
such as /target:library
to build a dotnet library(dll
) and /target:module
to create reusable modules. If we didn’t specify any value for /target
its default value is exe
. Next, we have the /out
argument, which defines the output file name. The last argument is the file we want to compile. Finally, we run the command. After that, we will have an output file by the name SampleMain.exe
on Windows and SampleMain
on Mac.
On Windows, we can simply double-click and run the SampleMain.exe
. However, on MacOS, we should use Mono to run the SampleMain
file. And in both cases, after running the output file, it will print:
Hello, from SampleMain.txt!
Roslyn Compiler in .NET SDK
If we don’t have Visual Studio setup, locating Roslyn inside the .NET SDK is possible. The .NET SDK is available on the official Microsoft website. Because both C# and Visual Basic compilers also ship with the .NET SDK. We can locate the csc.dll
inside the .NET SDK installation directory.
To compile the SampleMain.txt
using csc.dll
, we should first create a SampleOutput.runtimeconfig.json
file and specify the runtime configuration settings:
{ "runtimeOptions": { "tfm": "net7.0", "framework": { "name": "Microsoft.NETCore.App", "version": "7.0.2" } } }
Next, for readability, instead of writing long commands in the terminal, we will create a PowerShell script file CompileUsingCSCDll.ps1
that reference the required assemblies:
dotnet 'C:\Program Files\dotnet\sdk\7.0.202\Roslyn\bincore\csc.dll' ` /r:'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\7.0.4\System.Runtime.dll' ` /r:'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\7.0.4\System.Console.dll' ` /r:'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\7.0.4\System.Private.CoreLib.dll' ` /out:SampleOutput.dll SampleMain.txt
We use the /r
or /reference
argument for adding a reference to other assemblies. Now, let’s run the script:
.\CompileUsingCSCDll.ps1
This will create a SampleOutput.dll
output file. We can run the application, and it should print the message Hello, from SampleMain.txt!
.
However, it becomes more impractical to compile using this process if we have a larger code base. Fortunately, we usually don’t need to worry about every step because dotnet takes the necessary steps to compile it.
Roslyn Analyzers
Roslyn analyzers provide real-time feedback on our C# code in Visual Studio, helping us write more unified code. Visual Studio comes with a set of analyzers, and we can install or build more as needed.
Visual Studio analyzers heavily leverage Roslyn API. These analyzers inspect our C# and Visual Basic code for syntax and structure and provide feedback.
There are three analyzer groups:
- code style
- quality
- external analyzers
In this section, we will briefly look at the set analyzers that come with Visual Studio and other analyzers we can install.
Code Style Analyzers
Code style analyzers are a set of analyzers that help us write code that exhibits a unified coding style or structure throughout our code base.
Some rules are:
- remove unnecessary cast
- add braces and more
To learn more about the available rules, please refer to Microsoft documentation.
The .editorconfig
file is a great way to define coding style rules. These rules include specifying the naming style, whether we should use var
or explicit type in our code base, and more. Those sets of rules have an IDE
prefix in the rule ID.
The .editorconfig
file contains a long list of code style rules we can customize by setting the value at the Value
column. The Severity
column lets us specify if the feedback for violating the coding style rule should be an error, suggestion, warning, or simply no feedback.
For example, we set the rule to use var
for built-in types. We will get a warning if we use the explicit type:
Let’s write a code that violates this rule:
string message = "Hello, There!"; Console.WriteLine(message);
Next, let’s see the feedback from the compiler:
IDE0007: use 'var' instead of explicit type
As a result of the rule we set in the .editorconfig
file, we get a warning and a potential fix telling us to use var
instead of string
.The warning rule ID (which is IDE0007
) starts with IDE
. We can apply the fix throughout the project or even the solution. We also have the option to suppress the rule on this specific source file.
Code Quality Analyzers
Code quality analyzers are a set of analyzers that help us improve our code’s design, globalization, performance, and security. We use the .editorconfig
file to specify code style analyzer rules similarly, we use .editorconfig
to specify code quality rules.
The code quality rules list is quite long. Some rules are: do not expose generic lists, enums should have zero value and more. Please refer to Microsoft documentation to learn more about the available code quality rules. Those sets of rules have a CA
prefix in the rule ID.
Let’s find the code quality analyzer rules in the Analyzers
tab and set the severity of the “Avoid empty interfaces” rule to a Warning
:
Next, let’s create an empty IEmptyInterface
interface that violates our code quality rule:
public interface IEmptyInterface { }
Let’s see the compiler’s feedback:
CA1040: Avoid empty interfaces
The analyzers detect this violation and provide the rule’s ID and description. The ID of the violated rule is CA1040
, and if we hover over the ID, it gives a link to Microsoft’s documentation that explains the rule in detail. In addition, the rule ID provides a link to the corresponding documentation for all the analyzers that ship with Visual Studio. However, that might not be the case for external analyzers; it depends on the developer.
External Analyzers
External analyzers are those that don’t ship with Visual Studio. Instead, other developers write these analyzers, and they are available for installation as a NuGet package or Visual Studio extension, for example, StyleCop, Roslynator, and XUnit Analyzers.
Conclusion
In conclusion, we’ve learned that the Roslyn compiler and analyzers in .NET help the developers maintain good code quality. As we have seen, the Roslyn compiler is a powerful .NET compiler platform. It enables us to compile both C# and Visual Basic code. Moreover, it provides a rich set of code analysis APIs. By default, Visual Studio comes with a wide array of analyzers. These analyzers enable us to write consistent style and quality code. Installing external analyzers or building our analyzer is also possible. We also learned different ways of specifying .NET analyzer rules and looked at the usage of the .editorconfig
file.