Skip to content

Add analyzer rule for ArgumentOutOfRangeException.ThrowIfInPast/ThrowIfInFuture #729

Description

@samtrion

Summary

NetEvolve.Arguments provides ArgumentOutOfRangeException.ThrowIfInPast/ThrowIfInFuture overloads for DateTime, DateTimeOffset, and DateOnly (available on .NET 8+ target frameworks), optionally accepting a TimeProvider. NetEvolve.Arguments.Analyser does not currently have a rule that detects the manual equivalent of these checks.

Problem

The "now" side of the comparison varies significantly between codebases and has no single canonical form, e.g.:

if (value < DateTime.UtcNow)
    throw new ArgumentOutOfRangeException(nameof(value));

if (value < DateTime.Now)
    throw new ArgumentOutOfRangeException(nameof(value));

if (value < timeProvider.GetUtcNow())
    throw new ArgumentOutOfRangeException(nameof(value));

if (value > someTimeProvider.GetUtcNow())
    throw new ArgumentOutOfRangeException(nameof(value));

Correctly distinguishing "in the past" vs. "in the future" per type (DateTime vs. DateTimeOffset vs. DateOnly), handling .Now vs. .UtcNow (semantically different — a naive rewrite could silently change behavior for DateTime.Now, which is local time, since the throw-helper always compares against UTC/current time via TimeProvider), and supporting the optional TimeProvider overload significantly increases the risk of an incorrect rewrite compared to the other rules, which is why it was deliberately left out of the initial rule set.

Proposed solution

Design and implement a new rule (next available ID) that recognizes at least the DateTime.UtcNow/DateTimeOffset.UtcNow comparisons (skipping .Now, where a rewrite could change behavior), with a code fix rewriting to ArgumentOutOfRangeException.ThrowIfInPast/ThrowIfInFuture. Investigate whether .Now-based comparisons should be flagged separately (as a correctness issue) rather than auto-fixed.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions