Motivation
@SimpleBuilderFor requires every external type to be listed explicitly in value. For libraries exposing many DTOs this means a long, manually maintained list that drifts out of date whenever the library adds a type. It should be possible to point the annotation at a package (or several packages) and generate builders for every top-level class found there.
@SimpleBuilderFor(
packages = {"com.thirdparty.users", "com.thirdparty.orders"},
options = @SimpleBuilder.Options(packageName = "com.example.generated"))
public class ExternalBuildersProvider { }
API design: additional property vs. new annotation
Option A — additional property on @SimpleBuilderFor (e.g. String[] packages() default {}):
- Scanning plays the same role as
value - it selects which external types get builders, just in bulk. Keeping both on one annotation avoids a parallel API for the same purpose.
- Each repeat of the (now
@Repeatable) annotation composes its packages with its own options, so different packages can still be routed to different output packages.
- Cost:
value loses its "required" status and becomes default {}, plus validation that at least one of value/packages is non-empty.
Option B — a separate annotation (e.g. @SimpleBuilderForPackage("com.thirdparty.users")):
- Keeps
value mandatory on @SimpleBuilderFor and gives scanning its own obvious name.
- Cost: a second annotation to document and maintain for the same job, and it would need its own repeatability story and
options member duplicated (or a nested options object shared between the two).
Recommendation: Option A. Package scanning is a bulk form of the existing value list, not a different feature; the option-level composition already introduced by repeatability makes packages a natural fit on the same annotation. A sensible name avoiding confusion with packageName (the output package) would be packages or scanPackages.
Implementation notes / open questions
- Discovery via
Elements.getPackageElement(name).getEnclosedElements() gives only top-level types - nested classes keep requiring an explicit value entry.
- Filter policy for non-constructible members of a package (interfaces, abstract classes, enums, annotation types): skip silently, or report per type? A skip-with-debug default plus strict-mode escalation seems reasonable.
- On the module path, scanning is limited to packages readable/exported to the compiling module.
- Deterministic output ordering should sort discovered types (e.g. by qualified name).
Raised while discussing #306 (multiple packages for generated builders).
Written by Devin
Motivation
@SimpleBuilderForrequires every external type to be listed explicitly invalue. For libraries exposing many DTOs this means a long, manually maintained list that drifts out of date whenever the library adds a type. It should be possible to point the annotation at a package (or several packages) and generate builders for every top-level class found there.API design: additional property vs. new annotation
Option A — additional property on
@SimpleBuilderFor(e.g.String[] packages() default {}):value- it selects which external types get builders, just in bulk. Keeping both on one annotation avoids a parallel API for the same purpose.@Repeatable) annotation composes itspackageswith its ownoptions, so different packages can still be routed to different output packages.valueloses its "required" status and becomesdefault {}, plus validation that at least one ofvalue/packagesis non-empty.Option B — a separate annotation (e.g.
@SimpleBuilderForPackage("com.thirdparty.users")):valuemandatory on@SimpleBuilderForand gives scanning its own obvious name.optionsmember duplicated (or a nested options object shared between the two).Recommendation: Option A. Package scanning is a bulk form of the existing
valuelist, not a different feature; the option-level composition already introduced by repeatability makespackagesa natural fit on the same annotation. A sensible name avoiding confusion withpackageName(the output package) would bepackagesorscanPackages.Implementation notes / open questions
Elements.getPackageElement(name).getEnclosedElements()gives only top-level types - nested classes keep requiring an explicitvalueentry.Raised while discussing #306 (multiple packages for generated builders).
Written by Devin