Qodana 2025.3 Help

Create and run Roslyn analyzers

You can create and run your custom Roslyn analyzers using the Qodana for .NET linter as explained in this section.

Prerequisites

This section uses JetBrains Rider for creating an analyzer template.

Create a template

In the New Project dialog of JetBrains Rider, create a new solution using the Roslyn template of the Analyzers type. The created solution will also contain three separate projects. For example, for the MyCustomAnalyzer solution, this will contain the following projects:

  • MyCustomAnalyzer is designed for implementation of the analyzer logic

  • MyCustomAnalyzer.Sample lets you see how your analyzer operates in real time

  • MyCustomAnalyzer.Tests lets you write unit tests to verify the correctness of your analyzer

Using the Solution Explorer window of JetBrains Rider, expand the logic implementation project (MyCustomAnalyzer in the example above) and make sure that it contains implementations of the DiagnosticAnalyzer and CodeFixProvider classes.

In the logic implementation project, open the analyzer class derived from the DiagnosticAnalyzer class (often named as SampleSyntaxAnalyzer.cs) and replace its contents with the following sample code that will catch empty catch statements in your code:

using System.Collections.Immutable; using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; namespace MyCustomAnalyzer { [DiagnosticAnalyzer(LanguageNames.CSharp)] public sealed class EmptyCatchBlockAnalyzer : DiagnosticAnalyzer { public const string DiagnosticId = "MCA0001"; private static readonly DiagnosticDescriptor Rule = new( id: DiagnosticId, title: "Avoid empty catch blocks", messageFormat: "Empty catch block should be avoided", category: "Reliability", defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true, description: "Reports catch clauses with an empty block. Empty catches can hide failures and make debugging harder." ); public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(Rule); public override void Initialize(AnalysisContext context) { context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.EnableConcurrentExecution(); context.RegisterSyntaxNodeAction(AnalyzeCatchClause, SyntaxKind.CatchClause); } private static void AnalyzeCatchClause(SyntaxNodeAnalysisContext context) { var catchClause = (CatchClauseSyntax)context.Node; // catch { } or catch (Exception) { } var block = catchClause.Block; if (block is null) return; // Ignore non-empty catches if (block.Statements.Count != 0) return; // Ignore catches that have comments inside (often intentionally empty) if (block.DescendantTrivia().Any(t => t.IsKind(SyntaxKind.SingleLineCommentTrivia) || t.IsKind(SyntaxKind.MultiLineCommentTrivia))) return; context.ReportDiagnostic(Diagnostic.Create(Rule, catchClause.CatchKeyword.GetLocation())); } } }

Configure the analyzer project

In the project configuration file, add the following configuration:

<PropertyGroup> <!-- NuGet Package Configuration --> <IsPackable>true</IsPackable> <GeneratePackageOnBuild>true</GeneratePackageOnBuild> <!-- Prevent the analyzer from being added as a lib reference --> <IncludeBuildOutput>false</IncludeBuildOutput> <SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking> </PropertyGroup> <!-- Locate the analyzer DLL in the correct package directory --> <ItemGroup> <None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false"/> </ItemGroup>

Package and run your Roslyn analyzer

Package your analyzer by running the dotnet pack utility.

Qodana for .NET runs Roslyn analyzers under the following conditions:

  • The analyzer is referenced in a solution or project configuration of an analyzed project, for example:

    <ItemGroup> <PackageReference Include="MyCustomAnalyzer" Version="1.0.0" /> </ItemGroup>
  • The analyzer is reachable by build/restore and executed

  • The nuget.config file provides access to the package

  • Your project is built as described in the Build the project chapter

  • The Qodana for .NET linter is going to be executed in the native mode

Below is a sample Qodana configuration:

version: 1.0 # Configuring native mode linter: qodana-dotnet withinDocker: false # Restoring, building and referencing package bootstrap: |+ dotnet restore dotnet build dotnet add package MyCustomAnalyzer --version 1.0.0 dotnet: solution: MyProjectSolutionFile.csproj

To run your Roslyn analyzer using Qodana in JetBrains Rider, install your analyzer package by navigating View | Tool Windows | NuGet.

13 February 2026