dotnet-add-analyzers

SKILL.md

dotnet-add-analyzers

Add and configure .NET code analyzers to an existing project. Covers built-in Roslyn CA rules, nullable reference types enforcement, trimming/AOT compatibility analyzers, and third-party analyzer packages.

Prerequisites: Run [skill:dotnet-version-detection] first — analyzer features vary by SDK version. Run [skill:dotnet-project-analysis] to understand the current project layout.

Scope

  • Built-in Roslyn CA rules and AnalysisLevel configuration
  • Nullable reference types enforcement
  • Trimming and AOT compatibility analyzers
  • Third-party analyzer packages and severity configuration

Out of scope

  • EditorConfig hierarchy and IDE code style preferences -- see [skill:dotnet-editorconfig]
  • Solution layout and Directory.Build.props -- see [skill:dotnet-project-structure]
  • New project scaffolding with analyzers -- see [skill:dotnet-scaffold-project]

Cross-references: [skill:dotnet-project-structure] for where build props/targets live, [skill:dotnet-scaffold-project] which includes analyzer setup in new projects, [skill:dotnet-editorconfig] for EditorConfig hierarchy/precedence, IDE code style preferences, naming rules, and global AnalyzerConfig files.


Built-in Roslyn Analyzers

.NET SDK ships built-in analyzers controlled by AnalysisLevel. Configure in Directory.Build.props:


<PropertyGroup>
  <AnalysisLevel>latest-all</AnalysisLevel>
  <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
  <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>

```text

### AnalysisLevel Values

| Value                | Behavior                                           |
| -------------------- | -------------------------------------------------- |
| `latest`             | Default rules only — covers correctness, not style |
| `latest-minimum`     | Fewer rules than default                           |
| `latest-recommended` | Default + additional recommended rules             |
| `latest-all`         | All rules enabled — most comprehensive             |
| `9-all`, `10-all`    | Pin to a specific SDK version's full rule set      |

`latest-all` is recommended for new projects. For existing projects with many warnings, start with `latest-recommended`
and tighten over time.

### Rule Categories

| Category      | Prefix                        | Examples                                                           |
| ------------- | ----------------------------- | ------------------------------------------------------------------ |
| Design        | CA1xxx                        | CA1002 (don't expose generic lists), CA1062 (validate arguments)   |
| Globalization | CA1300–CA1399                 | CA1304 (specify CultureInfo)                                       |
| Performance   | CA1800–CA1899                 | CA1822 (mark members static), CA1848 (use LoggerMessage)           |
| Reliability   | CA2000–CA2099                 | CA2000 (dispose objects), CA2007 (ConfigureAwait)                  |
| Security      | CA2100–CA2199, CA3xxx, CA5xxx | CA2100 (SQL injection), CA3075 (XML processing)                    |
| Usage         | CA2200–CA2299                 | CA2211 (non-constant static fields), CA2245 (don't assign to self) |
| Naming        | CA1700–CA1799                 | CA1707 (no underscores in identifiers)                             |
| Style         | IDE0xxx                       | IDE0003 (this qualification), IDE0063 (using declaration)          |

---

## EditorConfig Severity Overrides

Fine-tune analyzer severity per-rule in `.editorconfig`:

```ini

[*.cs]
# Suppress specific rules
dotnet_diagnostic.CA1062.severity = none          # Nullable handles this
dotnet_diagnostic.CA2007.severity = none          # Not needed in ASP.NET Core apps

# Escalate to error
dotnet_diagnostic.CA1822.severity = error         # Mark members as static
dotnet_diagnostic.CA1848.severity = warning       # Use LoggerMessage delegates

# Style enforcement
dotnet_diagnostic.IDE0005.severity = warning      # Remove unnecessary usings
dotnet_diagnostic.IDE0063.severity = warning      # Use simple using statement
dotnet_diagnostic.IDE0090.severity = warning      # Simplify new expression

```text

### Common Suppressions by Project Type

**ASP.NET Core apps** — suppress ConfigureAwait warnings:

```ini

dotnet_diagnostic.CA2007.severity = none

```text

**Libraries** — keep CA2007 as warning (callers may not have a SynchronizationContext):

```ini

dotnet_diagnostic.CA2007.severity = warning

```text

**Test projects** — relax certain rules:

```ini

dotnet_diagnostic.CA1707.severity = none          # Allow underscores in test names
dotnet_diagnostic.CA1062.severity = none          # Parameters validated by test framework
dotnet_diagnostic.CA2007.severity = none          # ConfigureAwait not relevant

```text

---

## Nullable Reference Types

Enable globally in `Directory.Build.props`:

```xml

<PropertyGroup>
  <Nullable>enable</Nullable>
</PropertyGroup>

```xml

Nullable analysis produces warnings (CS86xx) not CA rules. Related settings:

```xml

<PropertyGroup>
  <!-- Treat nullable warnings as errors -->
  <WarningsAsErrors>$(WarningsAsErrors);nullable</WarningsAsErrors>
</PropertyGroup>

```text

For gradual adoption in existing codebases, enable per-file:

```csharp

#nullable enable

```csharp

See [skill:dotnet-csharp-nullable-reference-types] for annotation strategies and patterns.

---

## Trimming and AOT Compatibility Analyzers

### Applications

For apps published with trimming or Native AOT, enable the analyzers alongside the publish properties:

```xml

<PropertyGroup>
  <!-- Enable trimmed publishing + analysis -->
  <PublishTrimmed>true</PublishTrimmed>
  <EnableTrimAnalyzer>true</EnableTrimAnalyzer>

  <!-- Enable AOT publishing + analysis -->
  <PublishAot>true</PublishAot>
  <EnableAotAnalyzer>true</EnableAotAnalyzer>

  <!-- Single-file analysis (subset of trim analysis) -->
  <EnableSingleFileAnalyzer>true</EnableSingleFileAnalyzer>
</PropertyGroup>

```text

Enable the analyzers early (even before publishing trimmed) to catch issues during development. `EnableTrimAnalyzer` and
`EnableAotAnalyzer` can be set independently of `PublishTrimmed`/`PublishAot`.

### Libraries

Libraries use `IsTrimmable` and `IsAotCompatible` to declare compatibility to consumers. Enable these even if consumers
don't trim yet:

```xml

<PropertyGroup>
  <IsTrimmable>true</IsTrimmable>
  <IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>

```text

Setting `IsTrimmable`/`IsAotCompatible` automatically enables the corresponding analyzers. This ensures the library
works correctly when consumers eventually enable trimming/AOT.

### What the Analyzers Flag

These analyzers flag:

- Reflection usage that breaks trimming (IL2xxx warnings)
- P/Invoke patterns incompatible with AOT
- Dynamic code generation (`Reflection.Emit`, `System.Linq.Expressions` compilation)
- Types not annotated with `[DynamicallyAccessedMembers]`

---

## Third-Party Analyzers

Add via `Directory.Build.targets` so they apply to all projects:

```xml

<!-- Directory.Build.targets -->
<Project>
  <ItemGroup>
    <PackageReference Include="Meziantou.Analyzer" PrivateAssets="all" />
    <PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" PrivateAssets="all" />
  </ItemGroup>
</Project>

```text

With CPM, add version entries in `Directory.Packages.props`:

```xml

<PackageVersion Include="Meziantou.Analyzer" Version="2.0.187" />
<PackageVersion Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="3.11.0-beta1.25058.1" />

```xml

### Recommended Analyzer Packages

| Package                                     | Focus                                                  |
| ------------------------------------------- | ------------------------------------------------------ |
| `Meziantou.Analyzer`                        | Security, performance, best practices (broad coverage) |
| `Microsoft.CodeAnalysis.BannedApiAnalyzers` | Ban specific APIs via `BannedSymbols.txt`              |
| `Microsoft.CodeAnalysis.PublicApiAnalyzers` | Track public API surface (library authors)             |
| `SonarAnalyzer.CSharp`                      | Security, reliability, maintainability                 |

### BannedSymbols.txt

When using `BannedApiAnalyzers`, create `BannedSymbols.txt` at the repo root and include it:

```xml

<!-- Directory.Build.targets -->
<ItemGroup>
  <AdditionalFiles Include="$(MSBuildThisFileDirectory)BannedSymbols.txt"
                   Condition="Exists('$(MSBuildThisFileDirectory)BannedSymbols.txt')" />
</ItemGroup>

```text

Example `BannedSymbols.txt`:

```text

T:System.DateTime;Use DateTimeOffset instead
M:System.DateTime.Now;Use DateTimeOffset.UtcNow instead
T:System.GC;Do not call GC methods directly

```text

---

## Adding Analyzers to an Existing Project

1. **Enable built-in analyzers** — set `AnalysisLevel` and `EnforceCodeStyleInBuild` in `Directory.Build.props`
2. **Start at recommended level** — use `latest-recommended` if `latest-all` produces too many warnings
3. **Add EditorConfig overrides** — suppress rules that don't apply to your project type
4. **Add third-party analyzers** — via `Directory.Build.targets` with CPM versions
5. **Fix incrementally** — enable `TreatWarningsAsErrors` only after addressing existing warnings, or use `<NoWarn>`
   temporarily for categories being addressed

### Incremental Adoption Pattern

For large codebases, avoid fixing all warnings at once:

```xml

<!-- Directory.Build.props — temporary during migration -->
<PropertyGroup>
  <AnalysisLevel>latest-recommended</AnalysisLevel>
  <!-- Fix these categories first, then remove NoWarn entries -->
  <NoWarn>$(NoWarn);CA1822;CA1848</NoWarn>
</PropertyGroup>

```text

Remove `NoWarn` entries as each category is addressed. Track progress with:

```bash

dotnet build 2>&1 | grep -oE 'CA[0-9]+' | sort | uniq -c | sort -rn

```bash

---

## References

- [Code Analysis Overview](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview)
- [Configure Analyzers](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/configuration-options)
- [Trimming Analyzer](https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/prepare-libraries-for-trimming)
- [AOT Compatibility](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/)
- [EditorConfig for .NET](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/code-style-rule-options)
Weekly Installs
1
First Seen
11 days ago
Installed on
amp1
cline1
opencode1
cursor1
kimi-cli1
codex1