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-8267126: javadoc should show "line and caret" for diagnostics. #4074
JDK-8267126: javadoc should show "line and caret" for diagnostics. #4074
Conversation
|
@jonathan-gibbons The following label will be automatically applied to this pull request:
When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command. |
Webrevs
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not a review, but preliminary comments to help me get started with the review.
if (configuration.workArounds.accessInternalAPI()) { | ||
Module thisModule = getClass().getModule(); | ||
Module tagletLoaderUnnamedModule = tagClassLoader.getUnnamedModule(); | ||
List<String> pkgs = List.of( | ||
"jdk.javadoc.doclet", | ||
"jdk.javadoc.internal.doclets.toolkit", | ||
"jdk.javadoc.internal.doclets.formats.html"); | ||
pkgs.forEach(p -> thisModule.addOpens(p, tagletLoaderUnnamedModule)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's that and the corresponding WorkArounds.accessInternalAPI about?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's Module System Magic. :-) Don't look too hard at the man behind the curtains.
The general problem is allowing external code to access module internals if they really want it and ask nicely. For external code that is provided on the class path, there are command-line options like --add-exports
and --add-opens
. These options allow a user to override access to module-internal classes for classes in the application class loader, which (colloquially) is the unnamed module for classes on the classpath.
The problem is that those command-line options do not grant access from module-internal classes to classes in "other" unnamed modules ... yes, there are many unnamed modules: essentially one per class loader. So, it is up to the creator of any additional class loader to decide whether to grant privileges to the classes in that class loader.
For javac, there are (regrettably) annotation processors and plugins that want to access javac internals, and those classes are (you guessed) loaded into a new class loader based on the -processorpath
option. And so the decision was made to provide an undocumented option to allow such code the same access that they had before the module system was introduced. That javac option is -XDaccessInternalAPI
. Note that -XD
is a semi-magic option that effectively allows any name=value
to be set in the internal options map, thus bypassing the normal mechanism for documentated options. And, side-note, javadoc
provides the same -XD
option for the same reasons. If you search the javac
code for the string "accessInternalAPI"
you will find two usages, one for plugins and one for anno-processors, and both result in a low-level utility method being called, ModuleHelper.addExports
, which gives various access rights to any classes in that class loader.
Side-story: In JDK 9, ModuleHelper
was much more complicated in its implementation, because it had to work entirely through core-reflection, because of the "bootstrap compiler" issue. Nowadays, it's much simpler.
Back to this PR. You've probably managed to guess most of the story at this point. There's functionality missing from taglets, but I want to write a test taglet that gets at the missing information. So, I've copied the javac backdoor mechanism, and opened up access to some of the internal javadoc packages, provided that a suitable command-line option is given. Further out, we should provide some of the API that is currently missing, so that the test code no longer needs access to doclet internals.
As for WorkArounds
, that class is the only one we allow in the standard doclet to access "tool stuff" via backdoors. In this case, WorkArounds
needs to access the compiler options, to see if XDaccessInternalAPI
has been set.
Note that both the javac and javadoc mechanism are in line with JPMS policy that you have to ask for the enhanced access by using command-line options.
* @return the diagnostic position | ||
*/ | ||
private DiagnosticPosition getDiagnosticPosition(DocTreePath path) { | ||
ToolEnvironment toolEnv = getToolEnv(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
toolEnv is unused.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I'll double check and delete if unused.
Confirmed; deleted. It preceded the use of utility method getSourcePositions
.
I'll update this in the next commit.
@@ -144,7 +142,6 @@ protected ToolEnvironment(Context context) { | |||
finder = JavadocClassFinder.instance(context); | |||
enter = JavadocEnter.instance(context); | |||
names = Names.instance(context); | |||
externalizableSym = syms.enterClass(syms.java_base, names.fromString("java.io.Externalizable")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What was externalizableSym about and why have you deleted it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TL;DR: the value was unused. It's gratuitous cleanup ;-)
The value was the Symbol
(javac subtype of Element
) for the class java.io.Externalizable
. I presume at some point it was required for handling serializable/externalizable classes, by checking if it was a supertype of a class being documented.
@@ -374,7 +374,7 @@ public void test4() { | |||
checkExit(Exit.OK); | |||
|
|||
// make sure the doclet indeed emits the warning | |||
checkOutput(Output.OUT, true, "C.java:0: warning - invalid usage of tag <"); | |||
checkOutput(Output.OUT, true, "C.java:31: warning: invalid usage of tag <"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is interesting: while the line coordinate of an error has changed in this test, those of TestSearch.java L676-L679 from this same PR have not. Mind you, I haven't investigated it yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a different error message, coming from a different place in the code, presumably with different contextual info.
In the other case, it was correct both before and after. In this case, it was wrong before and now correct. So that's good.
Tip: to find where errors come from, use (I think) -XD-doe
. As I wrote earlier in a different PR, -XD
is the general mechanism to set any option. -doe
is a hidden javac option, short for "dump on error", and triggers a track trace when any diagnostic is reported. It's handled down in Log. Look for uses of Log.dumpOnError
, especially roundabout line 771.
@@ -419,6 +419,7 @@ public final BooleanProperty somethingProperty() { | |||
javadoc("-d", "out5", | |||
"--javafx", | |||
"--disable-javafx-strict-checks", | |||
"--no-platform-links", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It just happens so that yesterday I asked Hannes about proliferation of --no-platform-links
in tests and now we have 3 more of those in this PR alone.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was getting more messages reporting that the classes could not be found. It was throwing off warning counts in golden output. My unproven suspicion is that we may not have been accurately counting warnings before this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will continue reviewing this change. Meanwhile, please update copyright years and address other nits below.
/** | ||
* Returns whether or not to permit dynamically loaded components to access | ||
* part of the javadoc internal API. The flag is the same (hidden) compiler | ||
* option that allows javac plugins and annotation processors to javac internal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you use "allow x to y" here in the sense of "letting x into y"? If so, consider using "allow x into y" instead of "allow x to y". Otherwise it might sound like there's a verb missing: allow to (access? enter?) javac internal API. My non-native English speaker's two cents.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, there was a missing verb. Fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(Copyrights: only TagletManager needed updating; done.)
* The class leverages the javac support for reporting diagnostics, for stylistic consistency | ||
* of diagnostic messages and to avoid code duplication. | ||
* | ||
* The class is a subtype of javac's Log, and is primarily a transducer between |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would "adapter" be more suitable than "transducer"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both are valid, but agreed that "adapter" is a more common term.
} | ||
|
||
/** | ||
* Print a message. | ||
* Part of DocErrorReporter. | ||
* Print a "notice" message. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add "s" to "print" for consistency with doc comment of other methods in this class.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely.
|
||
@Override | ||
public Void visitEntity(EntityTree node, Diagnostic.Kind k) { | ||
if (node.getName().contentEquals("#x1f955")) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this... a carrot (
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -112,6 +112,7 @@ private void test(Path base, String code, String expect) throws Exception { | |||
|
|||
javadoc("-d", base.resolve("api").toString(), | |||
"-Xdoclint:missing", | |||
"--no-platform-links", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More of those... sigh.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A different solution would be to disable platform links by default (in JavadocTester) and only enables for specific tests. But that would be a minor paradigm shift of JavadocTester providing default options.
@@ -75,7 +75,7 @@ File genSrc(int count) throws IOException { | |||
String javadoc(File f) { | |||
StringWriter sw = new StringWriter(); | |||
PrintWriter pw = new PrintWriter(sw); | |||
String[] args = { "-Xdoclint:none", "-d", "api", f.getPath() }; | |||
String[] args = { "-Xdoclint:none", "--no-platform-links", "-d", "api", f.getPath() }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Argh...
* <li>{@code Element} -- maps to {@code DiagnosticSource and {@code DiagnosticPosition} | ||
* <li>{@code DocTreePath} -- maps to {@code DiagnosticSource and {@code DiagnosticPosition} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Close @code
tags.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mildly worrying that "make docs" did not give errors ... but I guess the error was masked by the subsequent }
of the subsequent {@code ...}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mildly worrying that "make docs" did not give errors
This should be currently detectable by DocLint: since </ul>
is consumed by @code
, the ul
element is left unclosed.
* The javac layer deals primarily in pre-localized (key, args) pairs, | ||
* while the javadoc layer, especially the {@code Reporter} interface, deals in localized strings. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it is not a typo, consider changing "deal in" to something simpler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll try. Maybe something based on "operates on" or "uses" or something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rephrased the sentence and added more details as well.
/** The tool environment, providing access to the tool's utility classes and tables. */ | ||
private ToolEnvironment toolEnv; | ||
|
||
/** The utility class to access the positions of items in doc comments., */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove that trailing comma.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops
* messages directly. (A better solution would be to expose access to the output | ||
* and error streams via {@code DocletEnvironment}. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sentence: either remove "(" or add ")".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add ")" and change DocletEnvironment to Reporter for now, and to delete the sentence paragraph when we add streams to Reporter.
@jonathan-gibbons This change now passes all automated pre-integration checks. After integration, the commit message for the final commit will be:
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 4 new commits pushed to the
Please see this link for an up-to-date comparison between the source branch of this pull request and the
|
/integrate |
@jonathan-gibbons Since your change was applied there have been 4 commits pushed to the
Your commit was automatically rebased without conflicts. Pushed as commit b4d4884. |
Please review a change to overhaul the javadoc support for diagnostics to better leverage the support available in javac. This includes the ability for all javadoc diagnostics to show a "source line and caret" to indicate the position of a reported issue. As a side-effect, it normalizes the formatting of javadoc messages, to be consistent with javac messages.
The primary changes are in the javadoc
Messager
class, and are primarily focussed "downward" on the internal use of the javacLog.report
method, which is the nexus for reporting methods. There is additional cleanup that could be done inMessager
in the API it provides to clients, but (for the most part) that is not done in this work.Additional changes are done to facilitate writing a test for this work, and reflect the current shortcomings of the existing
Doclet
API. Most notably:Utils
to allow a user-defined taglet to override a built-in tagletTagletManager
andWorkarounds
to allow a user-defined taglet to access internal API, to workaround API that would be useful to provide onStandardDoclet
There are a few minor specific cleanup changes in code style and/or improved comments.
There is one primary new test,
TestDiagsLineCaret.java
which exercises different kinds of diagnostics at different positions in a file, to verify that the source line and a caret are produced as appropriate.There are additional test changes triggered by the slight change in the format of error messages. Most notably, prefixes like
error -
andwarning -
becomeerror:
andwarning:
.Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.java.net/jdk pull/4074/head:pull/4074
$ git checkout pull/4074
Update a local copy of the PR:
$ git checkout pull/4074
$ git pull https://git.openjdk.java.net/jdk pull/4074/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 4074
View PR using the GUI difftool:
$ git pr show -t 4074
Using diff file
Download this PR as a diff file:
https://git.openjdk.java.net/jdk/pull/4074.diff