Search code examples
javaannotationsjavadoclombok

Add javadoc in annotations


I'd like to add javadoc for an annotation, specifically for lombok.

If I do this:

/**
 * Custom constructor used only in <code>OrderMapper</code></p>.
 * @param totalValue single parameter necessary to pass on the information to frontend
 * @see   <a href= "https://github.com/projectlombok/lombok/issues/1269">Implicit @RequiredArgsConstructor on @Data will be removed when using @NoArgsConstructor #1269</a>
 */
@RequiredArgsConstructor 

It doesn't returns any errors but the javadoc is not generated.

It is even possible to do what I'm trying to? If yes, What I'm doing wrong?

I thought it was because of the generic constructor, but @NoArgsConstructor is unique and also doesn't work.


Solution

  • lombok core maintainer here:

    It is not possible to directly javadoc the constructor that lombok generates. In theory lombok could set things up such that the javadoc that appears 'just above' an annotation applies to the thing that annotation generates, but this is problematic for various reasons so I highly doubt we would ever add this:

    • Various lombok nodes generate multiple things, such as @Getter on a class which generates multiple getters.
    • Javac wants to bind those docs to something quite early in the process. We can work around it but it's technically asking for lots of bugreports.
    • It isn't compatible with many style guides and established ways of writing java code. Specifically, the vast majority of java programmers write their stuff as:
    /** javadoc */
    @Override public void foo() {}
    

    and not as:

    @Override
    /** javadoc */
    public void foo() {}
    

    even though both are equally legal both as far as 'compile this code' is concerned and as far as 'make javadoc based on this code' is concerned.

    That's a problem then: If everybody writes like this and lombok changes things so that:

    /** javadoc */
    @RequiredArgsConstructor
    public class Foo {}
    

    means that the javadoc is now on the constructor and not on the class, that's a breaking change, and one that tests won't catch (we wouldn't want to do that to our users!) - and even if somehow we accepted all that damage, that means users who are aware of this change and update their code accordingly need to write:

    @RequiredArgsConstructor
    /** javadoc */
    public class Foo {}
    

    and this is non-standard (in the sense that it doesn't match what 90%+ of all java programmers are used to, and lombok is not interested in attempting to change the established culture of the entire java ecosystem in that drastic a fashion unless it really, really pays off, and this is a few ballparks short of being useful enough to try it).

    At best, we could say that this:

    /** javadoc A */
    @RequiredArgsConstructor
    /** javadoc B */
    class Foo {}
    

    is interpreted the way you want it to, but this 'feature' would be very hard to discover, and we don't like adding features that are doomed to be used by virtually nobody. It's not worth the maintenance hassle and learning curve. If nobody knows this is how it works and they see your file where you do the above thing, do they even know what it means? Would they surmise this means if you delete javadoc B, that the javadoc now no longer applies to the constructor but only to the class, B has to be there so lombok knows that 'A' is for the constructor? I doubt it, hence, we'd veto this feature request if it works like this. Too likely to confuse.

    I guess if there is a need to specifically javadoc some boilerplate, then it is no longer boilerplate so you'll need to write it out long form.

    But, really, just no shot at all?

    We do have a 'feature' that could be adopted for this: You can javadoc an individual field like so:

    /**
     * A
     * -- SETTER --
     * B
     *
     * @param C
     */
    @Getter @Setter private String field;
    

    and this results in lombok breaking that javadoc apart into bits, and is equivalent to:

    /**
     * A
     */
    private String field;
    
    /**
     * A
     */
    public String getField() { return field; }
    
    /**
     * B
     * @param C
     */
    public void setField(String field) { this.field = field; }
    

    The same logic could be applied to class-level javadoc, that you could do something like:

    /**
     * Water is wet
     * -- CONSTRUCTOR --
     * Circles are round
     */
    @RequiredArgsConstructor
    public class Foo {}
    

    and that lombok would break that javadoc apart into just 'water is wet' to go on the class, and just 'Circles are round' to go on the constructor. However, this is quite the change - presumably then you'd want the constructor javadoc that lombok makes for you to include each field as a @param, perhaps copying over the javadoc on that field (but what if there's a ton of javadoc there? @param is not really intended to contain a lot, so do we just take the first sentence?

    You see how that turns into a big feature that requires a lot of choices to be made. Point is, a feature request for this would not be immediately denied, but especially without an attached pull request with the feature implemented and the docs updated I doubt we'd get around to fulfilling that request anytime soon.