You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Extract framework-agnostic builder/DTO model into its own project #233
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.
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
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.
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.
Activity
[-]Extract framework-agnostic builder/DTO model into its own project (resolves Sonar duplication gate)[/-][+]Extract framework-agnostic builder/DTO model into its own project[/+]igel-devin-ai commentedon Oct 12, 2026
Extraction plan (agreed)
Target architecture: two Maven artifacts —
simple-codegen(framework-agnostic annotation-processing / code-generation layer, package rootorg.javahelpers.simple.codegen) andsimple-codegen-roaster(Roaster backend implementing theClassCodeGeneratorSPI). 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 mvmoves happen after the classes no longer import builder internals, so Git's rename detection andgit log --followkeep the full file history. Moves use one rename-safe commit per group where practical; old paths remain in history.Subtasks
ProcessingContextinto genericAnnotationProcessingContext+ builder contextsimple-codegen+simple-codegen-roastermodulesKey decisions
ProcessingLoggertakes no decision boolean:new ProcessingLogger(env)vs.ProcessingLogger.verbose(env)factory over a privateVerbosityenum.GenerationIssueReporter(functional interface) inGenerationEnvironment— the Roaster backend never seesProcessingContext.MapperOptions(copyTypeAnnotationsflag +generatedTypeResolverfunction typed onResolvedBuilder); builder wiring lives inBuilderDefinitionCreator.findConstructorForBuilderis parameterized by the constructor marker annotation; the builder caller passesSimpleBuilderConstructor.ProcessingPhases(pipeline) andGenerationPhases(codegen children);ActivePerformanceTrackerreceives the hierarchy —PerformanceTrackeris a pure protocol.BuilderExceptionbecomesCodeGenerationExceptionduring extraction; missing DTOs/enums are recreated on the builder side — no backwards dependency from the generic library onto builder types.