RFR: 8294377: Prepare to stop auto-inheriting documentation for subclasses of exceptions whose documentation is inherited [v2]
Pavel Rappo
prappo at openjdk.org
Thu Oct 6 14:35:20 UTC 2022
On Fri, 30 Sep 2022 19:15:17 GMT, Phil Race <prr at openjdk.org> wrote:
> If the docs end up the same as you say that is fine by me since for the two ImageIO classes that seems to be what we'd want.
Since this change does not affect HTML pages for java.desktop, I take it as "approved".
> But inheritDoc behaviour is still "surprising". I've never been sure I understood it and now I'm just sure I don't.
>
> 1. The two ImageIO methods don't have @OverRide or _anything_ and yet javadoc infers
> they'd want to inherit the docs from the interface .. clever javadoc .. I guess I can see
> that some doc is better than none so this is OK
> 2. When it does inherit I'd expected that it copies the EXACT and ENTIRE javadoc
> from the super-interface, which for your change to work can't be all its doing.
> You've added JUST
> /**
>
> * @throws SomeExceptionSubType blah-blah
> */
>
> and yet javadoc somehow figures out this is to be ADDED to the super-type doc for the method and not replace it .. ???
>
> 3. What the old code was doing seems to me to be "natural" to the extent any of
> this does and the fix you are preparing would add to the surprising behaviours ..
Let me try to clarify exception documentation inheritance for you.
A method **never** inherits exception documentation unless that method explicitly requests to do so. A method that wants to inherit documentation for a particular exception has two options: use a doc comment or use a method declaration.
Let's see how those options work. Suppose, a method wants to inherit documentation for an exception `X`. To inherit documentation through a doc comment, the method adds the following exception tag (`@throws` or `@exception`) to that method's doc comment:
@throws X {@inheritDoc}
To inherit documentation through a method declaration, the method lists `X` in that method's `throws` clause:
throws ..., X, ...
If a method chooses neither of those options, then that method won't inherit exception documentation for `X` (assuming that exception documentation for `X` exists in the supermethod).
Here's an informal, simplified, but conceptually correct version of the algorithm that javadoc uses to document exceptions thrown by a method:
Step 1. For each exception tag, do the following. If an exception tag does not have `{@inheritDoc}` in its description, add an entry for the exception that this tag describes to the "Throws:" section. Otherwise, look for corresponding documentation in the supermethod, to which apply this step (Step 1) recursively.
Step 2. For each exception from the `throws` clause, do the following. If an exception has not been documented on the previous step, document it using corresponding documentation in the supermethod, to which apply this algorithm (both steps in order) recursively.
A few notes on the algorithm:
* Exception tags are examined prior to the `throws` clause. This allows a method to **override** documentation that could be otherwise inherited from the supermethod: if the method provides exception tags for a particular exception, then documentation for that exception will be found on Step 1 and, hence, won't be looked for in the supermethod on Step 2.
@throws X <overriding-description>
* If a method wants to **add** documentation for a particular exception, rather than **override** it, the method should both add documentation and inherit it using tags:
@throws X <additional-description>
@throws X {@inheritDoc}
The above model might explain a common **misconception** according to which methods inherit documentation for checked exceptions and do not inherit it for unchecked exceptions. In reality, javadoc treats all exceptions equally. It's just that if a method throws a checked exception, that exception (or its superclass) must be listed in that method's `throws` clause. Now, if such an exception is not documented by that method but documented by the supermethod, that exception documentation is inherited. That gives a false impression that the documentation is inherited because the exception is checked. In fact, the documentation would still be inherited if that exception, listed in the `throws` clause, were unchecked.
The above is how it has been working (barring bugs) since documentation comment inheritance appeared in its current form. Implicit inheritance (filling in missing text) appeared in JDK 1.3, explicit inheritance (`{@inheritDoc}`) appeared in JDK 1.4, auto-inheriting documentation for subclasses of exceptions whose documentation is inherited (JDK-4947455) appeared in JDK 5.
Back to this PR change in `java.desktop`. `ImageInputStreamImpl.readBoolean` inherits `EOFException` documentation not because that method doesn't have a doc comment of its own and, thus, inherits "the exact and entire" doc comment from its supermethod (`ImageInputStream.readBoolean`). It's because that when the algorithm reaches Step 2 and tries to find documentation for `IOException` (because it is listed in the `throws` clause), JDK-4947455 kicks in. And JDK-4947455 says that if a method inherits documentation for a particular exception, it should also inherit documentation for that exception's subclasses. So, javadoc goes ahead and inherits documentation for `IOException`, because it's a direct match, and for `EOFException`, because it's a subclass of `IOException`.
To inherit `EOFException` documentation after JDK-4947455 has been reverted and, thus, the subclassing :magic_wand: has gone, `ImageInputStreamImpl.readBoolean` has two options:
* list `EOFException` in the `throws` clause
* `@throws EOFException {@inheritDoc}`
Thanks to the current implementation of documentation inheritance, any of the above can be done **before** JDK-4947455 is reverted. For now doing so just adds a redundant but harmless inheritance route, which will become the only route in time. For this PR to be less disruptive and qualify as "noreg-doc" I chose to add an exception tag rather than amend the `throws` clause.
I hope that my reply clarifies the matter. Documentation inheritance can be surprising. We're trying hard to capture its model and simplify it where possible. We are constantly improving the Documentation Comment Specification for the Standard Doclet[^1] (spec), but since documentation inheritance is a popular topic which is often misunderstood, along with improving the spec in this area, we might also provide a less formal document dedicated to documentation inheritance.
[^1]: https://docs.oracle.com/en/java/javase/19/docs/specs/javadoc/doc-comment-spec.html
-------------
PR: https://git.openjdk.org/jdk/pull/10449
More information about the core-libs-dev
mailing list