Skip to content

Inherited @SimpleBuilder / @SimpleBuilder.Template options are not applied to subclasses — only defaults #248

Description

@AndreasIgel

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions