JDK-8231411 : Improve javac messages for using an API associated with a preview feature
  • Type: CSR
  • Component: tools
  • Sub-Component: javac
  • Priority: P3
  • Status: Closed
  • Resolution: Approved
  • Fix Versions: 14
  • Submitted: 2019-09-24
  • Updated: 2020-08-26
  • Resolved: 2019-10-16
Related Reports
CSR :  
Relates :  
Relates :  
Description
Summary
-------

Any API associated with a preview feature will receive special handling in javac and javadoc.

Problem
-------

In JDK 12 and 13, an API associated with a preview feature is annotated as deprecated for removal _as soon as the API is introduced_. For example, `String::stripIndent` is deprecated for removal in JDK 13 because it is associated with text blocks (JEP 355), a preview feature of JDK 13. The intent is to un-deprecate the API in a future JDK if the preview feature graduates into a final and permanent feature. However, using deprecation in this manner is problematic for at least two reasons: 1) Use of the API leads to a deprecation warning, but the warning does not communicate anything about the "connection" to a preview feature, leading to usability issues and confusion; 2) It is difficult to find/keep track of the APIs introduced for particular preview features.

Solution
--------

When an API element is added to support a preview feature, the API element will be marked as either a) "essential", if it appears in an ordinary, non-reflective API of Java SE, such as in a class in the `java.lang` package, or b) "non-essential", if it appears either in a reflective API of Java SE, such as in a class of `java.lang.reflect` or `javax.lang.model`, or in a JDK-specific API, such as in a class of the Trees API. Depending on the classification, any use of the marked element will get special handling in javac and javadoc.

Specification
-------------

Whenever use of a marked API element is detected, `javac` behaves as follows.

("Suppression" means <code>@SuppressWarnings("preview")</code> applies in the developer's program to the point where the marked API element is used/invoked/overridden.)

<table>
<tr>
<td>API type</td>
<td><pre>--enable-preview</pre> <pre>No Suppression</pre></td>
<td><pre>--enable-preview</pre> <pre>Suppression</pre></td>
<td><pre>No --enable-preview</pre> <pre>No Suppression</pre></td>
<td><pre>No --enable-preview</pre> <pre>Suppression</pre></td>
</tr>

<tr>
<td>essential</td>
<td>mandatory warning</td>
<td>no warning</td>
<td><strong>error</strong></td>
<td><strong>error</strong></td>
</tr>

<tr>
<td>non-essential</td>
<td>mandatory warning</td>
<td>no warning</td>
<td>mandatory warning</td>
<td>no warning</td>
</tr>
</table>

Note the bold text: when preview features are disabled, it is a compile-error to use an essential API element. The API element is available for use only when its "sponsoring" preview feature is enabled.

The precise output of javac for a "mandatory warning" is as follows:

 * with -Xlint:preview, a warning on each occurrence.
 * with -Xlint:-preview, a summary at the end of the compilation stating preview features have been used.

The default is -Xlint:preview when no --enable-preview is present, and -Xlint:-preview when --enable-preview is present. An explicit -Xlint setting overrides this default.

The list of essential Java SE APIs will be given in the JLS.

javadoc will contain a helpful text on all APIs related to preview features.

Marking an API element in support a preview feature does not represent a commitment to keep the API element in Java SE or the JDK beyond the lifetime of the preview feature. We reserve the right to remove any API that is so marked at any time.

The following specific API changes are also included:

In `java.lang.String`, the methods

  * `formatted(java.lang.Object...)`
  * `stripIndent()`
  * `translateEscapes()`

Analogous changes are made in the `com.sun.source` tree API for the switch expression features.

See details in the attached specdiff.
have their `@Deprecated` annotations removed and replaced with a preview feature warning.
Comments
Approving amended request after details of API changes added.
16-10-2019

I've attached a specdiff of javadoc changes (removal of deprecation for removal; and addition of warnings about API associated with preview features). It is also available for convenience here: http://cr.openjdk.java.net/~jlahoda/8226585/specdiff/overview-summary.html
16-10-2019

[~abuckley], I'm fine with no warning in that case given the modifications to the compilation environment that are needed to enable it. As there is still a difference in handling when --enable-preview is not used, the essential vs non-essential distinction is still germane to make. I'll vote to approve this amended request once there is a stated plan for the supporting API changes to java.lang.String and elsewhere. They could either be done as part of this CSR or under a separate one, whichever is easier. Thanks.
15-10-2019

@Joe Thanks ... I hear the alternative proposal, about a message rather than no warning at all, but I believe it would lead to the novel-in-itself situation of a message being printed even when `@SuppressWarnings` is used ... for consistency with suppression in general, and for consistency between the essential and non-essential rows (helpful for an implementation), I think the "no warning" behavior is best.
15-10-2019

[~abuckley], the modification you propose does address my concern. Another way to address my concern would be for essential API, under --enable-preview, with Suppression to generate a compiler *message* that did not result in a non-zero exit code. I think it would be acceptable if the message text contained the string "warning", perhaps as a summary "Warning: usage of APIs associated with preview features which may be ... Compile with -Xyz for more detail." Thanks.
15-10-2019

Update: I reviewed all the warnings with Brian. Our conclusion is that one of the boxes in the Specification's table is too tough. Specifically, for use of an essential API, if `--enable-preview` is employed then it should be possible to suppress the warning about the essential API usage, just like it is possible for a non-essential API when `--enable-preview` is used. The bold "mandatory warning" box would become simply "no warning". This puts essential APIs on the same footing as non-essential APIs -- if you don't suppress, then you get either a stern warning (which `javac -Xlint:all -Werror` will fail the build over) or an error (if you forgot `--enable-preview` entirely) ... but you always have the choice to suppress so that your API usage doesn't break the build. [~darcy] please confirm if this addresses your concern over `-Werror`.
15-10-2019

Previously on compiler-dev I stated: "To be precise on terminology, if compiling with --enable-preview, I think the warnings generated for using preview languages feature and associated API elements should be a little-w warnings. That is, messages from the compiler that still allows the compile to exist with a zero exit code. Operationally, such messages would be Diagnostic.Kind.NOTE rather than Diagnostic.Kind.{WARNING, MANDATORY_WARNING}. The goal would be to allow a clean compile under "-Xlint:all -Werror" when preview features were being used. Not allowing "successful" compile of preview features would further complicate adding preview features to CI pipelines, etc." https://mail.openjdk.java.net/pipermail/compiler-dev/2019-August/013621.html
15-10-2019

I agree with [~jlahoda] that `javac -Xlint:all -Werror` should complete successfully (return zero) only if the non-essential API usage occurs in code which suppresses the mandatory warning. If the non-essential API usage occurs in code which does NOT suppress the mandatory warning, then a warning is due. (Call it Warning NEAPI.) And, if an essential API usage occurs in code (regardless of whether the code tries to suppress), then a warning is due. (Call it Warning EAPI.) Warning EAPI should for sure cause a non-zero code under `javac -Xlint:all -Werror` -- [~darcy], if you disagree, please take to compiler-dev because it's a bigger issue for JEP 12 than this CSR can accommodate. Also, I want one kind of mandatory warning, not two, because the complexity of this is getting out of hand; consequently, I am fine if Warning NEAPI returns non-zero under `javac -Xlint:all -Werror` just like Warning EAPI does.
14-10-2019

"javac -Xlint:all -Werror" can complete successfully under this design under two conditions: a) the API used is non-essential; b) every use of the API is covered by a @SuppressWarnings("preview"). This should ensure the user is aware of the use of the API associated with the preview feature. Expanding cases where we allow the compiler to successfully compile source code may limit the user's awareness of the usage of the API associated with the preview features (for which we reserve the right to remove it at any time). Printing a note may not be efficient enough in notifying the user of the problem, as it may be lost in a long log output, and compiling with "-Xlint:all -Werror" should, I belive, mean "no issues at all". (Also, I believe that at least for the non-essential APIs, this behavior is similar to the @Deprecated behavior - "-Xlint:all -Werror" will fail for usages of deprecated APIs unless the usages are covered by @SuppressWarnings("deprecation")). For essential APIs, I believe [~abuckley] should comment on the behavior there.
14-10-2019

Please comment on the effect of mandatory previews warnings the return code of javac. If the API changes to remove the @Deprecated(forRemoval=true) annotations from the preview methods on java.lang.String are not being handled another another bug, please add them to this CSR.
08-10-2019

I believe an important operational consideration is that "javac -Xlint:all -Werror ..." can complete successfully in the presence of preview features being used. Therefore, for the spec above I'd like "mandatory warning" to be seen as a notification the compiler just give to the user rather than a requirement to given a non-zero error code of -Werror is enabled.
04-10-2019