Qodana 2024.1 Help

.NET

All Qodana linters are based on IDEs designed for particular programming languages and frameworks. To analyze .NET projects, you can use the following Qodana linters:

  • Qodana for .NET is based on Rider, licensed under the Ultimate and Ultimate Plus licenses, and available as a native solution and the jetbrains/qodana-dotnet:2024.1 Docker image,

  • Qodana Community for .NET is based on ReSharper, licensed under the Community license, and available as the jetbrains/qodana-cdnet:2024.1-eap Docker image.

You can compare these linters by navigating to the Supported technologies and features section.

Before your start

Qodana Cloud

To run linters, you need to obtain a project token that will be used by Qodana for identifying and verifying a license.

Navigate to Qodana Cloud and create an account there.

In Qodana Cloud, create an organization, a team, and a project.

On the project card, you can find the project token that you will be using in this section.

SDK version

The Dockerized version of Qodana for .NET provides the following SDK versions:

  • 6.0.417,

  • 7.0.404,

  • 8.0.100.

All SDK versions are stored in the /usr/share/dotnet/sdk directory of the Qodana container filesystem.

In case a project requires a different version of the SDK, you can set it using the bootstrap key in the qodana.yaml file. For example, this command will install the required version of the SDK that is specified in the global.json file and located in the root of your project:

bootstrap: curl -fsSL https://dot.net/v1/dotnet-install.sh | bash -s -- --jsonfile /data/project/global.json -i /usr/share/dotnet

Build the project

During the start, Qodana builds your project. If the project build fails, code analysis cannot be performed. You can configure the project build using the bootstrap key of the qodana.yaml file contained in your project directory.

Alternatively, you can build your project in a pipeline before Qodana starts.

If you wish to run your custom build, use the --no-build option:

docker run \ -v <source-directory>/:/data/project/ \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<dotnet/cdnet>:2024.1<-eap> \ --no-build

This is the GitHub Actions configuration sample invoking the --no-build option:

name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2024.1 with: args: --no-build env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}

Run Qodana

You can run the Qodana for .NET linter either in the native mode (recommended) or using the linter in a container mode.

You can run the Qodana Community for .NET linter in a container mode.

Native mode

The native mode is the recommended method for running the Qodana for .NET linter that lets you run the linter without using Docker containers.

YAML file

Using the YAML configuration is the preferred method of configuring the linter because it lets you use such configuration across all software that runs Qodana without additional configuration.

You can configure the native mode by adding this line to the qodana.yaml file:

ide: QDNET

JetBrains IDEs

You can run Qodana in Rider and forward inspection reports to Qodana Cloud for storage and analysis purposes.

  1. In Rider, navigate to Tools | Qodana | Try Code Analysis with Qodana.

  2. On the Run Qodana dialog, you can configure:

    Configuring Qodana in the Run Qodana dialog

    Click Run for analyzing your code.

  3. In the Server-Side Analysis tool window, see the inspection results.

GitHub Actions

If you have already configured the qodana.yaml file, you can skip this and navigate to the GitHub Actions section below.

You can run Qodana using the Qodana Scan GitHub action as shown below.

  1. On the Settings tab of the GitHub UI, create the QODANA_TOKEN encrypted secret and save the project token as its value.

  2. On the Actions tab of the GitHub UI, set up a new workflow and create the .github/workflows/code_quality.yml file.

  3. To inspect the main branch, release branches and the pull requests coming to your repository in the native mode, save this workflow configuration to the .github/workflows/code_quality.yml file:

    name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2024.1 with: args: --ide,QDNET env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}

    This configuration invokes the native mode using:

    with:    args: --ide,QDNET

Local run

Assuming that you have already installed Qodana CLI on your machine, you can run this command in the project root directory:

qodana scan \ --ide QDNET

Here, the --ide option downloads and employs the JetBrains IDE binary file.

Alternatively, in the qodana.yaml file save ide: QDNET, and then run Qodana using the following command:

qodana scan

Container mode

The container mode is available for the Qodana for .NET and Qodana Community for .NET linters. For the Qodana for .NET linter, the native mode is the recommended method.

For the Qodana Community for .NET linter, only the container mode is available.

GitHub Actions

You can run Qodana using the Qodana Scan GitHub action as shown below.

  1. On the Settings tab of the GitHub UI, create the QODANA_TOKEN encrypted secret and save the project token as its value.

  2. On the Actions tab of the GitHub UI, set up a new workflow and create the .github/workflows/code_quality.yml file.

  3. To analyze the main branch, release branches and the pull requests coming to your repository in the container mode, save this workflow configuration to the .github/workflows/code_quality.yml file:

    name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2024.1 env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}

Local run

To start, pull the image from Docker Hub (only necessary to get the latest version):

docker pull jetbrains/qodana-<dotnet/cdnet>:2024.1<-eap>

Start local analysis with source-directory pointing to the root of your project and QODANA_TOKEN referring to the project token:

docker run \    -v <source-directory>/:/data/project/ \    -e QODANA_TOKEN="<cloud-project-token>" \    jetbrains/qodana-<dotnet/cdnet>:2024.1<-eap>

Open Qodana Cloud in your browser to examine analysis results.

Analyze a specific solution

By default, Qodana tries to locate and employ a single solution file, or, if no solution file is present, it tries to find a project file. If your project contains multiple solution files, you need to specify the exact filename as shown below.

Specify a solution

You can specify a solution in various ways. Using a YAML configuration is the most convenient method because you can configure it once and use the configuration across all software that runs Qodana.

YAML file

Specify the relative path to the solution file from the project root:

dotnet: solution: <relative-path-to-solution-file>

If your project contains no solution files and multiple project files, you need to employ a project file:

dotnet: project: <relative-path-to-project-file>
Docker

The Qodana for .NET linter uses the --property option, while the Qodana Community for .NET linter uses the --solution option to specify a path to a solution file:

docker run \    -v <source-directory>/:/data/project/ \    -e QODANA_TOKEN="<cloud-project-token>" \    jetbrains/qodana-dotnet:2024.1 \    --property=qodana.net.solution=<relative-path-to-solution-file>
docker run \    -v <source-directory>/:/data/project/ \    -e QODANA_TOKEN="<cloud-project-token>" \    jetbrains/qodana-cdnet:2024.1-eap \    --solution=<relative-path-to-solution-file>

If your project contains no solution files and multiple project files, you need to employ a project file using the --property and --project options:

docker run \    -v <source-directory>/:/data/project/ \    -e QODANA_TOKEN="<cloud-project-token>" \    jetbrains/qodana-dotnet:2024.1 \    --property=qodana.net.project=<relative-path-to-project-file>
docker run \    -v <source-directory>/:/data/project/ \    -e QODANA_TOKEN="<cloud-project-token>" \    jetbrains/qodana-cdnet:2024.1-eap \    --project=<relative-path-to-project-file>

Configure a solution

A solution configuration defines which projects in the solution to build, and which project configurations to use for specific projects within the solution.

Every solution contains the Debug and Release configurations that you can employ as shown below.

YAML file

You can switch configurations of the current solution in the qodana.yaml file:

dotnet: configuration: Release

By default, the solution platform is set to Any CPU, and you can override it, for example:

dotnet: platform: x86
Docker

You can apply a configuration using the --property and --configuration options:

docker run \    -v <source-directory>/:/data/project/ \    -e QODANA_TOKEN="<cloud-project-token>" \    jetbrains/qodana-dotnet:2024.1 \    --property=qodana.net.configuration=Release
docker run \    -v <source-directory>/:/data/project/ \    -e QODANA_TOKEN="<cloud-project-token>" \    jetbrains/qodana-cdnet:2024.1-eap \    --configuration=Release

By default, the solution platform is set to Any CPU, and you can override it as shown below:

docker run \    -v <source-directory>/:/data/project/ \    -e QODANA_TOKEN="<cloud-project-token>" \    jetbrains/qodana-dotnet:2024.1 \    --property=qodana.net.platform=x86
docker run \    -v <source-directory>/:/data/project/ \    -e QODANA_TOKEN="<cloud-project-token>" \    jetbrains/qodana-cdnet:2024.1-eap \    --platform=x86

Private NuGet repositories

You can run Qodana for .NET using private NuGet feeds. The linter does not support authentication for private NuGet repositories using, for example, Windows Authentication. To overcome this limitation, you can place all required packages within the Qodana cache as shown below:

  1. In the local filesystem, create the folder that will contain cache. For example, it can be C:/Temp/QodanaCache.

  2. Run Qodana using the --cache-dir C:/Temp/QodanaCache option:

    docker run \    -v <source-directory>/:/data/project/ \    -e QODANA_TOKEN="<cloud-project-token>" \    -e QODANA_NUGET_URL=<private-NuGet-feed-URL> \    -e QODANA_NUGET_USER=<login> \    -e QODANA_NUGET_PASSWORD=<plaintext-password> \    -e QODANA_NUGET_NAME=<name-of-private-NuGet-feed> \    jetbrains/qodana-dotnet:2024.1 \    --cache-dir C:/Temp/QodanaCache
  3. Copy all NuGet packages contained by default in the %userprofile%\.nuget\packages folder to C:/Temp/QodanaCache/nuget. If you have a custom package folder, copy packages from that folder instead of %userprofile%\.nuget\packages.

  4. Run Qodana using the --cache-dir C:/Temp/QodanaCache once more.

Explore analysis results

JetBrains IDEs

You can get the latest Qodana report in your IDE as explained below.

  1. In your IDE, navigate to Tools | Qodana | Log in to Qodana.

  2. On the Settings dialog, click Log in.

    Connecting to Qodana Cloud

    This will redirect you to the authentication page.

  3. Select the Qodana Cloud project to link your local project with.

    Linking the project to Qodana Cloud
  4. By enabling the Always load most relevant Qodana report option, you get actual reports automatically retrieved from Qodana Cloud.

    Enabling to load the most relevant reports

    In this case, the IDE will search and fetch from Qodana Cloud the report that has the revision ID corresponding to the current revision ID (HEAD). If this report was not found, the IDE will select the previous report with the revision closest to the current revision ID (HEAD). Otherwise, the IDE retrieves the latest available report from Qodana Cloud.

  5. On the Server-Side Analysis tab of the Problems tool window, view analysis results.

Qodana Cloud

Once Qodana analyzed your project and uploaded the analysis results to Qodana Cloud, in Qodana Cloud navigate to your project and review the analysis results report.

Analysis report example

To learn more about Qodana report UI, see the Inspection report section.

Extend the configuration

Adjust the scope of analysis

Qodana for .NET

Qodana for .NET reads configuration from the qodana.yaml file located in the root directory of your project. For example, add this configuration to run the linter using the qodana.recommended inspection profile:

version: "1.0" profile: name: qodana.recommended

You can analyze your code using Roslyn analyzers with each analyzer considered as a separate inspection. You can configure Roslyn analyzers as explained in the EditorConfig section. This is an experimental feature, so use them at your own risk.

To disable Roslyn analyzers, you can configure the Qodana profile using the qodana.yaml file, for example:

name: "Custom profile" baseProfile: qodana.starter groups: # List of configured groups - groupId: InspectionsToExclude groups: - "category:C#/Roslyn Analyzers" inspections: # Group invocation - group: InspectionsToExclude enabled: false # Disable the InspectionsToExclude group

Configuration examples are available on GitHub.

If you are familiar with configuring code analysis via Rider inspection profiles, you can pass the reference to the existing profile by mapping the profile:

docker run \    -v $(pwd):/data/project/ \    -v $(pwd)/.qodana/<inspection-profile.xml>:/data/project/myprofiles/<inspection-profile.xml> \    -e QODANA_TOKEN="<cloud-project-token>" \    jetbrains/qodana-dotnet:2024.1 \    --profile-path /data/project/myprofiles/<inspection-profile.xml>

Qodana Community for .NET

If you have previously worked on the target solution with ReSharper, you may have already configured code inspections settings. If so, InspectCode will find your custom settings in .DotSettings files and apply them. If there are no settings files, then the default severity levels will be used for all analyses. Besides custom severity levels for code inspections, InspectCode will look for the following settings in .DotSettings files:

To configure InspectCode on a CI server, make all configurations locally with ReSharper, save the settings to the Solution Team-Shared layer, and then commit the resulting YourSolution.sln.DotSettings file in the solution directory to your VCS. InspectCode on the server will find and apply these settings.

By default, InspectCode also runs Roslyn analyzers on the target solution. To configure Roslyn analyzers, see the EditorConfig section.

To disable Roslyn analyzers, in the solution's .DotSettings file add the following configuration:

<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <!-- Enable/disable Roslyn analyzers and Source Generators --> <s:Boolean x:Key="/Default/CodeInspection/Roslyn/RoslynEnabled/@EntryValue">False</s:Boolean> <!-- Include/exclude Roslyn analyzers in Solution-Wide Analysis --> <s:Boolean x:Key="/Default/CodeInspection/Roslyn/UseRoslynInSwea/@EntryValue">False</s:Boolean> </wpf:ResourceDictionary>

EditorConfig

If you use EditorConfig to maintain code styles for your project, you can also configure code inspections from .editorconfig files.

As EditorConfig convention suggests, InspectCode will apply inspection settings defined in files named .editorconfig in the directory of the current file and in all its parent directories until it reaches the root filepath or finds an EditorConfig file with root=true. File masks specified in .editorconfig files, for example *Test.cs are also taken into account.

Inspection settings in .editorconfig files are configured similarly to other properties — by adding the corresponding lines:

[inspection_property]=[error | warning | suggestion | hint | none]

For example, you can change the severity level of the Possible 'System.NullReferenceException' inspection to Error with the following line:

resharper_possible_null_reference_exception_highlighting=error

or you can disable the Redundant argument with default value inspection with the following line:

resharper_redundant_argument_default_value_highlighting=none

You can find EditorConfig property for each inspection on pages in the Code inspection index section as well as on the Index of EditorConfig properties page. — just use the browser search to find the property for the desired inspection.

Enable the baseline

You can skip analysis for specific problems using the baseline feature.

JetBrains IDEs

  1. In your IDE, navigate to the Problems tool window.

  2. In the Problems tool window, click the Server-Side Analysis tab.

  3. On the Server-Side Analysis tab, click the Try Locally button.

  4. On the dialog that opens, expand the Advanced configuration section and specify the path to the baseline file, and then click Run.

GitHub Actions

This snippet contains the args: --baseline,qodana.sarif.json line that specifies the path to the SARIF-formatted file containing a baseline:

name: Qodana on: workflow_dispatch: pull_request: push: branches: # Specify your branches here - main # The 'main' branch - 'releases/*' # The release branches jobs: qodana: runs-on: ubuntu-latest permissions: contents: write pull-requests: write checks: write steps: - uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit fetch-depth: 0 # a full history is required for pull request analysis - name: 'Qodana Scan' uses: JetBrains/qodana-action@v2024.1 with: args: --baseline,qodana.sarif.json env: QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}

Local run

In these snippets, the --baseline option configures the path to the SARIF-formatted file containing a baseline:

docker run \ -v <source-directory>/:/data/project/ \ -v <path_to_baseline>:/data/base/ \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<dotnet/cdnet>:2024.1<-eap> \ --baseline /data/base/qodana.sarif.json

Enable the quality gate

You can configure quality gates for the total number of project problems, specific problem severities, and code coverage by saving this snippet to the qodana.yaml file:

failureConditions: severityThresholds: any: 50 # Total number of problems in all severities critical: 1 # Severities high: 2 moderate: 3 low: 4 info: 5 testCoverageThresholds: fresh: 6 # Fresh code coverage total: 7 # Total percentage

Analyze pull requests

GitHub Actions

Because the Qodana Scan GitHub action automatically analyzes all pull requests, you can use this configuration.

Local run

To analyze changes in your code, employ the --diff-start option and specify a hash of the commit that will act as a base for comparison:

docker run \    -v $(pwd):/data/project/ \    -e QODANA_TOKEN="<cloud-project-token>" \    jetbrains/qodana-<dotnet/cdnet>:2024.1<-eap> \    --diff-start=<GIT_START_HASH>

Usage statistics

According to the JetBrains EAP user agreement, we can use third-party services to analyze the usage of our features to further improve the user experience. All data will be collected anonymously. You can disable statistics by using the --no-statistics=true CLI option, for example:

docker run \ -v <source-directory>/:/data/project/ \ -e QODANA_TOKEN="<cloud-project-token>" \ jetbrains/qodana-<dotnet/cdnet>:2024.1<-eap> \ --no-statistics=true

Supported technologies and features

Support for

Name

Qodana for .NET

Qodana Community for .NET

Programming languages

C#

C++ *

VB.NET **

C *

JavaScript

TypeScript

✔ All from the list

Frameworks and libraries

.NET Framework

.NET Core

Handlebars/Mustache

Less

Node.JS

NUnit

Pug/Jade

Sass/SCSS

Unity

Unreal Engine

Vue

Xunit

✔ All from the list

❌ None

Databases and ORM

MongoDB

MySQL

Oracle

PostgreSQL

SQL

SQL server

✔ All from the list

❌ None

Markup languages

HTML

XML

CSS

JSON and JSON5

RELAX NG

T4

XPath

XSLT

YAML

✔ All from the list

Scripting languages

Shell script

Build management

MSBuild

Qodana features

Baseline

Quality gate

Code coverage

License audit

✔ All from the list

* C and C++ inspections are applicable for projects containing .sln files.

** Supports Visual Basic inspections only.

Last modified: 18 June 2024