This PR is primarily informational: aside from adding a few code comments and 
`assert` statements, it acts as a place to record observations on unknown 
JavaDoc tag reporting mechanics. Because it's a PR, this text will be 
automatically sent to the javadoc-dev mailing list and archived for future 
reference.

---

DocLint can be run in three modes:

  * from javac (i.e. `javac -Xdoclint`)
  * from javadoc (i.e. `javadoc -Xdoclint`)
  * as a standalone test tool (i.e. 
`test/langtools/tools/doclint/DocLintTester.java`)

While the core of all these modes is the same, 
`jdk.javadoc.internal.doclint.DocLint`, and is capable of reporting on unknown 
tags, whether an unknown tag will be reported, depends on the core 
configuration, which differs significantly among these modes.

The latter mode is for testing only and can be configured flexibly, but it's of 
little interest to us. The former two modes are important as they face end 
user, but are limited in their configuration and, additionally, each has own 
peculiarities.

In javac mode, DocLint cannot be passed with a list of custom tags: the 
required wiring is missing. So, when a potentially unknown tag is detected, the 
error is not raised because `env.customTags == null`:

    private void checkUnknownTag(DocTree tree, String tagName) {
        if (env.customTags != null && !env.customTags.contains(tagName))
            ^^^^^^^^^^^^^^^^^^^^^^
            env.messages.error(SYNTAX, tree, "dc.tag.unknown", tagName);
    }

This is why we don't see errors for JDK-specific tags (e.g. `@implSpec`, 
`@implNote`, `@apiNote`, `@jls`) when `make images`, during which DocLint is 
run from javac.

In javadoc mode DocLint is passed with a list of custom tags, containing tags 
captured from `-tag` and `-taglet` options. Because `make docs` runs javadoc 
with such options for each of the JDK-specific tags, all tags are known, and no 
errors are reported.

Here's a twist though: javadoc has its own machinery for reporting unknown 
tags. So why don't we see doubling of diagnostics? There should be an error 
from DocLint and a warning [sic!] from javadoc, but there's only an error. 
Here's why:

    public void checkTags(Element element, Iterable<? extends DocTree> trees) {
        CommentHelper ch = utils.getCommentHelper(element);
        for (DocTree tag : trees) {
            String name = tag.getKind().tagName;
                              ^^^^^^^^^^^^^^^^^
            if (name == null) {
                continue;
            }
            if (!name.isEmpty() && name.charAt(0) == '@') {
                name = name.substring(1);
            }
            if (! (standardTags.contains(name) || 
allTaglets.containsKey(name))) {
                if (standardTagsLowercase.contains(Utils.toLowerCase(name))) {
                    messages.warning(ch.getDocTreePath(tag), 
"doclet.UnknownTagLowercase", ch.getTagName(tag));
                    continue;
                } else {
                    messages.warning(ch.getDocTreePath(tag), 
"doclet.UnknownTag", ch.getTagName(tag));
                    continue;
                }
            }

Unknown tags are modelled by two `DocTree` subinterfaces, 
`UnknownInlineTagTree` and `UnknownBlockTagTree`, each of which return the name 
of the captured tag from `getTagName()`, not from `getKind().tagName`, which 
(unsurprisingly) returns null for those two kinds. That means that the body of 
this `if` block is dead code (i.e. DocLint or not, it's never reached for an 
unknown tag):

            if (! (standardTags.contains(name) || 
allTaglets.containsKey(name))) {

Here's another twist: DocLint can be disabled for a javadoc run: 
`-Xdoclint:none`. When coupled with defunct javadoc reporting, disabled DocLint 
means that no unknown tags are reported.

I don't know which of the above is by mistake and which by design, but it's how 
it works today. We could address (some of) that in a later PR. Personally, I 
wouldn't provide missing wiring in javac, given that javac mode has been 
recently somewhat de-emphasized. That said, I think we should repair javadoc 
reporting and make sure that either DocLint or javadoc, but not both, report on 
unknown tags at all times (i.e. whatever the javadoc configuration might be).

-------------

Commit messages:
 - Initial commit

Changes: https://git.openjdk.org/jdk/pull/15314/files
 Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=15314&range=00
  Issue: https://bugs.openjdk.org/browse/JDK-8314213
  Stats: 16 lines in 2 files changed: 15 ins; 0 del; 1 mod
  Patch: https://git.openjdk.org/jdk/pull/15314.diff
  Fetch: git fetch https://git.openjdk.org/jdk.git pull/15314/head:pull/15314

PR: https://git.openjdk.org/jdk/pull/15314

Reply via email to