static-analysis

SKILL.md

.NET Static Analysis

Built-in Analyzers

.NET Analyzers

.NET SDK includes analyzers for code quality and style. Enable in project file:

<PropertyGroup>
  <!-- Enable all .NET analyzers -->
  <EnableNETAnalyzers>true</EnableNETAnalyzers>

  <!-- Analysis level (latest, 8.0, 7.0, etc.) -->
  <AnalysisLevel>latest</AnalysisLevel>

  <!-- Analysis mode: Default, Minimum, Recommended, All -->
  <AnalysisMode>Recommended</AnalysisMode>
</PropertyGroup>

Analysis Categories

Category Prefix Focus
Design CA1xxx API design guidelines
Globalization CA2xxx Internationalization
Performance CA18xx Performance optimizations
Security CA2xxx, CA3xxx Security vulnerabilities
Usage CA2xxx Correct API usage
Naming CA17xx Naming conventions
Reliability CA2xxx Error handling, resources

Running Analysis

With Build

# Build with analyzers (default)
dotnet build

# Ensure analyzers run
dotnet build /p:RunAnalyzersDuringBuild=true

# Treat warnings as errors
dotnet build /p:TreatWarningsAsErrors=true

# Run only analyzers (no compile)
dotnet build /p:RunAnalyzers=true /p:RunCodeAnalysis=true

As Separate Step

# Format check (style only)
dotnet format --verify-no-changes

# Format and fix
dotnet format

# Analyze specific project
dotnet build src/MyApp/MyApp.csproj /p:TreatWarningsAsErrors=true

Configuring Rules

EditorConfig

# .editorconfig
root = true

[*.cs]
# Naming conventions
dotnet_naming_rule.private_fields_should_be_camel_case.severity = warning
dotnet_naming_rule.private_fields_should_be_camel_case.symbols = private_fields
dotnet_naming_rule.private_fields_should_be_camel_case.style = camel_case_style

dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private

dotnet_naming_style.camel_case_style.capitalization = camel_case
dotnet_naming_style.camel_case_style.required_prefix = _

# Code style
csharp_style_var_for_built_in_types = true:suggestion
csharp_style_expression_bodied_methods = when_on_single_line:suggestion
csharp_prefer_braces = true:warning

# Analyzer rules
dotnet_diagnostic.CA1062.severity = warning  # Validate arguments
dotnet_diagnostic.CA2007.severity = none     # Don't require ConfigureAwait
dotnet_diagnostic.IDE0044.severity = warning # Make field readonly

GlobalAnalyzerConfig

# .globalconfig
is_global = true

# Apply to all projects
dotnet_diagnostic.CA1062.severity = warning
dotnet_diagnostic.CA2000.severity = error

Project-Level

<PropertyGroup>
  <!-- Suppress in entire project -->
  <NoWarn>$(NoWarn);CA1062;CA2007</NoWarn>

  <!-- Treat specific as error -->
  <WarningsAsErrors>$(WarningsAsErrors);CA2000</WarningsAsErrors>
</PropertyGroup>

Suppressing Warnings

Code-Level Suppression

// Suppress on member
[SuppressMessage("Design", "CA1062:Validate arguments",
    Justification = "Validated by framework")]
public void Process(Request request) { }

// Suppress on line
#pragma warning disable CA1062
public void Process(Request request) { }
#pragma warning restore CA1062

// Suppress all in file
[assembly: SuppressMessage("Design", "CA1062")]

Global Suppressions

// GlobalSuppressions.cs
using System.Diagnostics.CodeAnalysis;

[assembly: SuppressMessage("Design", "CA1062",
    Scope = "namespaceanddescendants",
    Target = "~N:MyApp.Controllers")]

Common Analyzer Rules

CA1062 - Validate Arguments

// Warning: parameter 'request' is never validated
public void Process(Request request)
{
    request.Execute();  // CA1062
}

// Fixed
public void Process(Request request)
{
    ArgumentNullException.ThrowIfNull(request);
    request.Execute();
}

CA2007 - ConfigureAwait

// Warning in library code
await SomeAsync();  // CA2007

// Fixed
await SomeAsync().ConfigureAwait(false);

// Or suppress in application code (.editorconfig)
dotnet_diagnostic.CA2007.severity = none

CA1822 - Mark Members Static

// Warning: can be static
public int Calculate(int x) => x * 2;  // CA1822

// Fixed
public static int Calculate(int x) => x * 2;

IDE0044 - Make Field Readonly

// Warning
private int _value;  // IDE0044

// Fixed
private readonly int _value;

CA2000 - Dispose Objects

// Warning: not disposed
public void Process()
{
    var stream = new FileStream("file.txt", FileMode.Open);
}  // CA2000

// Fixed
public void Process()
{
    using var stream = new FileStream("file.txt", FileMode.Open);
}

dotnet format

Check Formatting

# Check without changes
dotnet format --verify-no-changes

# Check specific files
dotnet format --include "src/**/*.cs" --verify-no-changes

# Exclude paths
dotnet format --exclude "**/Migrations/**"

Apply Fixes

# Fix all issues
dotnet format

# Fix style issues only
dotnet format style

# Fix analyzers only
dotnet format analyzers

# Fix specific severity
dotnet format --severity warn

Targeting

# Whitespace only
dotnet format whitespace

# Style and analyzers
dotnet format style
dotnet format analyzers

# Specific diagnostics
dotnet format --diagnostics CA1062 IDE0044

Third-Party Analyzers

StyleCop.Analyzers

dotnet add package StyleCop.Analyzers
# .editorconfig
# Configure StyleCop rules
dotnet_diagnostic.SA1101.severity = none  # Prefix local calls with this
dotnet_diagnostic.SA1200.severity = none  # Using directives placement
dotnet_diagnostic.SA1633.severity = none  # File header

Roslynator

dotnet add package Roslynator.Analyzers

SonarAnalyzer

dotnet add package SonarAnalyzer.CSharp

CI Integration

Quality Gate Script

#!/bin/bash
# Run build with analysis
dotnet build --no-restore /p:TreatWarningsAsErrors=true

# Check format
dotnet format --verify-no-changes

# Exit with error if any issues
exit $?

Azure DevOps

- task: DotNetCoreCLI@2
  displayName: 'Build with Analysis'
  inputs:
    command: build
    arguments: '/p:TreatWarningsAsErrors=true'

See analyzers.md for detailed analyzer configurations.

Weekly Installs
7
GitHub Stars
1
First Seen
Jan 25, 2026
Installed on
opencode5
gemini-cli4
github-copilot4
codex4
claude-code3
amp3