<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p>Hi,</p>
    <p>I don't think it's possible to give a custom warning at compile
      time without the user having a specific annotation processor
      active (ie, to get the warning, they'd first need to set up an
      annotation processor which FX provides).  The problem here is that
      we can't enforce the use of the annotation processor
      unconditionally.</p>
    <p>The only annotation that you can use to intentionally create a
      compiler warning is the @Deprecated annotation (perhaps the
      compiler team should look into more annotations for this purpose).</p>
    <p>The deprecated annotation was used at the time of the first
      preview features to indicate their status, from JEP-12:</p>
    <p>
      <blockquote type="cite"><span style="color: rgb(94, 108, 132);
          font-family: "DejaVu Sans", sans-serif; font-size:
          14px; font-style: normal; font-variant-ligatures: normal;
          font-variant-caps: normal; font-weight: 400; letter-spacing:
          normal; orphans: 2; text-align: left; text-indent: 0px;
          text-transform: none; widows: 2; word-spacing: 0px;
          -webkit-text-stroke-width: 0px; white-space: normal;
          background-color: rgb(255, 255, 255);
          text-decoration-thickness: initial; text-decoration-style:
          initial; text-decoration-color: initial; display: inline
          !important; float: none;">The earliest version of this JEP
          proposed to use the deprecation mechanism for flagging APIs
          associated with preview features. Consequently, in Java SE 12
          and 13, the APIs associated with preview features were
          terminally deprecated at birth, that is, annotated with<span> </span></span><code
          class="prettyprint" style="font-family: SFMono-Medium,
          "SF Mono", "Segoe UI Mono", "Roboto
          Mono", "Ubuntu Mono", Menlo, Courier,
          monospace; color: rgb(94, 108, 132); font-size: 14px;
          font-style: normal; font-variant-ligatures: normal;
          font-variant-caps: normal; font-weight: 400; letter-spacing:
          normal; orphans: 2; text-align: left; text-indent: 0px;
          text-transform: none; widows: 2; word-spacing: 0px;
          -webkit-text-stroke-width: 0px; white-space: normal;
          background-color: rgb(255, 255, 255);
          text-decoration-thickness: initial; text-decoration-style:
          initial; text-decoration-color: initial;">@Deprecated(forRemoval=true,
          since=...)</code><span style="color: rgb(94, 108, 132);
          font-family: "DejaVu Sans", sans-serif; font-size:
          14px; font-style: normal; font-variant-ligatures: normal;
          font-variant-caps: normal; font-weight: 400; letter-spacing:
          normal; orphans: 2; text-align: left; text-indent: 0px;
          text-transform: none; widows: 2; word-spacing: 0px;
          -webkit-text-stroke-width: 0px; white-space: normal;
          background-color: rgb(255, 255, 255);
          text-decoration-thickness: initial; text-decoration-style:
          initial; text-decoration-color: initial; display: inline
          !important; float: none;"><span> </span>when they were
          introduced. For example, Java SE 13 declared an<span> </span></span><a
href="https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/lang/String.html#stripIndent%28%29"
          class="external-link" target="_blank" rel="nofollow noopener"
          title="Follow link" style="color: rgb(0, 82, 204);
          text-decoration: var(--aui-link-decoration); cursor: pointer;
          font-family: "DejaVu Sans", sans-serif; font-size:
          14px; font-style: normal; font-variant-ligatures: normal;
          font-variant-caps: normal; font-weight: 400; letter-spacing:
          normal; orphans: 2; text-align: left; text-indent: 0px;
          text-transform: none; widows: 2; word-spacing: 0px;
          -webkit-text-stroke-width: 0px; white-space: normal;
          background-color: rgb(255, 255, 255);">essential API
          associated with text blocks</a><span style="color: rgb(94,
          108, 132); font-family: "DejaVu Sans", sans-serif;
          font-size: 14px; font-style: normal; font-variant-ligatures:
          normal; font-variant-caps: normal; font-weight: 400;
          letter-spacing: normal; orphans: 2; text-align: left;
          text-indent: 0px; text-transform: none; widows: 2;
          word-spacing: 0px; -webkit-text-stroke-width: 0px;
          white-space: normal; background-color: rgb(255, 255, 255);
          text-decoration-thickness: initial; text-decoration-style:
          initial; text-decoration-color: initial; display: inline
          !important; float: none;">, and a<span> </span></span><a
href="https://docs.oracle.com/en/java/javase/13/docs/api/jdk.compiler/com/sun/source/tree/SwitchExpressionTree.html"
          class="external-link" target="_blank" rel="nofollow noopener"
          title="Follow link" style="color: rgb(0, 82, 204);
          text-decoration: var(--aui-link-decoration); cursor: pointer;
          font-family: "DejaVu Sans", sans-serif; font-size:
          14px; font-style: normal; font-variant-ligatures: normal;
          font-variant-caps: normal; font-weight: 400; letter-spacing:
          normal; orphans: 2; text-align: left; text-indent: 0px;
          text-transform: none; widows: 2; word-spacing: 0px;
          -webkit-text-stroke-width: 0px; white-space: normal;
          background-color: rgb(255, 255, 255);">reflective API
          associated with switch expressions</a><span style="color:
          rgb(94, 108, 132); font-family: "DejaVu Sans",
          sans-serif; font-size: 14px; font-style: normal;
          font-variant-ligatures: normal; font-variant-caps: normal;
          font-weight: 400; letter-spacing: normal; orphans: 2;
          text-align: left; text-indent: 0px; text-transform: none;
          widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;
          white-space: normal; background-color: rgb(255, 255, 255);
          text-decoration-thickness: initial; text-decoration-style:
          initial; text-decoration-color: initial; display: inline
          !important; float: none;">. However, the deprecation-based
          approach was eventually dropped because it was confusing to
          see an API element introduced in the same Java SE release as
          it was deprecated, that is, to see<span> </span></span><code
          class="prettyprint" style="font-family: SFMono-Medium,
          "SF Mono", "Segoe UI Mono", "Roboto
          Mono", "Ubuntu Mono", Menlo, Courier,
          monospace; color: rgb(94, 108, 132); font-size: 14px;
          font-style: normal; font-variant-ligatures: normal;
          font-variant-caps: normal; font-weight: 400; letter-spacing:
          normal; orphans: 2; text-align: left; text-indent: 0px;
          text-transform: none; widows: 2; word-spacing: 0px;
          -webkit-text-stroke-width: 0px; white-space: normal;
          background-color: rgb(255, 255, 255);
          text-decoration-thickness: initial; text-decoration-style:
          initial; text-decoration-color: initial;">@since 13</code><span
          style="color: rgb(94, 108, 132); font-family: "DejaVu
          Sans", sans-serif; font-size: 14px; font-style: normal;
          font-variant-ligatures: normal; font-variant-caps: normal;
          font-weight: 400; letter-spacing: normal; orphans: 2;
          text-align: left; text-indent: 0px; text-transform: none;
          widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px;
          white-space: normal; background-color: rgb(255, 255, 255);
          text-decoration-thickness: initial; text-decoration-style:
          initial; text-decoration-color: initial; display: inline
          !important; float: none;"><span> </span>and<span> </span></span><code
          class="prettyprint" style="font-family: SFMono-Medium,
          "SF Mono", "Segoe UI Mono", "Roboto
          Mono", "Ubuntu Mono", Menlo, Courier,
          monospace; color: rgb(94, 108, 132); font-size: 14px;
          font-style: normal; font-variant-ligatures: normal;
          font-variant-caps: normal; font-weight: 400; letter-spacing:
          normal; orphans: 2; text-align: left; text-indent: 0px;
          text-transform: none; widows: 2; word-spacing: 0px;
          -webkit-text-stroke-width: 0px; white-space: normal;
          background-color: rgb(255, 255, 255);
          text-decoration-thickness: initial; text-decoration-style:
          initial; text-decoration-color: initial;">@Deprecated(forRemoval=true,
          since="13")</code><span style="color: rgb(94, 108, 132);
          font-family: "DejaVu Sans", sans-serif; font-size:
          14px; font-style: normal; font-variant-ligatures: normal;
          font-variant-caps: normal; font-weight: 400; letter-spacing:
          normal; orphans: 2; text-align: left; text-indent: 0px;
          text-transform: none; widows: 2; word-spacing: 0px;
          -webkit-text-stroke-width: 0px; white-space: normal;
          background-color: rgb(255, 255, 255);
          text-decoration-thickness: initial; text-decoration-style:
          initial; text-decoration-color: initial; display: inline
          !important; float: none;"><span> </span>on the same API
          element.</span></blockquote>
      The PreviewFeature annotation can't be used I think, it's part of
      `jdk.internal.javac`.<br>
    </p>
    <p>--John</p>
    <div class="moz-cite-prefix">On 07/02/2024 13:21, Kevin Rushforth
      wrote:<br>
    </div>
    <blockquote type="cite"
      cite="mid:010b221f-e06c-42eb-87c4-17a7584d4cae@oracle.com">Yes,
      something like an opt-in property might be workable and is worth
      considering. We would also want to explore ideas for producing a
      compile-time warning along with with a pattern to document them.
      I'm not familiar enough with what you can do with annotations, but
      maybe there is something there that could help.
      <br>
      <br>
      We should explore this further for JavaFX 23.
      <br>
      <br>
      -- Kevin
      <br>
      <br>
      <br>
      On 2/7/2024 1:22 AM, John Hendrikx wrote:
      <br>
      <blockquote type="cite">Hi Kevin, Michael,
        <br>
        <br>
        I think throwing an exception when using features that are
        preview without a prerequisite property being present or set to
        some value would be a good idea.  JavaFX has quite a few
        properties already, and a special one for previews would make it
        possible to ensure that such a feature is not being used without
        being aware of it.
        <br>
        <br>
        I would suggest making the property consists of keys (comma
        separated) so you must opt-in to each preview feature
        separately, or having multiple properties that follow a specific
        pattern.
        <br>
        <br>
        A preview check can be as simple as:
        <br>
        <br>
             if
        (!Boolean.getProperty("javafx.enablePreview.platformPrefs") )
        throw new UnsupportedOperationException(STANDARD_DISCLAIMER +
        "preview feature, please enable: xyz");
        <br>
        <br>
        The disclaimer can be a standard piece of text explaining what a
        preview feature is, what it means, and what guarantees we offer
        (as limited as they might be).  For example, I think preview
        features are still guaranteed to be maintained for the release
        version they target, but that may be altered or completely
        removed in a next major release.
        <br>
        <br>
        I think a warning line is insufficient, especially when preview
        feature use may be inherited via a dependency.
        <br>
        <br>
        --John
        <br>
        <br>
        On 07/02/2024 02:06, Michael Strauß wrote:
        <br>
        <blockquote type="cite">Hi Kevin,
          <br>
          <br>
          my suggestion would be to annotate and document the preview
          API (at
          <br>
          least annotations do show up by default in most IDEs), and
          emit a
          <br>
          one-time runtime warning when the API is used (this works for
          methods
          <br>
          and constructors). This would make it quite visible to
          developers that
          <br>
          they are using a preview feature, or that a third-party
          library uses a
          <br>
          preview feature.
          <br>
          <br>
          The runtime warning can be suppressed with a command line
          parameter
          <br>
          such as "javafx.enablePreviewFeatures". A more drastic
          approach would
          <br>
          be to throw an exception from new APIs when the parameter is
          not
          <br>
          specified.
          <br>
          <br>
          Given that there are very tangible benefits to previewing new
          API,
          <br>
          this would seem to me like a good enough solution.
          <br>
          <br>
          <br>
          On Wed, Feb 7, 2024 at 12:59 AM Kevin Rushforth
          <br>
          <a class="moz-txt-link-rfc2396E" href="mailto:kevin.rushforth@oracle.com"><kevin.rushforth@oracle.com></a> wrote:
          <br>
          <blockquote type="cite">In order for preview features and
            incubating features to not cause more
            <br>
            problems than they solve, there needs to be a robust way to
            ensure that
            <br>
            applications and libraries don't use them without knowing
            that they are
            <br>
            doing so. We know how to do that for a feature that lives in
            its own
            <br>
            module (an incubating feature), but not how to do that for
            something
            <br>
            like a preview feature.
            <br>
            <br>
            For incubating features, this is relatively
            straight-forward, since they
            <br>
            are delivered in a separate module that has "incubator" in
            the name,
            <br>
            isn't resolved by default, and warns you at runtime when
            those modules
            <br>
            are resolved. Adapting what the JDK does for JavaFX should
            be pretty
            <br>
            easy, and retain the benefit that an app knows when they are
            using
            <br>
            incubating features.
            <br>
            <br>
            I don't think it is feasible to do the same thing for
            preview features.
            <br>
            The way the JDK preview features work is that a command line
            option is
            <br>
            needed both at compile time and at runtime to opt into
            preview features
            <br>
            for a specific release. This prevents using a preview API
            from an
            <br>
            existing module and package without knowing that it is
            subject to
            <br>
            change. Without a clear "opt in" mechanism to be able to use
            an API, an
            <br>
            app would be able to accidentally use a feature whose API is
            unstable
            <br>
            and quite possible might change. An annotation isn't good
            enough (and
            <br>
            documentation certainly isn't sufficient). IDEs will still
            autocomplete
            <br>
            and show the API, and once an app uses it -- accidentally or
            otherwise
            <br>
            -- there is no indication at runtime that you are using a
            feature that
            <br>
            will likely stop working without any notice in the next
            version.
            <br>
            <br>
            I don't see a good way to do this for JavaFX given the
            limitations.
            <br>
            <br>
            -- Kevin
            <br>
          </blockquote>
        </blockquote>
      </blockquote>
      <br>
    </blockquote>
  </body>
</html>