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

JDK-8257925 enable more support for nested inline tags #2369

Closed
wants to merge 8 commits into from

Conversation

jonathan-gibbons
Copy link
Contributor

@jonathan-gibbons jonathan-gibbons commented Feb 3, 2021

Please review an update to improve the support, where appropriate, for nested inline tags.

It has always been the case that certain inline tags allow text and HTML to appear within them. With tags like {@return} and {@summary} it becomes desirable to also generally allow nested inline tags to appear in those places as well. The work for this was started with the support for {@return} JDK-8075778, but applying the work more generally was out of scope at the time. This change completes the work that was started then.

The work can be grouped into 4 parts, in 3 commits.

Commit 1

  • Update DocCommentParser to syntactically allow nested inline tags in situations that permit text and HTML
  • Update the downstream code to semantically limit nestg where it does not make sense, and provide new tests to verify the behavior.

A family of new tests are added, each testing the ability to put an inline tag within another of the same kind, with and without doclint being enabled. In addition, test cases are added placing a simple instance {@value} in an enclosing tag: this is a useful case just because the expansion is plain text and therefore valid in all situations. Additional tests and test cases can be added as needed.

This commit left the {@index} tag generating "bad" code when it was nested. The error was "reference to an undeclared ID". The (temporary) solution was to disable the automatic link checking for this specific subtest.

Commit 2

  • HtmlDocletWriter and TagletWriterImpl pass around a pair of booleans isFirstSentence and inSummary to help determine the output to be generated. Conceptually, a third value is added to that group: a set containing the set of nested tag kinds, so that it is possible to determine the enclosing tags for a tag. But, rather than add a third parameter to be passed around, the 3 are grouped into a new class TagletWriterImpl.Context which encapsulates the two booleans and the new set. The new class is added in a way to minimize code churn. No tests are affected by this change: all continue to pass.

Commit 3

  • The new Context#inTags field is used to help improve the behavior of nested {@index} tags even when used incorrectly, with warnings disabled. As a result, the temporary change in the first commit to disable automatic link checking in one of the test cases is reverted.

The introduction of the new Context class is arguably more general than we need at this time, but it clears up some erratic and inconsistent use of the isFirstSentence and inSummary booleans. The new class also provides a better framework for any complex new inline tags we may add in future. We might want to change the Set<DocTree.Kind> to some other collection at some point, if needs be (a stack, for example.) We might also want to move more information into the Context, such as the related Element that is otherwise ubiquitously passed around.

The overall cleanup also revealed some latent bugs in the code, that were hidden in some of the tests. Most notable was that there were still some cases were < and > were not being correctly escaped as &lt; and &gt; leading to output in some tests of the form List<String> ! This triggered a minor cleanup/rewrite of the beginning of HtmlDocletWriter.seeTagsToContent which was previously a bit too liberal with the use of new RawHtml! The other minor cleanup was more consistent handling of whitespace at the end of the first sentence, as will be seen in a couple of places in one of the tests that was updated.


Progress

  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue
  • Change must be properly reviewed

Issue

  • JDK-8257925: Enable more support for nested inline tags

Reviewers

Download

$ git fetch https://git.openjdk.java.net/jdk pull/2369/head:pull/2369
$ git checkout pull/2369

@bridgekeeper
Copy link

bridgekeeper bot commented Feb 3, 2021

👋 Welcome back jjg! A progress list of the required criteria for merging this PR into master will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link

openjdk bot commented Feb 3, 2021

@jonathan-gibbons The following labels will be automatically applied to this pull request:

  • compiler
  • javadoc

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing lists. If you would like to change these labels, use the /label pull request command.

@openjdk openjdk bot added javadoc javadoc-dev@openjdk.org compiler compiler-dev@openjdk.org labels Feb 3, 2021
@openjdk openjdk bot added the rfr Pull request is ready for review label Feb 3, 2021
@mlbridge
Copy link

mlbridge bot commented Feb 3, 2021

Webrevs

@pavelrappo
Copy link
Member

Although this patch generally looks reasonable, I'm surprised to see some of the behavior it introduces. For example, consider composition of @link tags from the included tests:

/** First sentence. {@link #m1() ABC {@link #m2() DEF} GHI} */

Before the patch that doc comment resulted in the following HTML:

First sentence. <a href="#m1()"><code>ABC {@link #m2() DEF} GHI</code></a>

After the patch that same doc comment results in HTML that looks like this:

First sentence. <a href="#m1()"><code>ABC <a href="#m2()"><code>DEF</code></a> GHI</code></a>

I wouldn't expect that latter behavior. Not only nested <a> are invalid HTML, but they are also rendered strangely in browsers. In this particular case the trailing GHI appears as normal text, not as a hyperlink.

@jonathan-gibbons
Copy link
Contributor Author

I wouldn't expect that latter behavior. Not only nested <a> are invalid HTML, but they are also rendered strangely in browsers. In this particular case the trailing GHI appears as normal text, not as a hyperlink.

Thanks; it was on my list to check whether nested links were allowed. I'm pleased they're not, and this will be another situation where the inTags info is useful.

Copy link
Member

@pavelrappo pavelrappo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for fixing the nested <a> issue. With your last commit (96bfeb5) the output from

/** First sentence. {@link #m1() ABC {@link #m2() DEF} GHI} */

looks like this

First sentence. <a href="#m1()"><code>ABC DEF GHI</code></a>

and if doclint is enabled, javadoc issues a warning

warning: nested tag: @link
/** First sentence. {@link #m1() ABC {@link #m2() DEF} GHI} */
                                     ^

I would recommend comparing JDK API documentation before and after, if only to bring any uncovered surprises to maintainers' attention early.

@openjdk
Copy link

openjdk bot commented Feb 12, 2021

@jonathan-gibbons this pull request can not be integrated into master due to one or more merge conflicts. To resolve these merge conflicts and update this pull request you can run the following commands in the local repository for your personal fork:

git checkout inline-tags
git fetch https://git.openjdk.java.net/jdk master
git merge FETCH_HEAD
# resolve conflicts and follow the instructions given by git merge
git commit -m "Merge master"
git push

@openjdk openjdk bot added the merge-conflict Pull request has merge conflict with target branch label Feb 12, 2021
Copy link
Member

@hns hns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a very nice improvement! I have added a few comments and suggestions, but nothing of major importance.

}
default -> {
assert false;
return HtmlTree.EMPTY;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason to assert false here and in other places instead of, say, always throw a RuntimeException?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the general discussion about the use of assert, and whether it is better to throw an exception in production code, or "carry on regardless". I wish Java had a should-not-happen statement or at least a ShoudNotHappen exception.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, IllegalStateException is a reasonable alternative

Content label = commentTagsToContent(node, element, node.getLabel(), context);
if (label.isEmpty()) {
label = new StringContent(node.getReference().getSignature());
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's quite a bit of work for something probably very few people should try...

@@ -1576,7 +1634,7 @@ public Boolean visitLiteral(LiteralTree node, Content c) {
@Override
public Boolean visitSee(SeeTree node, Content c) {
// we need to pass the DocTreeImpl here, so ignore node
result.add(seeTagToContent(element, tag));
result.add(seeTagToContent(element, tag, context));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is above comment still correct? Aren't tag and node the same object?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, updated

@@ -109,7 +164,24 @@ public TagletWriterImpl(HtmlDocletWriter htmlWriter, boolean isFirstSentence) {
public TagletWriterImpl(HtmlDocletWriter htmlWriter, boolean isFirstSentence, boolean inSummary) {
super(isFirstSentence);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To avoid almost identical constructors this one could be implemented as

this(htmlWriter, new Context(isFirstSentence, inSummary));

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch

"{@link",
"ABC <a href=\"#m2()\"");
checkOutput("p/C.html", true,
"ABC DEF GHI");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you are running this with and without doclint, should this or any test in this file check for doclint warnings?

@openjdk
Copy link

openjdk bot commented Feb 16, 2021

@jonathan-gibbons 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:

8257925: enable more support for nested inline tags

Reviewed-by: prappo, hannesw

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 42 new commits pushed to the master branch:

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 ready Pull request is ready to be integrated and removed merge-conflict Pull request has merge conflict with target branch labels Feb 16, 2021
Copy link
Member

@hns hns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!

@jonathan-gibbons
Copy link
Contributor Author

/integrate

@openjdk openjdk bot closed this Feb 19, 2021
@openjdk openjdk bot added integrated Pull request has been integrated and removed ready Pull request is ready to be integrated rfr Pull request is ready for review labels Feb 19, 2021
@openjdk
Copy link

openjdk bot commented Feb 19, 2021

@jonathan-gibbons Since your change was applied there have been 48 commits pushed to the master branch:

  • 433096a: 8261744: Implement CharsetDecoder ASCII and latin-1 fast-paths
  • efbaede: 8262018: Wrong format in SAP copyright header of OsVersionTest
  • 55463b0: 8261984: Shenandoah: Remove unused ShenandoahPushWorkerQueuesScope class
  • a180a38: 8260694: (fc) Clarify FileChannel.transferFrom to better describe "no bytes available" case
  • 1b0c36b: 8261649: AArch64: Optimize LSE atomics in C++ code
  • 61820b7: 8259984: IGV: Crash when drawing control flow before GCM
  • 7e2c909: 8260485: Simplify and unify handler vectors in Posix signal code
  • c99eeb0: 8260858: Implementation specific property xsltcIsStandalone for XSLTC Serializer
  • 5caf686: 8261644: NMT: Simplifications and cleanups
  • ed93bc9: 8196301: java/awt/print/PrinterJob/Margins.java times out
  • ... and 38 more: https://git.openjdk.java.net/jdk/compare/61a659f4bfe066250af871b9d84943bed526e71d...master

Your commit was automatically rebased without conflicts.

Pushed as commit c4f17a3.

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

@jonathan-gibbons jonathan-gibbons deleted the inline-tags branch February 19, 2021 15:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler compiler-dev@openjdk.org integrated Pull request has been integrated javadoc javadoc-dev@openjdk.org
3 participants