NineKit.Analyzers (0.1.0)

Published 2026-04-07 20:23:13 +00:00 by forgejo-admin

Installation

dotnet nuget add source --name forgejo-admin --username your_username --password your_token 
dotnet add package --source forgejo-admin --version 0.1.0 NineKit.Analyzers

About this package

NineKit custom Roslyn analyzers.

NineKit.Analyzers

Custom Roslyn analyzers for NineKit solutions to enforce code quality and prevent common anti-patterns.

Available Analyzers

NKA001: Prefer Task over ValueTask in application code

Purpose: Prevents unnecessary use of ValueTask in application code

Triggers:

  • Method returns ValueTask/ValueTask<T> outside of allowed namespaces (Infrastructure, Core, Abstractions, Providers)

Suppresses when:

  • The method is DisposeAsync() (required by IAsyncDisposable)
  • The file path indicates tests or analyzer sources
  • The method or containing type is annotated with [ValueTaskReturnJustification("...")]
  • A [SuppressMessage] attribute is present

Documentation: See docs/dev-guides/task-vs-valuetask.md for policy details


NKA002: High-cardinality data used in metric tags

Purpose: Prevents cardinality explosion in OpenTelemetry/Prometheus metrics

Triggers:

  • Using high-cardinality data (IDs, session IDs, user IDs, execution IDs) as metric tags
  • Counter/Histogram/Record methods with suspicious tag names

Detects:

  • Tag names: execution_id, sessionId, userId, operationId, requestId, traceId, correlationId, transactionId
  • Parameter names containing: id, session, user, execution, request, trace, correlation, transaction
  • Variables with ID-like names

Example:

// ❌ Triggers NKA002
ExecutionDurationHistogram.Record(duration,
    new("execution_id", executionId));  // High cardinality!

// ✅ OK
ExecutionDurationHistogram.Record(duration,
    new("status", status));

Documentation: See docs/dev-guides/metrics-cardinality-best-practices.md for best practices

Suppress:

#pragma warning disable NKA002
// Code here
#pragma warning restore NKA002

Logging template constants (built-in analyzer)

NKA0021 has been removed in favor of the built-in .NET analyzer CA2254 (Template should be a constant). Use CA2254 as the single source of truth for preventing string interpolation and non-constant logging templates.

Configuration: Set centrally in .editorconfig (dotnet_diagnostic.CA2254.severity = warning).


NKA0031: Avoid Rocks mocks for ILogger and IOptions

Purpose: Prevents Rocks source generator bloat from mocking generic framework interfaces.

Triggers:

  • [assembly: Rock(typeof(ILogger<>), BuildType.Create)]
  • [assembly: Rock(typeof(IOptions<>), BuildType.Create)]
  • [assembly: Rock(typeof(IOptionsMonitor<>), BuildType.Create)]
  • Any other Rock(typeof(ILogger<MyType>)), IOptions<T>, or IOptionsMonitor<T> usage

Recommended replacements:

  • FakeLogger<T> or TestLogging.CreateTestLogger<T> for loggers
  • Options.Create(value) or BaseUnitTest.CreateOptions(value) for IOptions<T>
  • BaseUnitTest.CreateOptionsMonitor(value) or TestOptionsMonitor.Create(value) for IOptionsMonitor<T>

NKA103: Use RockContext for automatic Rocks verification

Purpose: Enforces Pattern A (RockContext) over Pattern B (manual .Verify()) for Rocks mocks.

Triggers:

  • .Verify() calls on Rocks expectation objects (e.g., expectations.Verify(), mock.Expectations.Verify())

Rationale:

  • Pattern A (Recommended): using var context = new RockContext(); - Automatic verification
  • Pattern B (Legacy): expectations.Verify(); - Manual verification (error-prone)

RockContext automatically verifies all mocks when disposed, eliminating manual .Verify() calls and preventing missed verifications.

Fix: Replace manual .Verify() with RockContext:

// ❌ Legacy Pattern B - FLAGGED by NKA103
[Test]
public async Task MyTest()
{
    var expectations = new IFooCreateExpectations();
    // ... setup ...
    var result = await service.DoWorkAsync();
    expectations.Verify();  // Manual verification - error-prone!
}

// ✅ Recommended Pattern A
[Test]
public async Task MyTest()
{
    using var context = new RockContext();  // Automatic verification!
    
    var expectations = new IFooCreateExpectations();
    // ... setup ...
    var result = await service.DoWorkAsync();
    // No .Verify() needed - context.Dispose() handles it
}

Configuration: Set to warning level in .editorconfig for test projects during migration, then upgrade to error once migration is complete.

Documentation: See tests/CLAUDE.md - Rocks Mocking Library - Verification Pattern section


Integrating the analyzers

You can consume this analyzer via direct project reference or by packing it as a NuGet package.

Add the analyzer project to your solution:

# Add analyzer project to the solution
DOTNET_CLI_HOME=. dotnet sln SWEMK.slnx add src/Analyzers/NineKit.Analyzers/NineKit.Analyzers.csproj

Then, in each application project (SWEMK.Web, SWEMK.Maui, jobs/APIs as desired), add:

<ItemGroup>
  <ProjectReference Include="../../Analyzers/NineKit.Analyzers/NineKit.Analyzers.csproj"
                    OutputItemType="Analyzer"
                    ReferenceOutputAssembly="false" />
</ItemGroup>

Alternatively, centralize in Directory.Build.props under an ItemGroup scoped to app projects only.

Option B: Pack as NuGet

DOTNET_CLI_HOME=. dotnet pack src/Analyzers/NineKit.Analyzers/NineKit.Analyzers.csproj -c Release

Publish the .nupkg to your internal feed and then add a PackageReference where needed.


Configuration and Tuning

NKA001 Tuning

  • Adjust AllowedNamespaceMarkers / ExcludedPathMarkers in ValueTaskReturnAnalyzer.cs
  • Suppress with [ValueTaskReturnJustification("...")] or [SuppressMessage]

NKA002 Tuning

  • Customize HighCardinalityTagNames array in HighCardinalityMetricAnalyzer.cs
  • Adjust parameter name checks in IsHighCardinalityParameterName()
  • Suppress with [SuppressMessage("Observability", "NKA002")]

Building and Testing

# Build the analyzer
dotnet build src/Analyzers/NineKit.Analyzers/NineKit.Analyzers.csproj

# Run analyzer on solution
dotnet build SWEMK.slnx --verbosity minimal | grep NKA

Versioning

Keep analyzer dependencies aligned with the repo's compiler/tooling. See Directory.Build.props and global.json for SDK versions.


Documentation

  • NKA001: docs/dev-guides/task-vs-valuetask.md
  • NKA002: docs/dev-guides/metrics-cardinality-best-practices.md
  • Summary: CARDINALITY_FIX_SUMMARY.md
Details
NuGet
2026-04-07 20:23:13 +00:00
0
9kit
29 KiB
Assets (2)
Versions (1) View all
0.1.0 2026-04-07