Skip to content

Release v1.0.0

Choose a tag to compare

@github-actions github-actions released this 02 Jun 07:13
910843c

This PR introduces a new Roslyn analyzer package for enforcing CUPID-oriented architecture rules across Cratis codebases, covering CRARCH0001 through CRARCH0026. It also incorporates the requested CRARCH0018 exception: concrete constructor injection is allowed for types marked with [ReadModel].

  • New analyzer package and project layout

    • Added Source/CodeAnalysis as Cratis.Architecture.CodeAnalysis.
    • Added Cratis.Architecture.slnx and analyzer/spec projects under Source/CodeAnalysis and Source/CodeAnalysis.Specs.
  • Analyzer implementation (CRARCH0001–CRARCH0026)

    • Implemented diagnostics for exception naming/types, class naming postfixes, namespace constraints, region usage, logging usage, DI constraints, null checks, string formatting, constructor fan-out, file length, async/blocking patterns, test-type references, static naming, interface usage, namespace-path alignment, concrete-type injection, async method naming, unhandled async invocations, serializable attribute usage, explicit private modifier usage, typed logger category usage, LoggerMessage container conventions, Cratis Fundamentals traces usage, and Cratis Fundamentals metrics usage.
    • Updated diagnostic descriptor descriptions across the implemented rules to be explicit and actionable for both humans and LLMs, clarifying expected remediation.
    • Added:
      • CRARCH0019: warns on Async postfix in method names unless a synchronous method with the same base name exists.
      • CRARCH0020: warns when async-returning invocations are neither awaited nor continued (fire-and-forget).
      • CRARCH0021 (adopted from AS0001): warns when types are marked with [Serializable].
      • CRARCH0022 (adopted from AS0002): warns on explicit private modifiers, with an exception for private setters/init on public properties.
      • CRARCH0023: warns when constructor logging dependencies are not ILogger<TContainingType>.
      • CRARCH0024: warns when types containing [LoggerMessage] methods are not internal static partial classes with LogMessages suffix.
      • CRARCH0025: warns on direct ActivitySource.StartActivity usage and points to Cratis Fundamentals tracing (IActivitySource<T>, IActivityScope<T>, [Span]-generated methods).
      • CRARCH0026: warns on direct Meter.Create* instrument creation and points to Cratis Fundamentals metrics (IMeter<T>, IMeterScope<T>, [Counter]/[Gauge]-generated methods).
    • Tightened:
      • CRARCH0006: warns on direct ILogger.Log* invocations, requiring use of [LoggerMessage] generated methods.
  • CRARCH0018 ReadModel exception

    • Updated concrete-injection detection to skip diagnostics only when the injected concrete type is annotated with the specific Cratis type Cratis.Arc.Queries.ModelBound.ReadModelAttribute.
    • Added spec coverage to ensure lookalike ReadModelAttribute types from non-Cratis namespaces do not qualify for the exception.
  • Code fixes for straightforward rules

    • Added code fix support for:
      • CRARCH0008: == null / != nullis null / is not null
      • CRARCH0009: string.Format(...) → interpolated string (for straightforward placeholder patterns)
  • Focused analyzer specs

    • Added tests validating core behavior, including explicit coverage for:
      • CRARCH0018 warning on regular concrete injection
      • no CRARCH0018 warning when dependency type is marked with Cratis.Arc.Queries.ModelBound.ReadModelAttribute
      • CRARCH0018 warning when a non-Cratis ReadModelAttribute is used
      • CRARCH0019 warning when Async suffix has no synchronous counterpart
      • no CRARCH0019 warning when synchronous counterpart exists
      • CRARCH0020 warning on unhandled async calls
      • no CRARCH0020 warning when async call is continued
      • CRARCH0021 warning on [Serializable]
      • CRARCH0022 warning on explicit private
      • no CRARCH0022 warning for private setter on a public property
      • CRARCH0023 warning on non-generic logger injection
      • CRARCH0023 warning on mismatched logger category type
      • no CRARCH0023 warning for ILogger<TContainingType>
      • CRARCH0024 warning when LoggerMessage container conventions are not followed
      • no CRARCH0024 warning when LoggerMessage container conventions are followed
      • CRARCH0006 warning on direct ILogger.Log* invocation
      • CRARCH0025 warning on direct ActivitySource.StartActivity
      • no CRARCH0025 warning when using Cratis Fundamentals tracing abstractions
      • CRARCH0026 warning on direct Meter.Create* instrument creation
      • no CRARCH0026 warning when using Cratis Fundamentals metrics abstractions

Example of the CRARCH0018 exception now supported:

namespace Cratis.Arc.Queries.ModelBound
{
    public class ReadModelAttribute : Attribute
    {
    }
}

[Cratis.Arc.Queries.ModelBound.ReadModel]
public class CustomerReadModel
{
}

public class Handler
{
    public Handler(CustomerReadModel customer) // no CRARCH0018
    {
    }
}