Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8285488: Improve DocFinder #10746

Closed
wants to merge 70 commits into from
Closed

Conversation

pavelrappo
Copy link
Member

@pavelrappo pavelrappo commented Oct 18, 2022

Please have a look at this work-in-progress PR. The reason this is a (normal) PR rather than a more suitable draft PR is to mainly trigger a discussion on the mailing list on whether the suggested approach to solve multiple intertwined issues of exception documentation inheritance is a correct one.

In a nutshell, it turns out that the combination of {@throws} and {@inheritDoc} is quite complex. It's more complex than a combination of {@inheritDoc} with any other tag or {@inheritDoc} on its own. To account for that complexity, handling of {@inheritDoc} in {@throws} is lifted to ThrowsTaglet.

The said complexity stems from two facts:

  1. Processing of {@inheritDoc} is context free and is done by replacing {@inheritDoc} with the tags it expands to. That model does not account for @throws where {@inheritDoc} sometimes expands to multiple @throws tags, which correspond to separate entries in the "Throws:" section of a method detail. Read: we change the exception section, not a description of one of its entries.

  2. Corresponding exception types in the hierarchy (i.e. matching {@inheritDoc} with exception documentation it must inherit) is not always clear-cut. This becomes especially apparent when type variables are involved.

History

The work started as an attempt to fix JDK-8285488, hence the issue number for the PR. However, along its course the PR solved other issues, which will be soon added to the PR:

  • 8287796: Stop auto-inheriting documentation for subclasses of exceptions whose documentation is inherited
  • 8291869: Match exceptions using types of javax.lang.model, not strings
  • 8295277: Expand {@inheritDoc} in @throws fully
  • 8288045: Clean up ParamTaglet
  • 8288046: Clean up ThrowsTaglet

As of today

  • All tests (both existing and newly introduced) pass.
  • JDK API Documentation is the same, except for two files. In the first file, docs/api/java.management.rmi/javax/management/remote/rmi/RMIConnectionImpl_Stub.html, the order of exceptions has changed, which is insignificant. As for the second file, docs/api/java.management/javax/management/MBeanServer.html, the new warning is generated and erroneous input added to the corresponding page. The issue has to be addressed on the component side and is tracked by JDK-8295151.

Progress

  • Change must be properly reviewed (1 review required, with at least 1 Reviewer)
  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue

Issues

Reviewers

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/jdk pull/10746/head:pull/10746
$ git checkout pull/10746

Update a local copy of the PR:
$ git checkout pull/10746
$ git pull https://git.openjdk.org/jdk pull/10746/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 10746

View PR using the GUI difftool:
$ git pr show -t 10746

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/10746.diff

javax.lang.model.element.Element.provides rationale for that:

  Elements should be compared using the equals(Object) method. There is
  no guarantee that any particular element will always be represented
  by the same object.
**WARNING**: This commit changes the JDK API Documentation.
All changes are of the same kind. One such change can be seen in
java.io.ObjectInputStream.readUTF. That method now documents
previously undocumented EOFException.

The reason why EOFException was not documented previously is
that the old code incorrectly started documentation search
for IOException and its subclasses (for subclasses see 4947455)
from ObjectInputStream.readUTF itself, rather than from the
methods it overrides. Because ObjectInputStream.readUTF documents
IOException, the search succeeded immediately, never finding
EOFException which is documented in java.io.DataInput.readUTF.

This commit changes the code so that the search skips
ObjectInputStream.readUTF when looking for exception
documentation for exceptions listed in the `throws`
clause and their subexceptions.
**WARNING**: This commit changes the JDK API Documentation.

All changes are of the same kind: some methods document more exceptions
without any of the related doc comments having been changed.

For example, along with DateTimeException, ChronoLocalDate.plus(long,
TemporalUnit) now documents UnsupportedTemporalTypeException.

The reason why UnsupportedTemporalTypeException was not documented
previously (although it should've been because of JDK-4947455) is that
ThrowsTaglet.inherit was incorrectly obtaining
javax.lang.model.element.Element corresponding to the exception in
the `@throws` tag. ThrowsTaglet.inherit was looking for a ThrowsTree
node in a wrong DocCommentTree node; what was done like this:

    var ch = utils.getCommentHelper(input.element);
    target = ch.getException(tag);

should've been done like this:

    target = utils.getCommentHelper(input.docTreeInfo.element()).getException(tag);

The new code obtains the target correctly.

The new behavior sometimes results in doubling of exception
documentation. This happens when a subexception is inherited both
explicitly and implicitly when a superexception is inherited.
For example, java.nio.channels.SocketChannel#bind now documents
ClosedChannelException twice.

The first time because:

    @throws  ClosedChannelException              {@inheritdoc}

And the second time because:

    @throws  IOException                         {@inheritdoc}

Such doubling is an intermediate artifact of this commit and will
disappear in subsequent commits.
**CAVEATS**: This is an intermediate commit, whose primary purpose is
to finally stop using old DocFinder.search and friends so that they
could be deleted. As such, the commit cuts a few corners.

In particular, SeeTaglet throws an exception on an attempt to use:

    @see {@inheritdoc}

That and other issue will be cleaned up and refactored in subsequent
commits.

**NOTES:**

* It would be nice to have this method instead of a newly introduced
  `inherit` so that all the specifics of inheritance processing would
  be hidden in individual taglets:

      void inherit(ExecutableElement owner,
                   DocTree tag,
                   TagletWriter writer)

  But I don't see how we could do this, because the `inherit` is called
  while parsing an individual tag, rather than a group of similar tags.
  So we cannot use such a method to implement, say, a one-to-many type
  of inheritance. (See the existing ThrowsTaglet.flatten workaround).

* SimpleTaglet first sentence handling seems misguided. It needs to be
  sorted out.
- Method signatures no longer require BaseConfiguration
- DocFinder no longer depends on Utils or BaseConfiguration
- Methods are still grouped under a separate type, DocFinder, rather
  than flattened into Utils
Stream.peek is designed for debugging and can be optimized away.
Flipping the flag in flatMap seems wrong too; so use iterator.
There's no reason to have a stream-based implementation when a simpler
iterator-based implementation will do. Also, this commit fixes a bug
where if called with

    includeMethod && throwExceptionIfNoOverriddenMethods

on a method that didn't override anything, the search would not throw
an exception.
Comparing exceptions by their string names is incorrect.
This commit makes ThrowsTaglet "javax.lang.model typed"
rather than "stringly typed".

Changing the comparison mechanism broke 2 tests, which were
subsequently fixed by removing problematic @throws/@exception tag.
In neither test exceptions were pertinent:

* testHtmlDefinitionListTag used `@exception HeadlessException` to test
  HTML structure of `<dl>` tags generated by javadoc (see 6786690).
  For whatever reason, the exception was unknown. It's possible that
  it was supposed to be java.awt.HeadlessException, but it was neither
  imported nor FQNed in the tag. Since a particular type of exception
  does not matter in that test, this PR FQNed that exception.

* TestStdDoclet used `@throws DoesNotExist` as one of the warnings to
  contribute to the total warning count. Interestingly enough, the
  unknown exception in `@throws` was never warned about, unlike
  unknown references in 2 `@see` tags. This PR substitutes that
  exception with a separate test. Note that if "-Xdoclint:none"
  is removed, then that @throws tag triggers a doclint error:

      error: reference not found

To test and support the comparison mechanism change, many new tests
were introduced. They clearly show why being "stringly typed" is wrong
for ThrowsTaglet.
Doclint does this already:

  error: reference not found
       * @throws X {@inheritdoc}
         ^

Not sure how to coordinate doclint with the other diagnostic system
so that they work in a mutually exclusive fashion and not double
report.
@pavelrappo
Copy link
Member Author

JDK API Documentation is the same, except for two files. In the first file, docs/api/java.management.rmi/javax/management/remote/rmi/RMIConnectionImpl_Stub.html, the order of exceptions has changed, which is insignificant.

Is there now a defined order in which exceptions will be documented, and what was it before?

Generally speaking, the order was and still is the encounter order. It's the resolution of 8287796 that changed a few places so that you can see the difference between BFS and DFS.

There was a commit with a message that describes that. Let me see if I can quickly find it. Yes, here it is: 2475c1f

commit 2475c1f2834dd5ad671c0f05a3e9c906a9a3d29b
Author: Pavel Rappo <prappo at openjdk.org>
Date:   Wed Oct 12 11:57:55 2022 +0100

    fix: remove auto-inheriting of subexceptions

    This effectively implements 8287796: Stop auto-inheriting documentation
    for subclasses of exceptions whose documentation is inherited.

    All tests pass. The only difference in the JDK API Documentation is
    the order of exceptions in some methods of RMIConnectionImpl_Stub:
    MBeanException and MBeanRegistrationException are ordered
    reversely. That difference is insignificant.

@pavelrappo
Copy link
Member Author

/issue remove JDK-8295800

@openjdk
Copy link

openjdk bot commented Nov 14, 2022

@pavelrappo
Removing additional issue from issue list: 8295800.

@pavelrappo
Copy link
Member Author

I removed 8295800 ("When searching documentation for an exception, don't jump over methods that don't mention that exception") from this PR because fixing it here would be too disruptive. It should better be fixed in the context of 8285368 ("Overhaul doc-comment inheritance"), which proposes changes to the documentation search algorithm.

It was never a goal of this PR to fix InheritableTaglet.
It will be re-introduced in 8285368.
@jonathan-gibbons
Copy link
Contributor

I removed 8295800 ("When searching documentation for an exception, don't jump over methods that don't mention that exception") from this PR because fixing it here would be too disruptive. It should better be fixed in the context of 8285368 ("Overhaul doc-comment inheritance"), which proposes changes to the documentation search algorithm.

It will be interesting to see the list of affected places, when we have away to address this issue.

@openjdk
Copy link

openjdk bot commented Nov 15, 2022

@pavelrappo This change now passes all automated pre-integration checks.

ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details.

After integration, the commit message for the final commit will be:

8285488: Improve DocFinder
8287796: Stop auto-inheriting documentation for subclasses of exceptions whose documentation is inherited
8291869: Match exceptions using types of javax.lang.model, not strings
8288045: Clean up ParamTaglet
8288046: Clean up ThrowsTaglet
8295277: Expand {@inheritDoc} in @throws fully

Reviewed-by: jjg

You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been 13 new commits pushed to the master branch:

  • 0cbf084: 8296969: C1: PrintC1Statistics is broken after JDK-8292878
  • f662a06: 8296970: Remove sysThreadAvailableStackWithSlack from hotspot-symbols
  • 7357a1a: 8296889: Race condition when cancelling a request
  • 87530e6: 8296913: Correct enable preview idiom in JdbLastErrorTest.java
  • fafe682: 8295861: get rid of list argument in debug agent's removeNode() API
  • 216c6f6: 8294881: test/hotspot/jtreg/vmTestbase/nsk/jdi/VirtualMachine/dispose/dispose003/TestDescription.java fails
  • 6aef3a4: 8262435: Clarify the behavior of a few inherited ZipInputStream methods
  • c042b8e: 8294731: Improve multiplicative inverse for secp256r1 implementation
  • d3051a7: 8296736: Some PKCS9Attribute can be created but cannot be encoded
  • decb1b7: 8286800: Assert in PhaseIdealLoop::dump_real_LCA is too strong
  • ... and 3 more: https://git.openjdk.org/jdk/compare/6f467cd8292d41afa57c183879a704c987515243...master

As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.

➡️ To integrate this PR with the above commit message to the master branch, type /integrate in a new comment.

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Nov 15, 2022
Also removes three TODOs. The first TODO was about "binary name".
The notion of "binary name" seems to be inapplicable to packages
and modules (see JLS 13.1. The Form of a Binary) and as such is
a less than ideal here.
@pavelrappo
Copy link
Member Author

/integrate

@openjdk
Copy link

openjdk bot commented Nov 16, 2022

Going to push as commit 499406c.
Since your change was applied there have been 20 commits pushed to the master branch:

Your commit was automatically rebased without conflicts.

@openjdk openjdk bot added the integrated Pull request has been integrated label Nov 16, 2022
@openjdk openjdk bot closed this Nov 16, 2022
@openjdk openjdk bot removed ready Pull request is ready to be integrated rfr Pull request is ready for review labels Nov 16, 2022
@openjdk
Copy link

openjdk bot commented Nov 16, 2022

@pavelrappo Pushed as commit 499406c.

💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
integrated Pull request has been integrated javadoc javadoc-dev@openjdk.org
4 participants