Summary
Follow-up to #244.
Now that @SimpleBuilder and @SimpleBuilder.Template are @Inherited, subclasses of an annotated parent DO get a builder generated (the element is picked up via RoundEnvironment.getElementsAnnotatedWith(...)). However, the configuration options declared on the parent's @SimpleBuilder(options = ...) or on the parent's custom template annotation are NOT inherited — the subclass builder is generated with default options instead.
Reproduction
Parent with @SimpleBuilder(options = @SimpleBuilder.Options(generateFieldSupplier = OptionState.DISABLED)):
- Parent builder:
generateFieldSupplier is correctly DISABLED (no Supplier method generated) ✅
- Child builder (unannotated subclass):
generateFieldSupplier falls back to DEFAULT (ENABLED) — a Supplier method IS generated ❌
The same happens with a custom @Inherited template annotation whose @SimpleBuilder.Template(options = ...) sets generateFieldSupplier = OptionState.DISABLED: the parent builder respects it, the child builder does not.
Root cause
BuilderConfigurationReader reads annotations via element.getAnnotationMirrors(), which returns only directly-declared annotations, not inherited ones. The affected methods are:
readFromInlineOptions(Element) → extractAnnotationMirror(Element, String) (line ~106)
readFromTemplate(Element) (line ~248)
hasSimpleBuilderAnnotation(Element) (line ~266)
All three iterate element.getAnnotationMirrors() and therefore miss @Inherited annotations that come from a superclass.
Suggested fix
Use elementUtils.getAllAnnotationMirrors(element) (from javax.lang.model.util.Elements, already available as a field in BuilderConfigurationReader) instead of element.getAnnotationMirrors() in the three methods above. Elements.getAllAnnotationMirrors returns all annotations including @Inherited ones, so the subclass would pick up the parent's @SimpleBuilder / template annotation with its options attribute.
Impact
Any subclass that relies on inheriting @SimpleBuilder (or an @Inherited template annotation) from a parent will get a builder with default options, ignoring the parent's configured @SimpleBuilder.Options. This is likely to surprise users who expect the parent's configuration to propagate.
Summary
Follow-up to #244.
Now that
@SimpleBuilderand@SimpleBuilder.Templateare@Inherited, subclasses of an annotated parent DO get a builder generated (the element is picked up viaRoundEnvironment.getElementsAnnotatedWith(...)). However, the configuration options declared on the parent's@SimpleBuilder(options = ...)or on the parent's custom template annotation are NOT inherited — the subclass builder is generated with default options instead.Reproduction
Parent with
@SimpleBuilder(options = @SimpleBuilder.Options(generateFieldSupplier = OptionState.DISABLED)):generateFieldSupplieris correctly DISABLED (noSuppliermethod generated) ✅generateFieldSupplierfalls back to DEFAULT (ENABLED) — aSuppliermethod IS generated ❌The same happens with a custom
@Inheritedtemplate annotation whose@SimpleBuilder.Template(options = ...)setsgenerateFieldSupplier = OptionState.DISABLED: the parent builder respects it, the child builder does not.Root cause
BuilderConfigurationReaderreads annotations viaelement.getAnnotationMirrors(), which returns only directly-declared annotations, not inherited ones. The affected methods are:readFromInlineOptions(Element)→extractAnnotationMirror(Element, String)(line ~106)readFromTemplate(Element)(line ~248)hasSimpleBuilderAnnotation(Element)(line ~266)All three iterate
element.getAnnotationMirrors()and therefore miss@Inheritedannotations that come from a superclass.Suggested fix
Use
elementUtils.getAllAnnotationMirrors(element)(fromjavax.lang.model.util.Elements, already available as a field inBuilderConfigurationReader) instead ofelement.getAnnotationMirrors()in the three methods above.Elements.getAllAnnotationMirrorsreturns all annotations including@Inheritedones, so the subclass would pick up the parent's@SimpleBuilder/ template annotation with itsoptionsattribute.Impact
Any subclass that relies on inheriting
@SimpleBuilder(or an@Inheritedtemplate annotation) from a parent will get a builder with default options, ignoring the parent's configured@SimpleBuilder.Options. This is likely to surprise users who expect the parent's configuration to propagate.