Skip to content

Add DM0026 and a code fix that makes the service type explicit - #126

Merged
ipjohnson merged 1 commit into
mainfrom
agent/124-add-dm0026-and-its-code-fix
Oct 28, 2026
Merged

ipjohnson merged 1 commit into
mainfrom
agent/124-add-dm0026-and-its-code-fix

Conversation

@ipjohnson

@ipjohnson ipjohnson commented Oct 27, 2026 •

Copy link
Copy Markdown
Owner

What changed

This adds DM0026, an analyzer that reports [SingletonService], [ScopedService] and [TransientService] attributes without As = typeof(...). It is off by default. It also adds a code fix that writes the type the generator infers now.

ServiceTypeAnalyzer is in the generator assembly. It calls ServiceTypeInference and passes the inferred type to the fix in the diagnostic's properties. It passes the type only when typeof of it, bound at the attribute, reads back as the same type. ServiceTypeCodeFixProvider is in a new DependencyModules.CodeFixes project. That project references only Roslyn and is packed beside the generator in analyzers/dotnet/cs. scripts/verify-packages.sh checks that the DLL is in the package and that a consumer build with DM0026 set to error fails with DM0026. website/reference/diagnostics.md documents DM0026.

Closes #124. Part of #122.

Why

Projects that want every registration written out can turn DM0026 on and apply the fix, including Fix All, without changing what the container gets. The code fix is a separate assembly because a generator assembly must not reference Microsoft.CodeAnalysis.Workspaces (RS1038).

How it was tested

  • dotnet test tests/DependencyModules.Tests -c Release --filter "ServiceTypeCodeFixTests|CodeFixAssemblyTests|PublicApiTests|ServiceTypeInference" passes 50 tests on net8.0 and net10.0.
  • ApplyingEveryFix_LeavesTheRegistrationsUnchanged builds the module, applies all 12 fixes, builds it again, and compares the service type, lifetime, key and implementation type of each registration.
  • ./scripts/verify-packages.sh passes for net8.0 and net10.0.
  • dotnet csharpier check . is clean.
  • dotnet pack lists analyzers/dotnet/cs/DependencyModules.CodeFixes.dll, and the nuspec has no dependencies.

Review guide

Start with src/DependencyModules.SourceGenerator/ServiceTypeAnalyzer.cs, mainly WritableServiceType, which decides when a fix is offered. Then read src/DependencyModules.CodeFixes/ServiceTypeCodeFixProvider.cs, mainly WithAs, which edits only the argument list. The tests are in tests/DependencyModules.Tests/GeneratorTests/ServiceTypeCodeFixTests.cs.

To check by hand, open a project that uses the packed package in Visual Studio or Rider, set dotnet_diagnostic.DM0026.severity = warning, and apply the fix and Fix All. No IDE was run for this change.

Answers to the item's questions:

  • The packed code fix DLL references only Roslyn, System.Composition, System.Collections.Immutable and netstandard. CodeFixAssemblyTests loads it in a context that refuses every other assembly, so an IDE should load it without a FileNotFoundException for a sibling DLL.
  • The analyzer matches the attribute by symbol and As by its written name, the same check the generator uses. Aliased and fully qualified attributes are found and fixed.

Notes:

  • ServiceTypeCodeFixTests.cs adds four xUnit1051 warnings per target framework. Those calls do not pass TestContext.Current.CancellationToken.
  • A keyed factory method generates code that fails with CS1503. This is an existing generator bug. The round-trip test leaves the key off that factory, and a follow-up step tracks the bug.
  • ServiceModelUtility.GetTypeDeclarationDefinition changed from private to internal so the analyzer can call it.

🤖 Generated with Claude Code


Agent Driver: sessions 6b413364 and ba4bdc11, Task 467d4213 (Require explicit As on service attributes), item add-dm0026-and-its-code-fix. Open on your network

ServiceTypeAnalyzer reports [SingletonService], [ScopedService] and
[TransientService] without As = typeof(...). It is off by default. It
computes the inferred type with ServiceTypeInference and passes it to
the code fix in the diagnostic's properties, so the fix writes what the
generator registers and the code fix assembly references only Roslyn.

The code fix is in DependencyModules.CodeFixes, because a generator
assembly must not reference Microsoft.CodeAnalysis.Workspaces (RS1038).
It is packed beside the generator in analyzers/dotnet/cs.

Part of #122. Closes #124.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Driver-Session: 6b413364-2a61-4a69-81a1-b0d64aba5bf5
@ipjohnson
ipjohnson merged commit da50161 into main Oct 28, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add DM0026 and its code fix

1 participant