Skip to content

Extract framework-agnostic builder/DTO model into its own project #233

Open

Description

@AndreasIgel

Summary

The SonarCloud new-code Duplication density on main is ~7.6% (limit 3%), failing the quality gate. The duplication is by design: the processor carries two parallel model families — a generation-side model (BuilderDefinitionDto, BuilderMethodDto, FieldDto, ...) and a rendering-side model (GenerationTargetClassDto, MethodDto, ...), bridged by BuilderToGenerationTypeMapper. They are ~90% structurally identical, which Sonar counts as duplication.

Rather than force a base-class refactor, we will resolve this by extracting the fundamental, framework-agnostic model into its own project.

Goal

Provide a standalone, reusable foundation that any annotation processor could build on:

  • A clean set of DTOs describing the class/builder/field/method model that users work with.
  • Hide the concrete framework tooling used to actually emit source (currently Roaster) behind that model, so consumers depend on the DTOs, not on the code-generation library.
  • Easy setup: define the DTOs, hand them to the generator, get generated classes — without wiring up framework internals.

Proposed direction (to refine during design)

  • New module/project (e.g. codegen-model / codegen-core) containing the neutral DTOs + a generator SPI.
  • Move/merge the currently-duplicated generation & rendering models into that single model, eliminating the parallel duplication.
  • simple-builders processor depends on it and maps @SimpleBuilder analysis results onto the shared model.
  • Keep the Roaster-based emitter behind an interface so it can be swapped.

Acceptance criteria

  • Shared model extracted to its own project/module; the parallel generation/rendering duplication is removed at the source.
  • SonarCloud new-code Duplication condition no longer flags the parallel DTOs.
  • simple-builders behavior and generated output unchanged (generated example builders byte-identical).
  • Documented, minimal setup for defining DTOs and generating classes without exposing the framework tooling.

Notes

Until this lands, the duplication gate condition is accepted (agreed with maintainer). Related quality-gate items are tracked separately: NPE reliability fixes and the fork-sonar.yml security analysis task.

Activity

  1. added this to the v0.7.0 milestone on Aug 30, 2026
  2. changed the title [-]Extract framework-agnostic builder/DTO model into its own project (resolves Sonar duplication gate)[/-] [+]Extract framework-agnostic builder/DTO model into its own project[/+] on Oct 3, 2026
  3. igel-devin-ai commented on Oct 12, 2026

    @igel-devin-ai
    Collaborator

    Extraction plan (agreed)

    Target architecture: two Maven artifacts — simple-codegen (framework-agnostic annotation-processing / code-generation layer, package root org.javahelpers.simple.codegen) and simple-codegen-roaster (Roaster backend implementing the ClassCodeGenerator SPI). The processor keeps its builder-specific parts and calls the backend through the SPI; Roaster stays hidden behind it.

    History preservation: decouple first, move second — all git mv moves happen after the classes no longer import builder internals, so Git's rename detection and git log --follow keep the full file history. Moves use one rename-safe commit per group where practical; old paths remain in history.

    Subtasks

    Key decisions

    • ProcessingLogger takes no decision boolean: new ProcessingLogger(env) vs. ProcessingLogger.verbose(env) factory over a private Verbosity enum.
    • Strict-mode reporting stays via GenerationIssueReporter (functional interface) in GenerationEnvironment — the Roaster backend never sees ProcessingContext.
    • The mapper gets MapperOptions (copyTypeAnnotations flag + generatedTypeResolver function typed on ResolvedBuilder); builder wiring lives in BuilderDefinitionCreator.
    • findConstructorForBuilder is parameterized by the constructor marker annotation; the builder caller passes SimpleBuilderConstructor.
    • Phase constants live in ProcessingPhases (pipeline) and GenerationPhases (codegen children); ActivePerformanceTracker receives the hierarchy — PerformanceTracker is a pure protocol.
    • BuilderException becomes CodeGenerationException during extraction; missing DTOs/enums are recreated on the builder side — no backwards dependency from the generic library onto builder types.
    • Two artifacts (not one jar with classifiers): the generic layer must stay Roaster-free.
    • Generated example builders stay byte-identical at every step.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions