Skip to content

NDLRGEN063: Constructor can be generated by Needlr

Cause

A top-level non-record class declares one public constructor whose parameter signature, supported guard calls, and private readonly field assignments exactly match a constructor that Needlr can generate.

The diagnostic defaults to Info. It is a suggestion, not a requirement imposed on all Needlr consumers.

Rule Description

Needlr reports this diagnostic only when replacing the authored constructor preserves:

  • parameter names, types, and declaration order;
  • constructor accessibility;
  • supported ThrowIfNull, ThrowIfNullOrEmpty, or ThrowIfNullOrWhiteSpace guard behavior;
  • direct assignment to matching private readonly fields.

The analyzer does not report constructors that derive or normalize values, copy inputs, transfer ownership, initialize additional state, perform side effects, use constructor chaining, pass base-constructor arguments, expose overloads, or otherwise require developer intent.

The generated-constructor feature is independent of automatic DI registration, so the diagnostic can apply to manually constructed classes and to classes marked [DoNotAutoRegister].

How to Fix

Replace the constructor with eligible fields on a partial class and select the appropriate generated guard mode.

// WRONG - NDLRGEN063
public sealed class UserService
{
    private readonly IRepository _repository;

    public UserService(IRepository repository)
    {
        ArgumentNullException.ThrowIfNull(repository);
        _repository = repository;
    }
}
// CORRECT
using NexusLabs.Needlr.Generators;

[GenerateConstructor(ConstructorNullGuardMode.NonNullableReferences)]
public sealed partial class UserService
{
    private readonly IRepository _repository;
}

For a guard that is not supplied by the class-level mode, apply the matching field attribute:

// CORRECT
using NexusLabs.Needlr.Generators;

[GenerateConstructor]
public sealed partial class TenantService
{
    [ConstructorGuard(ConstructorGuardKind.NotNullOrWhiteSpace)]
    private readonly string _tenantName;
}

Enforcing the Suggestion

Promote the diagnostic in repositories that require the pattern:

[*.cs]
dotnet_diagnostic.NDLRGEN063.severity = warning

Projects that treat warnings as errors will then reject mechanically replaceable hand-written constructors while other Needlr consumers retain the non-blocking default.

See Also