6.4.2. Source Code Analysis for C#/.NET

6.4.2.1. Introduction

The information in this chapter is only relevant to the C#/.NET variant of the Axivion Suite.

For the C# analysis, the first step is to make sure that the project(s) to be analyzed can be built from command-line in the environment executing the analysis (using a msbuild, dotnet msbuild or dotnet build command). This is necessary, because csharp2rfg interprets solutions and project files very similar to msbuild, but instead of using csc to produce binary outputs, it uses all source code files, binary references and configuration options collected by msbuild to generate an RFG and calculate metrics, or to produce a C# package, which can be loaded and analyzed later.

If you are using a different build system (such as cake), it may be necessary to first generate MSBuild solution/project files for use with csharp2rfg.

The following tools can be used with C#:

axivion_ci

Using the AxivonC#Frontend build step a C# program - consisting of one or more C# MSBuild projects - can be compiled and various Axivion analysis rules can be configured to analyze the C# source code.

csharp2rfg

csharp2rfg compiles C# source code into a C# package, which can be loaded and analyzed later, or creates an RFG and performs calculation of metrics.

axivion_analysis

axivion_analysis can apply Axivion analysis rules on a pre-built C# package (.cspkg) created by the AxivionC#Frontend build step (invoked by axivion_ci) or csharp2rfg.

Note

This chapter focuses on the description of csharp2rfg. The AxivionC#Frontend build step uses csharp2rfg internally, so the description also applies to it, unless noted otherwise.

6.4.2.2. Requirements

The current version of csharp2rfg requires .NET 8.0 to run and can be executed on any platform that supports .NET 8.0 (recommended runtime version: 8.0.13 or higher on GNU/Linux ARM64 and 8.0.4 or higher on all other supported platforms).

csharp2rfg is capable of processing any valid C# program as accepted by Microsoft’s C# compiler csc.exe. The currently supported versions of C# are:

  • C# 1.0 (Visual Studio .NET)

  • C# 2.0 (Visual Studio 2005)

  • C# 3.0 (Visual Studio 2008)

  • C# 4.0 (Visual Studio 2010)

  • C# 5.0 (Visual Studio 2012)

  • C# 6.0 (Visual Studio 2015)

  • C# 7.x (Visual Studio 2017)

  • C# 8.0 (Visual Studio 2019)

  • C# 9.0 (Visual Studio 2019 [16.8] / .NET 5.0)

  • C# 10.0 (Visual Studio 2022 [17.0] / .NET 6.0)

  • C# 11.0 (Visual Studio 2022 [17.4] / .NET 7.0)

  • C# 12.0 (Visual Studio 2022 [17.8] / .NET 8.0)

  • C# 13.0 (Visual Studio 2022 [17.12] / .NET 9.0)

Using csharp2rfg with a newer version of C# is possible, but the analysis results are likely incomplete and may produce errors and is generally not recommended.

csharp2rfg supports processing MSBuild solutions, solution filters and project files using the following MSBuild versions:

  • MSBuild 15.3 or higher (Visual Studio 2017)

  • MSBuild 16.x (Visual Studio 2019)

  • MSBuild 17.x (Visual Studio 2022)

Using csharp2rfg with a newer or an older version of MSBuild is possible in theory, but may require additional configuration and is generally not recommended.

6.4.2.3. Usage with axivion_ci

Note

This section describes how to manually configure axivion_ci by using axivion_config. The setup wizard currently does not support C#.

csharp2rfg should be invoked as part of axivion_ci by using the AxivionC#Frontend action in BuildSystemIntegration. It can be configured by following these steps:

Prerequisites

Before configuring AxivionC#Frontend for the first time in a project, it is necessary to set some global properties:

  1. Set /Project/directory to the repository root.

  2. Set /Project/name to the name of the project.

  3. Set /Dashboard/dashboard_url to the URL where the Axivion Dashboard is hosted.

  4. Set the environment variable AXIVION_DATABASES_DIR to the correct location.

Setup of AxivionC#Frontend

  1. Create a new copy of AxivionC#Frontend.

  2. Set the field input to the item you want to analyze. This can be one of the following:

  1. a single C# source code file (.cs)

  2. a directory containing one or more C# source code files (.cs)

  3. a single Visual Studio C# project file (.csproj)

  4. a single Visual Studio Solution file (.sln)

  5. a single Visual Studio Solution filter file (.slnf)

3. If you are analyzing a single C# source code file (.cs) or a directory without any MSBuild project:

a. If it does not contain a Main method, it may be necessary to set the field project_is_library accordingly.

b. Set the field framework_path to the directory containing all assemblies (including BCL [base-class library] assemblies).

4. If you are analyzing a project or solution, csharp2rfg tries to detect the matching MSBuild version automatically, but if that fails you need to make sure that the correct version of MSBuild is used, you can manually set the msbuild_path option, to the correct version.

5. Make sure that the correct configuration and platform is used, unlike Visual Studio, csharp2rfg might not be able to infer them correctly, therefore it is a good idea to set them explicitly using the fields build_configuration and build_platform.

6. If your project uses new-style (aka SDK-style) projects, and you target multiple frameworks, it may be necessary to choose one target-framework for analysis. An analysis cannot contain multiple target frameworks. You can use the field build_target_framework to specify one explicitly.

7. If you project needs additional MSBuild variables you can use the field properties to pass a list of key-value pairs.

Note

If any problems occur during the execution of csharp2rfg or axivion_ci it is a good idea to set the binarylog option and the --verbose flag to get a better understanding of what is going on.

Note

For cycle detection it is necessary to disable the create_multiple_edges setting.

8. Configure analyses and additional build steps, as necessary. Note that not every rule is applicable to C#. Please see Limitations for more information.

6.4.2.4. Usage with axivion_analysis

axivion_analysis is intended for use with pre-built C# package files (.cspkg) and can be used to run analyses without having to first execute any build step. axivion_analysis accepts a –csharp PACKAGE_FILE option.

A C# package file (.cspkg) can be created by using csharp2rfg on the command-line or using the AxivionC#Frontend build step from axivion_ci.

About C# package files

Caution

C# package files contain potentially sensitive information and artifacts.

C# packages are archives that store all information necessary to compile a C# program. This includes all source code, resources, binary references, strong name keys and compiler configuration. Its contents will be visible to anyone having access to the C# package file.

6.4.2.5. Standalone usage

Standalone usage is similar to the steps used when setting up axivion_ci for C#. All options that can be set in the configuration UI can be directly passed to csharp2rfg on the command-line as well.

Command-Line Switches

csharp2rfg
  [-h]
  [--library]
  [--no_duplicate_edges]
  [--no_restore]
  [--only_used_types]
  [--configuration CONFIGURATION]
  [--target_framework TARGET_FRAMEWORK]
  [-t TARGETS]
  [--platform PLATFORM]
  [-p KEY=VALUE]
  [-r REFERENCE]
  [--framework_path FRAMEWORK_PATH]
  [--binarylog [BINARYLOG]]
  [-B BASEPATH]
  [--msbuild_path MSBUILD_PATH]
  [--list_msbuild_paths]
  [--verbose]
  input output

Creates a RFG from provided C# source file(s) or projects.

input

input path, can be a .cs file, a .csproj file, .sln, .slnf file or a directory containing .cs files

output

output file, must be a path to a .rfg file

--help

show this help message and exit

--library

When analyzing a single file or directory, use this flag to indicate whether the result is a library (i.e., has no Main method/entry-point) or not.

--no_duplicate_edges

The RFG should not contain multiple edges of the same kind (ignoring edge attributes) between two nodes. This happens for example, when a method calls the same method multiple times.

--no_restore

Do not execute a package restore before compilation.

--only_used_types

Only include types defined in source code and their dependencies in the RFG.

--configuration CONFIGURATION

Solution configuration to use for compilation. Default value: “Debug”

--target_framework TARGET_FRAMEWORK

Solution target framework to use for compilation.

--targets TARGETS

Build targets to invoke. Multiple values can be specified separated by comma or semi-colon. Default: Clean,Build (short form: -t)

--platform PLATFORM

Solution platform to use for compilation. Default value: “AnyCPU”

--property PROPERTY

Additional MSBuild properties to use for compilation. Can be used repeatedly to define multiple properties. (short form: -p)

--reference REFERENCE

References used when analyzing a single file or directory. Can be used repeatedly to define multiple references. (short form: -r)

--framework_path FRAMEWORK_PATH

When analyzing a single file or directory that depends on .NET Core and later, use this option to set a path to framework assemblies.

–binarylog [BINARYLOG]

Produce a binary log of the build. A filename can be added using “–binarylog <filename>”, if no filename is set, “msbuild.binlog” is used. If multiple projects are analyzed the argument is interpreted as directory name and each build is stored in a separate binary log in that directory. The file extension “.binlog” is appended automatically if absent.

--basepath BASEPATH

Specify a basepath of your project. If absent, inferred from environment or input path.

--msbuild_path MSBUILD_PATH

Sets the path to the version of MSBuild to be used in the analysis, should be set to the MSBuild version that is used to build the project to be analyzed. This should point directly to MSBuild.exe (or MSBuild.dll for newer versions of .NET).

--list_msbuild_paths

Will print a list of detected MSBuild installations and exit.

--verbose

Enable extra debug output. (short form: -v)

6.4.2.6. Integration of third-party analyzers and checks

axivion_ci or csharp2rfg support the execution of third-party Roslyn-based analyses. In general analyzers can be consumed from a VSIX package or a NuGet package. Axivion currently only supports executing analyzers from NuGet packages using a PackageReference.

The Axivion rule C#-ImportCompilerAndAnalyzerDiagnostics can be used to import any compiler warnings and analyzer diagnostics into the Axivion dashboard.

If you want to skip the execution of third-party analyzers during the execution of AxivionC#Frontend or csharp2rfg, you can set the MSBuild properties RunAnalyzers or RunAnalyzersDuringBuild to false.

6.4.2.7. Limitations

csharp2rfg does not produce an IR and therefore does not support all rules and checks provided by the Axivion Suite.

The following Axivion Suite core features are supported:

  • Architecture analysis

  • Cycle Detection (RFG-based)

  • Clone Detection (using C#CloneDetection)

  • C#-specific RFG transformations

  • RFG-based metrics

  • Stylechecks in the C# rule group

The following additional features are supported:

  • EntryPoints-EntriesByAttribute

  • EntryPoints-EntriesByLinkname

  • EntryPoints-EntriesByName

  • EntryPoints-EntriesByPath

6.4.2.8. Frequently Asked Questions

  • I am able to build my project successfully using MSBuild, but I am seeing various errors during execution of csharp2rfg. How do I solve this?

    1. Make sure that the correct version of MSBuild is used, you can manually set the msbuild_path option, to the correct version, if auto-detection fails.

    2. Make sure that the correct configuration and platform is used, unlike Visual Studio, csharp2rfg might not be able to infer them correctly, therefore it is a good idea to set them explicitly.

    3. If your project uses new-style (aka SDK-style) projects, and you target multiple frameworks, it may be necessary to choose one target-framework for analysis. An analysis cannot use multiple target frameworks. You can use the target_framework option (build_target_framework in the UI) to specify one explicitly.