8226585: Improve javac messages for using a preview API
authorjlahoda
Mon, 21 Oct 2019 15:38:26 +0200
changeset 58713 ad69fd32778e
parent 58712 14e098407bb0
child 58720 ae0af9fb3dbb
8226585: Improve javac messages for using a preview API Summary: Avoiding deprecation for removal for APIs associated with preview features, the features are marked with an annotation, and errors/warnings are produced for them based on the annotation. Reviewed-by: erikj, mcimadamore, alanb Contributed-by: joe.darcy@oracle.com, jan.lahoda@oracle.com
make/CompileInterimLangtools.gmk
make/Docs.gmk
make/jdk/src/classes/build/tools/taglet/Preview.java
src/java.base/share/classes/java/lang/String.java
src/java.base/share/classes/jdk/internal/PreviewFeature.java
src/java.base/share/classes/module-info.java
src/jdk.compiler/share/classes/com/sun/source/tree/CaseTree.java
src/jdk.compiler/share/classes/com/sun/source/tree/SwitchExpressionTree.java
src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java
src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java
src/jdk.compiler/share/classes/com/sun/source/tree/YieldTree.java
src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java
src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java
src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskPool.java
src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java
src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java
src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java
src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java
src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java
src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java
src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java
src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java
src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java
src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties
src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java
src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java
src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java
src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java
src/jdk.compiler/share/classes/com/sun/tools/javac/util/MandatoryWarningHandler.java
src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java
test/jdk/java/lang/String/Formatted.java
test/jdk/java/lang/String/StripIndent.java
test/jdk/java/lang/String/TranslateEscapes.java
test/langtools/tools/javac/diags/examples.not-yet.txt
test/langtools/tools/javac/lib/combo/ComboInstance.java
test/langtools/tools/javac/preview/PreviewErrors.java
test/langtools/tools/javac/tree/NoPrivateTypesExported.java
test/langtools/tools/jdeps/listdeps/ListModuleDeps.java
--- a/make/CompileInterimLangtools.gmk	Mon Oct 21 15:11:44 2019 +0200
+++ b/make/CompileInterimLangtools.gmk	Mon Oct 21 15:38:26 2019 +0200
@@ -49,6 +49,13 @@
 TARGETS += $(patsubst %, $(BUILDTOOLS_OUTPUTDIR)/gensrc/%/module-info.java, \
     $(INTERIM_LANGTOOLS_MODULES))
 
+$(eval $(call SetupCopyFiles, COPY_PREVIEW_FEATURES, \
+    FILES := $(TOPDIR)/src/java.base/share/classes/jdk/internal/PreviewFeature.java, \
+    DEST := $(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim/jdk/internal/, \
+))
+
+TARGETS += $(COPY_PREVIEW_FEATURES)
+
 ################################################################################
 # Setup the rules to build interim langtools, which is compiled by the boot
 # javac and can be run on the boot jdk. This will be used to compile the rest of
@@ -72,13 +79,15 @@
       BIN := $(BUILDTOOLS_OUTPUTDIR)/interim_langtools_modules/$1.interim, \
       ADD_JAVAC_FLAGS := --module-path $(BUILDTOOLS_OUTPUTDIR)/interim_langtools_modules \
           $$(INTERIM_LANGTOOLS_ADD_EXPORTS) \
+          --patch-module java.base=$(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim \
+          --add-exports java.base/jdk.internal=jdk.compiler.interim \
           -Xlint:-module, \
   ))
 
   $1_DEPS_INTERIM := $$(addsuffix .interim, $$(filter \
       $$(INTERIM_LANGTOOLS_BASE_MODULES), $$(call FindTransitiveDepsForModule, $1)))
 
-  $$(BUILD_$1.interim): $$(foreach d, $$($1_DEPS_INTERIM), $$(BUILD_$$d))
+  $$(BUILD_$1.interim): $$(foreach d, $$($1_DEPS_INTERIM), $$(BUILD_$$d)) $(COPY_PREVIEW_FEATURES)
 
   TARGETS += $$(BUILD_$1.interim)
 endef
--- a/make/Docs.gmk	Mon Oct 21 15:11:44 2019 +0200
+++ b/make/Docs.gmk	Mon Oct 21 15:38:26 2019 +0200
@@ -95,6 +95,7 @@
     -tag see \
     -taglet build.tools.taglet.ExtLink \
     -taglet build.tools.taglet.Incubating \
+    -taglet build.tools.taglet.Preview \
     -tagletpath $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
     $(CUSTOM_JAVADOC_TAGS) \
     #
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/make/jdk/src/classes/build/tools/taglet/Preview.java	Mon Oct 21 15:38:26 2019 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package build.tools.taglet;
+
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Predicate;
+import javax.lang.model.element.Element;
+import com.sun.source.doctree.DocTree;
+import com.sun.source.doctree.TextTree;
+import com.sun.source.doctree.UnknownInlineTagTree;
+import jdk.javadoc.doclet.Taglet;
+import static jdk.javadoc.doclet.Taglet.Location.*;
+
+/**
+ * An block tag to insert a standard warning about a preview API.
+ */
+public class Preview implements Taglet {
+
+    /** Returns the set of locations in which a taglet may be used. */
+    @Override
+    public Set<Location> getAllowedLocations() {
+        return EnumSet.of(MODULE, PACKAGE, TYPE, CONSTRUCTOR, METHOD, FIELD);
+    }
+
+    @Override
+    public boolean isInlineTag() {
+        return true;
+    }
+
+    @Override
+    public String getName() {
+        return "preview";
+    }
+
+    @Override
+    public String toString(List<? extends DocTree> tags, Element elem) {
+        UnknownInlineTagTree previewTag = (UnknownInlineTagTree) tags.get(0);
+        List<? extends DocTree> previewContent = previewTag.getContent();
+        String previewText = ((TextTree) previewContent.get(0)).getBody();
+        String[] summaryAndDetails = previewText.split("\n\r?\n\r?");
+        String summary = summaryAndDetails[0];
+        String details = summaryAndDetails.length > 1 ? summaryAndDetails[1] : summaryAndDetails[0];
+        StackTraceElement[] stackTrace = new Exception().getStackTrace();
+        Predicate<StackTraceElement> isSummary =
+                el -> el.getClassName().endsWith("HtmlDocletWriter") &&
+                      el.getMethodName().equals("addSummaryComment");
+        if (Arrays.stream(stackTrace).anyMatch(isSummary)) {
+            return "<div style=\"display:inline-block; font-weight:bold\">" + summary + "</div><br>";
+        }
+        return "<div style=\"border: 1px solid red; border-radius: 5px; padding: 5px; display:inline-block; font-size: larger\">" + details + "</div><br>";
+    }
+}
+
--- a/src/java.base/share/classes/java/lang/String.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/java.base/share/classes/java/lang/String.java	Mon Oct 21 15:38:26 2019 +0200
@@ -2888,6 +2888,15 @@
     }
 
     /**
+     * {@preview Associated with text blocks, a preview feature of
+     *           the Java language.
+     *
+     *           This method is associated with <i>text blocks</i>, a preview
+     *           feature of the Java language. Programs can only use this
+     *           method when preview features are enabled. Preview features
+     *           may be removed in a future release, or upgraded to permanent
+     *           features of the Java language.}
+     *
      * Returns a string whose value is this string, with incidental
      * {@linkplain Character#isWhitespace(int) white space} removed from
      * the beginning and end of every line.
@@ -2963,10 +2972,9 @@
      *
      * @since 13
      *
-     * @deprecated  This method is associated with text blocks, a preview language feature.
-     *              Text blocks and/or this method may be changed or removed in a future release.
      */
-    @Deprecated(forRemoval=true, since="13")
+    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.TEXT_BLOCKS,
+                                 essentialAPI=true)
     public String stripIndent() {
         int length = length();
         if (length == 0) {
@@ -3005,6 +3013,15 @@
     }
 
     /**
+     * {@preview Associated with text blocks, a preview feature of
+     *           the Java language.
+     *
+     *           This method is associated with <i>text blocks</i>, a preview
+     *           feature of the Java language. Programs can only use this
+     *           method when preview features are enabled. Preview features
+     *           may be removed in a future release, or upgraded to permanent
+     *           features of the Java language.}
+     *
      * Returns a string whose value is this string, with escape sequences
      * translated as if in a string literal.
      * <p>
@@ -3079,11 +3096,9 @@
      * @jls 3.10.7 Escape Sequences
      *
      * @since 13
-     *
-     * @deprecated  This method is associated with text blocks, a preview language feature.
-     *              Text blocks and/or this method may be changed or removed in a future release.
      */
-    @Deprecated(forRemoval=true, since="13")
+    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.TEXT_BLOCKS,
+                                 essentialAPI=true)
     public String translateEscapes() {
         if (isEmpty()) {
             return "";
@@ -3309,6 +3324,15 @@
     }
 
     /**
+     * {@preview Associated with text blocks, a preview feature of
+     *           the Java language.
+     *
+     *           This method is associated with <i>text blocks</i>, a preview
+     *           feature of the Java language. Programs can only use this
+     *           method when preview features are enabled. Preview features
+     *           may be removed in a future release, or upgraded to permanent
+     *           features of the Java language.}
+     *
      * Formats using this string as the format string, and the supplied
      * arguments.
      *
@@ -3324,10 +3348,9 @@
      *
      * @since 13
      *
-     * @deprecated  This method is associated with text blocks, a preview language feature.
-     *              Text blocks and/or this method may be changed or removed in a future release.
      */
-    @Deprecated(forRemoval=true, since="13")
+    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.TEXT_BLOCKS,
+                                 essentialAPI=true)
     public String formatted(Object... args) {
         return new Formatter().format(this, args).toString();
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/jdk/internal/PreviewFeature.java	Mon Oct 21 15:38:26 2019 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.internal;
+
+import java.lang.annotation.*;
+
+/**
+ * Indicates the API declaration in question is associated with a
+ * <em>preview feature</em>. See JEP 12: "Preview Language and VM
+ * Features" (http://openjdk.java.net/jeps/12).
+ * @since 14
+ */
+// Match the meaningful targets of java.lang.Deprecated, omit local
+// variables and parameter declarations
+@Target({ElementType.METHOD,
+         ElementType.CONSTRUCTOR,
+         ElementType.FIELD,
+         ElementType.PACKAGE,
+         ElementType.MODULE,
+         ElementType.TYPE})
+ // CLASS retention will hopefully be sufficient for the purposes at hand
+@Retention(RetentionPolicy.CLASS)
+// *Not* @Documented
+public @interface PreviewFeature {
+    /**
+     * Name of the preview feature the annotated API is associated
+     * with.
+     */
+    public Feature feature();
+
+    public boolean essentialAPI() default false;
+
+    public enum Feature {
+        SWITCH_EXPRESSIONS,
+        TEXT_BLOCKS;
+    }
+}
--- a/src/java.base/share/classes/module-info.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/java.base/share/classes/module-info.java	Mon Oct 21 15:38:26 2019 +0200
@@ -135,7 +135,8 @@
     exports com.sun.security.ntlm to
         java.security.sasl;
     exports jdk.internal to
-        jdk.jfr;
+        jdk.jfr,
+        jdk.compiler;
     exports jdk.internal.access to
         java.desktop,
         java.logging,
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/CaseTree.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/CaseTree.java	Mon Oct 21 15:38:26 2019 +0200
@@ -55,17 +55,25 @@
     ExpressionTree getExpression();
 
     /**
+     * {@preview Associated with switch expressions, a preview feature of
+     *           the Java language.
+     *
+     *           This method is associated with <i>switch expressions</i>, a preview
+     *           feature of the Java language. Preview features
+     *           may be removed in a future release, or upgraded to permanent
+     *           features of the Java language.}
+     *
      * Returns the labels for this case.
      * For default case, returns an empty list.
      *
      * @return labels for this case
      * @since 12
      *
-     * @deprecated This method is modeling a case with multiple labels,
+     * @preview This method is modeling a case with multiple labels,
      * which is part of a preview feature and may be removed
      * if the preview feature is removed.
      */
-    @Deprecated(forRemoval=true, since="12")
+    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SWITCH_EXPRESSIONS)
     List<? extends ExpressionTree> getExpressions();
 
     /**
@@ -78,6 +86,14 @@
     List<? extends StatementTree> getStatements();
 
     /**
+     * {@preview Associated with switch expressions, a preview feature of
+     *           the Java language.
+     *
+     *           This method is associated with <i>switch expressions</i>, a preview
+     *           feature of the Java language. Preview features
+     *           may be removed in a future release, or upgraded to permanent
+     *           features of the Java language.}
+     *
      * For case with kind {@linkplain CaseKind#RULE},
      * returns the statement or expression after the arrow.
      * Returns {@code null} for case with kind
@@ -85,32 +101,41 @@
      *
      * @return case value or null
      * @since 12
-     *
-     * @deprecated This method is modeling a rule case,
-     * which is part of a preview feature and may be removed
-     * if the preview feature is removed.
      */
-    @Deprecated(forRemoval=true, since="12")
+    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SWITCH_EXPRESSIONS)
     public default Tree getBody() {
         return null;
     }
 
     /**
+     * {@preview Associated with switch expressions, a preview feature of
+     *           the Java language.
+     *
+     *           This method is associated with <i>switch expressions</i>, a preview
+     *           feature of the Java language. Preview features
+     *           may be removed in a future release, or upgraded to permanent
+     *           features of the Java language.}
+     *
      * Returns the kind of this case.
      *
      * @return the kind of this case
      * @since 12
-     *
-     * @deprecated This method is used to model a rule case,
-     * which is part of a preview feature and may be removed
-     * if the preview feature is removed.
      */
-    @Deprecated(forRemoval=true, since="12")
+    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SWITCH_EXPRESSIONS)
+    @SuppressWarnings("preview")
     public default CaseKind getCaseKind() {
         return CaseKind.STATEMENT;
     }
 
     /**
+     * {@preview Associated with switch expressions, a preview feature of
+     *           the Java language.
+     *
+     *           This enum is associated with <i>switch expressions</i>, a preview
+     *           feature of the Java language. Preview features
+     *           may be removed in a future release, or upgraded to permanent
+     *           features of the Java language.}
+     *
      * The syntatic form of this case:
      * <ul>
      *     <li>STATEMENT: {@code case <expression>: <statements>}</li>
@@ -118,12 +143,9 @@
      * </ul>
      *
      * @since 12
-     *
-     * @deprecated This enum is used to model a rule case,
-     * which is part of a preview feature and may be removed
-     * if the preview feature is removed.
      */
-    @Deprecated(forRemoval=true, since="12")
+    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SWITCH_EXPRESSIONS)
+    @SuppressWarnings("preview")
     public enum CaseKind {
         /**
          * Case is in the form: {@code case <expression>: <statements>}.
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/SwitchExpressionTree.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/SwitchExpressionTree.java	Mon Oct 21 15:38:26 2019 +0200
@@ -28,6 +28,14 @@
 import java.util.List;
 
 /**
+ * {@preview Associated with switch expressions, a preview feature of
+ *           the Java language.
+ *
+ *           This interface is associated with <i>switch expressions</i>, a preview
+ *           feature of the Java language. Preview features
+ *           may be removed in a future release, or upgraded to permanent
+ *           features of the Java language.}
+ *
  * A tree node for a {@code switch} expression.
  *
  * For example:
@@ -40,12 +48,8 @@
  * @jls 15.29 Switch Expressions
  *
  * @since 12
- *
- * @deprecated This method is modeling switch expressions,
- * which are part of a preview feature and may be removed
- * if the preview feature is removed.
  */
-@Deprecated(forRemoval=true, since="12")
+@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SWITCH_EXPRESSIONS)
 public interface SwitchExpressionTree extends ExpressionTree {
     /**
      * Returns the expression for the {@code switch} expression.
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java	Mon Oct 21 15:38:26 2019 +0200
@@ -240,17 +240,20 @@
         SWITCH(SwitchTree.class),
 
         /**
+         * {@preview Associated with switch expressions, a preview feature of
+         *           the Java language.
+         *
+         *           This enum constant is associated with <i>switch expressions</i>, a preview
+         *           feature of the Java language. Preview features
+         *           may be removed in a future release, or upgraded to permanent
+         *           features of the Java language.}
+         *
          * Used for instances of {@link SwitchExpressionTree}.
          *
          * @since 12
-         *
-         * @deprecated
-         * This enum constant is modeling switch expressions,
-         * which are part of a preview feature and may be removed
-         * if the preview feature is removed.
          */
-        @Deprecated(forRemoval=true, since="12")
-        @SuppressWarnings("removal")
+        @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SWITCH_EXPRESSIONS)
+        @SuppressWarnings("preview")
         SWITCH_EXPRESSION(SwitchExpressionTree.class),
 
         /**
@@ -659,17 +662,20 @@
         OTHER(null),
 
         /**
+         * {@preview Associated with switch expressions, a preview feature of
+         *           the Java language.
+         *
+         *           This enum constant is associated with <i>switch expressions</i>, a preview
+         *           feature of the Java language. Preview features
+         *           may be removed in a future release, or upgraded to permanent
+         *           features of the Java language.}
+         *
          * Used for instances of {@link YieldTree}.
          *
          * @since 13
-         *
-         * @deprecated
-         * This enum constant is modeling yield statement,
-         * which are part of a preview feature and may be removed
-         * if the preview feature is removed.
          */
-        @Deprecated(forRemoval=true, since="13")
-        @SuppressWarnings("removal")
+        @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SWITCH_EXPRESSIONS)
+        @SuppressWarnings("preview")
         YIELD(YieldTree.class);
 
 
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java	Mon Oct 21 15:38:26 2019 +0200
@@ -354,20 +354,23 @@
     R visitSwitch(SwitchTree node, P p);
 
     /**
+     * {@preview Associated with switch expressions, a preview feature of
+     *           the Java language.
+     *
+     *           This method is associated with <i>switch expressions</i>, a preview
+     *           feature of the Java language. Preview features
+     *           may be removed in a future release, or upgraded to permanent
+     *           features of the Java language.}
+     *
      * Visits a SwitchExpressionTree node.
      *
      * @param node the node being visited
      * @param p a parameter value
      * @return a result value
      * @since 12
-     *
-     * @deprecated
-     * This method is modeling switch expressions,
-     * which are part of a preview feature and may be removed
-     * if the preview feature is removed.
      */
-    @Deprecated(forRemoval=true, since="12")
-    @SuppressWarnings("removal")
+    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SWITCH_EXPRESSIONS)
+    @SuppressWarnings("preview")
     R visitSwitchExpression(SwitchExpressionTree node, P p);
 
     /**
@@ -557,18 +560,21 @@
     R visitOther(Tree node, P p);
 
     /**
+     * {@preview Associated with switch expressions, a preview feature of
+     *           the Java language.
+     *
+     *           This method is associated with <i>switch expressions</i>, a preview
+     *           feature of the Java language. Preview features
+     *           may be removed in a future release, or upgraded to permanent
+     *           features of the Java language.}
+     *
      * Visits a YieldTree node.
      * @param node the node being visited
      * @param p a parameter value
      * @return a result value
      * @since 13
-     *
-     * @deprecated
-     * This method is modeling yield statement,
-     * which are part of a preview feature and may be removed
-     * if the preview feature is removed.
      */
-    @Deprecated(forRemoval=true, since="13")
-    @SuppressWarnings("removal")
+    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SWITCH_EXPRESSIONS)
+    @SuppressWarnings("preview")
     R visitYield(YieldTree node, P p);
 }
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/YieldTree.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/YieldTree.java	Mon Oct 21 15:38:26 2019 +0200
@@ -26,6 +26,14 @@
 package com.sun.source.tree;
 
 /**
+ * {@preview Associated with switch expressions, a preview feature of
+ *           the Java language.
+ *
+ *           This method is associated with <i>switch expressions</i>, a preview
+ *           feature of the Java language. Preview features
+ *           may be removed in a future release, or upgraded to permanent
+ *           features of the Java language.}
+ *
  * A tree node for a {@code yield} statement.
  *
  * For example:
@@ -36,12 +44,8 @@
  * @jls section TODO
  *
  * @since 13
- *
- * @deprecated This class is modeling yield from switch expressions,
- * which are part of a preview feature and may be removed if
- * the preview feature is removed.
  */
-@Deprecated(forRemoval=true, since="13")
+@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SWITCH_EXPRESSIONS)
 public interface YieldTree extends StatementTree {
 
     /**
--- a/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java	Mon Oct 21 15:38:26 2019 +0200
@@ -264,20 +264,23 @@
     }
 
     /**
+     * {@preview Associated with switch expressions, a preview feature of
+     *           the Java language.
+     *
+     *           This method is associated with <i>switch expressions</i>, a preview
+     *           feature of the Java language. Preview features
+     *           may be removed in a future release, or upgraded to permanent
+     *           features of the Java language.}
+     *
      * {@inheritDoc} This implementation calls {@code defaultAction}.
      *
      * @param node {@inheritDoc}
      * @param p {@inheritDoc}
      * @return  the result of {@code defaultAction}
-     *
-     * @deprecated
-     * This method is modeling switch expressions,
-     * which are part of a preview feature and may be removed
-     * if the preview feature is removed.
      */
     @Override
-    @Deprecated(forRemoval=true, since="12")
-    @SuppressWarnings("removal")
+    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SWITCH_EXPRESSIONS)
+    @SuppressWarnings("preview")
     public R visitSwitchExpression(SwitchExpressionTree node, P p) {
         return defaultAction(node, p);
     }
@@ -791,8 +794,8 @@
      * @return  the result of {@code defaultAction}
      */
     @Override
-    @Deprecated(forRemoval=true, since="13")
-    @SuppressWarnings("removal")
+    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SWITCH_EXPRESSIONS)
+    @SuppressWarnings("preview")
     public R visitYield(YieldTree node, P p) {
         return defaultAction(node, p);
     }
--- a/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java	Mon Oct 21 15:38:26 2019 +0200
@@ -26,7 +26,6 @@
 package com.sun.source.util;
 
 import com.sun.source.tree.*;
-import com.sun.source.tree.CaseTree.CaseKind;
 
 /**
  * A TreeVisitor that visits all the child tree nodes.
@@ -335,20 +334,23 @@
     }
 
     /**
+     * {@preview Associated with switch expressions, a preview feature of
+     *           the Java language.
+     *
+     *           This method is associated with <i>switch expressions</i>, a preview
+     *           feature of the Java language. Preview features
+     *           may be removed in a future release, or upgraded to permanent
+     *           features of the Java language.}
+     *
      * {@inheritDoc} This implementation scans the children in left to right order.
      *
      * @param node  {@inheritDoc}
      * @param p  {@inheritDoc}
      * @return the result of scanning
-     *
-     * @deprecated
-     * This method is modeling switch expressions,
-     * which are part of a preview feature and may be removed
-     * if the preview feature is removed.
      */
     @Override
-    @Deprecated(forRemoval=true, since="12")
-    @SuppressWarnings("removal")
+    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SWITCH_EXPRESSIONS)
+    @SuppressWarnings("preview")
     public R visitSwitchExpression(SwitchExpressionTree node, P p) {
         R r = scan(node.getExpression(), p);
         r = scanAndReduce(node.getCases(), p, r);
@@ -363,10 +365,10 @@
      * @return the result of scanning
      */
     @Override
-    @SuppressWarnings("removal")
+    @SuppressWarnings("preview")
     public R visitCase(CaseTree node, P p) {
         R r = scan(node.getExpressions(), p);
-        if (node.getCaseKind() == CaseKind.RULE)
+        if (node.getCaseKind() == CaseTree.CaseKind.RULE)
             r = scanAndReduce(node.getBody(), p, r);
         else
             r = scanAndReduce(node.getStatements(), p, r);
@@ -936,20 +938,23 @@
     }
 
     /**
+     * {@preview Associated with switch expressions, a preview feature of
+     *           the Java language.
+     *
+     *           This method is associated with <i>switch expressions</i>, a preview
+     *           feature of the Java language. Preview features
+     *           may be removed in a future release, or upgraded to permanent
+     *           features of the Java language.}
+     *
      * {@inheritDoc} This implementation returns {@code null}.
      *
      * @param node  {@inheritDoc}
      * @param p  {@inheritDoc}
      * @return the result of scanning
-     *
-     * @deprecated
-     * This method is modeling switch expressions,
-     * which are part of a preview feature and may be removed
-     * if the preview feature is removed.
      */
     @Override
-    @Deprecated(forRemoval=true, since="13")
-    @SuppressWarnings("removal")
+    @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SWITCH_EXPRESSIONS)
+    @SuppressWarnings("preview")
     public R visitYield(YieldTree node, P p) {
         return scan(node.getValue(), p);
     }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskPool.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskPool.java	Mon Oct 21 15:38:26 2019 +0200
@@ -52,6 +52,7 @@
 import com.sun.source.util.TaskListener;
 import com.sun.source.util.TreeScanner;
 import com.sun.tools.javac.code.Kinds;
+import com.sun.tools.javac.code.Preview;
 import com.sun.tools.javac.code.Symbol;
 import com.sun.tools.javac.code.Symtab;
 import com.sun.tools.javac.code.Type;
@@ -257,6 +258,8 @@
                 ((ReusableJavaCompiler)ReusableJavaCompiler.instance(this)).clear();
                 Types.instance(this).newRound();
                 Check.instance(this).newRound();
+                Check.instance(this).clear(); //clear mandatory warning handlers
+                Preview.instance(this).clear(); //clear mandatory warning handlers
                 Modules.instance(this).newRound();
                 Annotate.instance(this).newRound();
                 CompileStates.instance(this).clear();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java	Mon Oct 21 15:38:26 2019 +0200
@@ -286,7 +286,17 @@
     /**
      * Flag to indicate the given ModuleSymbol is an automatic module.
      */
-    public static final long AUTOMATIC_MODULE = 1L<<52;
+    public static final long AUTOMATIC_MODULE = 1L<<52; //ModuleSymbols only
+
+    /**
+     * Flag to indicate the given PackageSymbol contains any non-.java and non-.class resources.
+     */
+    public static final long HAS_RESOURCE = 1L<<52; //PackageSymbols only
+
+    /**
+     * Flag to indicate the given ParamSymbol has a user-friendly name filled.
+     */
+    public static final long NAME_FILLED = 1L<<52; //ParamSymbols only
 
     /**
      * Flag to indicate the given ModuleSymbol is a system module.
@@ -304,9 +314,9 @@
     public static final long DEPRECATED_REMOVAL = 1L<<55;
 
     /**
-     * Flag to indicate the given PackageSymbol contains any non-.java and non-.class resources.
+     * Flag to indicate the API element in question is for a preview API.
      */
-    public static final long HAS_RESOURCE = 1L<<56;
+    public static final long PREVIEW_API = 1L<<56; //any Symbol kind
 
     /**
      * Flag for synthesized default constructors of anonymous classes that have an enclosing expression.
@@ -320,9 +330,9 @@
     public static final long BODY_ONLY_FINALIZE = 1L<<17; //blocks only
 
     /**
-     * Flag to indicate the given ParamSymbol has a user-friendly name filled.
+     * Flag to indicate the API element in question is for a preview API.
      */
-    public static final long NAME_FILLED = 1L<<58; //ParamSymbols only
+    public static final long PREVIEW_ESSENTIAL_API = 1L<<58; //any Symbol kind
 
     /** Modifier masks.
      */
@@ -441,7 +451,9 @@
         HAS_RESOURCE(Flags.HAS_RESOURCE),
         POTENTIALLY_AMBIGUOUS(Flags.POTENTIALLY_AMBIGUOUS),
         ANONCONSTR_BASED(Flags.ANONCONSTR_BASED),
-        NAME_FILLED(Flags.NAME_FILLED);
+        NAME_FILLED(Flags.NAME_FILLED),
+        PREVIEW_API(Flags.PREVIEW_API),
+        PREVIEW_ESSENTIAL_API(Flags.PREVIEW_ESSENTIAL_API);
 
         Flag(long flag) {
             this.value = flag;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java	Mon Oct 21 15:38:26 2019 +0200
@@ -122,6 +122,9 @@
             values.add(LintCategory.OPENS);
             values.add(LintCategory.MODULE);
             values.add(LintCategory.REMOVAL);
+            if (!options.isSet(Option.PREVIEW)) {
+                values.add(LintCategory.PREVIEW);
+            }
         }
 
         // Look for specific overrides
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java	Mon Oct 21 15:38:26 2019 +0200
@@ -27,7 +27,6 @@
 
 import com.sun.tools.javac.code.Lint.LintCategory;
 import com.sun.tools.javac.code.Source.Feature;
-import com.sun.tools.javac.comp.Infer;
 import com.sun.tools.javac.jvm.Target;
 import com.sun.tools.javac.resources.CompilerProperties.Errors;
 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
@@ -36,17 +35,14 @@
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.tools.javac.util.JCDiagnostic.Error;
 import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition;
+import com.sun.tools.javac.util.JCDiagnostic.Warning;
 import com.sun.tools.javac.util.Log;
 import com.sun.tools.javac.util.MandatoryWarningHandler;
-import com.sun.tools.javac.util.Name;
 import com.sun.tools.javac.util.Options;
 
 import javax.tools.JavaFileObject;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
 
 import static com.sun.tools.javac.main.Option.PREVIEW;
 
@@ -62,7 +58,7 @@
  */
 public class Preview {
 
-    /** flag: are preview featutres enabled */
+    /** flag: are preview features enabled */
     private final boolean enabled;
 
     /** the diag handler to manage preview feature usage diagnostics */
@@ -151,6 +147,10 @@
         }
     }
 
+    public void reportPreviewWarning(DiagnosticPosition pos, Warning warnKey) {
+        previewHandler.report(pos, warnKey);
+    }
+
     /**
      * Are preview features enabled?
      * @return true, if preview features are enabled.
@@ -206,4 +206,9 @@
     public void reportDeferredDiagnostics() {
         previewHandler.reportDeferredDiagnostic();
     }
+
+    public void clear() {
+        previewHandler.clear();
+    }
+
 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java	Mon Oct 21 15:38:26 2019 +0200
@@ -378,6 +378,10 @@
         return (flags_field & DEPRECATED_REMOVAL) != 0;
     }
 
+    public boolean isPreviewApi() {
+        return (flags_field & PREVIEW_API) != 0;
+    }
+
     public boolean isDeprecatableViaAnnotation() {
         switch (getKind()) {
             case LOCAL_VARIABLE:
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Mon Oct 21 15:38:26 2019 +0200
@@ -214,6 +214,7 @@
     public final Type documentedType;
     public final Type elementTypeType;
     public final Type functionalInterfaceType;
+    public final Type previewFeatureType;
 
     /** The symbol representing the length field of an array.
      */
@@ -570,6 +571,7 @@
         lambdaMetafactory = enterClass("java.lang.invoke.LambdaMetafactory");
         stringConcatFactory = enterClass("java.lang.invoke.StringConcatFactory");
         functionalInterfaceType = enterClass("java.lang.FunctionalInterface");
+        previewFeatureType = enterClass("jdk.internal.PreviewFeature");
 
         synthesizeEmptyInterfaceIfMissing(autoCloseableType);
         synthesizeEmptyInterfaceIfMissing(cloneableType);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java	Mon Oct 21 15:38:26 2019 +0200
@@ -364,12 +364,17 @@
                     && (toAnnotate.kind == MDL || toAnnotate.owner.kind != MTH)
                     && types.isSameType(c.type, syms.deprecatedType)) {
                 toAnnotate.flags_field |= (Flags.DEPRECATED | Flags.DEPRECATED_ANNOTATION);
-                Attribute fr = c.member(names.forRemoval);
-                if (fr instanceof Attribute.Constant) {
-                    Attribute.Constant v = (Attribute.Constant) fr;
-                    if (v.type == syms.booleanType && ((Integer) v.value) != 0) {
-                        toAnnotate.flags_field |= Flags.DEPRECATED_REMOVAL;
-                    }
+                if (isAttributeTrue(c.member(names.forRemoval))) {
+                    toAnnotate.flags_field |= Flags.DEPRECATED_REMOVAL;
+                }
+            }
+
+            // Note: @Deprecated has no effect on local variables and parameters
+            if (!c.type.isErroneous()
+                    && types.isSameType(c.type, syms.previewFeatureType)) {
+                toAnnotate.flags_field |= Flags.PREVIEW_API;
+                if (isAttributeTrue(c.member(names.essentialAPI))) {
+                    toAnnotate.flags_field |= Flags.PREVIEW_ESSENTIAL_API;
                 }
             }
         }
@@ -397,6 +402,16 @@
             toAnnotate.setDeclarationAttributes(attrs);
         }
     }
+    //where:
+        private boolean isAttributeTrue(Attribute attr) {
+            if (attr instanceof Attribute.Constant) {
+                Attribute.Constant v = (Attribute.Constant) attr;
+                if (v.type == syms.booleanType && ((Integer) v.value) != 0) {
+                    return true;
+                }
+            }
+            return false;
+        }
 
     /**
      * Attribute and store a semantic representation of the annotation tree {@code tree} into the
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Oct 21 15:38:26 2019 +0200
@@ -32,7 +32,7 @@
 import javax.lang.model.element.ElementKind;
 import javax.tools.JavaFileObject;
 
-import com.sun.source.tree.CaseTree.CaseKind;
+import com.sun.source.tree.CaseTree;
 import com.sun.source.tree.IdentifierTree;
 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
 import com.sun.source.tree.MemberSelectTree;
@@ -1486,8 +1486,8 @@
             // check that there are no duplicate case labels or default clauses.
             Set<Object> labels = new HashSet<>(); // The set of case labels.
             boolean hasDefault = false;      // Is there a default label?
-            @SuppressWarnings("removal")
-            CaseKind caseKind = null;
+            @SuppressWarnings("preview")
+            CaseTree.CaseKind caseKind = null;
             boolean wasError = false;
             for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) {
                 JCCase c = l.head;
@@ -4092,6 +4092,7 @@
                 chk.checkDeprecated(tree.pos(), env.info.scope.owner, sym);
                 chk.checkSunAPI(tree.pos(), sym);
                 chk.checkProfile(tree.pos(), sym);
+                chk.checkPreview(tree.pos(), sym);
             }
 
             // If symbol is a variable, check that its type and
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Mon Oct 21 15:38:26 2019 +0200
@@ -93,6 +93,7 @@
     private final Source source;
     private final Target target;
     private final Profile profile;
+    private final Preview preview;
     private final boolean warnOnAnyAccessToMembers;
 
     // The set of lint options currently in effect. It is initialized
@@ -139,6 +140,7 @@
         syntheticNameChar = target.syntheticNameChar();
 
         profile = Profile.instance(context);
+        preview = Preview.instance(context);
 
         boolean verboseDeprecated = lint.isEnabled(LintCategory.DEPRECATION);
         boolean verboseRemoval = lint.isEnabled(LintCategory.REMOVAL);
@@ -224,6 +226,23 @@
         }
     }
 
+    /** Warn about deprecated symbol.
+     *  @param pos        Position to be used for error reporting.
+     *  @param sym        The deprecated symbol.
+     */
+    void warnPreview(DiagnosticPosition pos, Symbol sym) {
+        warnPreview(pos, Warnings.IsPreview(sym));
+    }
+
+    /** Log a preview warning.
+     *  @param pos        Position to be used for error reporting.
+     *  @param msg        A Warning describing the problem.
+     */
+    public void warnPreview(DiagnosticPosition pos, Warning warnKey) {
+        if (!lint.isSuppressed(LintCategory.PREVIEW))
+            preview.reportPreviewWarning(pos, warnKey);
+    }
+
     /** Warn about unchecked operation.
      *  @param pos        Position to be used for error reporting.
      *  @param msg        A string describing the problem.
@@ -434,6 +453,13 @@
         localClassNameIndexes.clear();
     }
 
+    public void clear() {
+        deprecationHandler.clear();
+        removalHandler.clear();
+        uncheckedHandler.clear();
+        sunApiHandler.clear();
+    }
+
     public void putCompiled(ClassSymbol csym) {
         compiled.put(Pair.of(csym.packge().modle, csym.flatname), csym);
     }
@@ -3290,6 +3316,16 @@
         }
     }
 
+    void checkPreview(DiagnosticPosition pos, Symbol s) {
+        if ((s.flags() & PREVIEW_API) != 0) {
+            if ((s.flags() & PREVIEW_ESSENTIAL_API) != 0 && !preview.isEnabled()) {
+                log.error(pos, Errors.IsPreview(s));
+            } else {
+                deferredLintHandler.report(() -> warnPreview(pos, s));
+            }
+        }
+    }
+
 /* *************************************************************************
  * Check for recursive annotation elements.
  **************************************************************************/
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java	Mon Oct 21 15:38:26 2019 +0200
@@ -30,7 +30,6 @@
 import java.util.function.Function;
 import java.util.stream.Stream;
 
-import com.sun.source.tree.CaseTree.CaseKind;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Kinds.KindSelector;
 import com.sun.tools.javac.code.Scope.WriteableScope;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Oct 21 15:38:26 2019 +0200
@@ -2819,6 +2819,7 @@
                                     typeargtypes, allowBoxing,
                                     useVarargs);
         chk.checkDeprecated(pos, env.info.scope.owner, sym);
+        chk.checkPreview(pos, sym);
         return sym;
     }
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java	Mon Oct 21 15:38:26 2019 +0200
@@ -1156,19 +1156,26 @@
             JCAnnotation a = al.head;
             if (a.annotationType.type == syms.deprecatedType) {
                 sym.flags_field |= (Flags.DEPRECATED | Flags.DEPRECATED_ANNOTATION);
-                a.args.stream()
-                        .filter(e -> e.hasTag(ASSIGN))
-                        .map(e -> (JCAssign) e)
-                        .filter(assign -> TreeInfo.name(assign.lhs) == names.forRemoval)
-                        .findFirst()
-                        .ifPresent(assign -> {
-                            JCExpression rhs = TreeInfo.skipParens(assign.rhs);
-                            if (rhs.hasTag(LITERAL)
-                                    && Boolean.TRUE.equals(((JCLiteral) rhs).getValue())) {
-                                sym.flags_field |= DEPRECATED_REMOVAL;
-                            }
-                        });
+                setFlagIfAttributeTrue(a, sym, names.forRemoval, DEPRECATED_REMOVAL);
+            } else if (a.annotationType.type == syms.previewFeatureType) {
+                sym.flags_field |= Flags.PREVIEW_API;
+                setFlagIfAttributeTrue(a, sym, names.essentialAPI, PREVIEW_ESSENTIAL_API);
             }
         }
     }
+    //where:
+        private void setFlagIfAttributeTrue(JCAnnotation a, Symbol sym, Name attribute, long flag) {
+            a.args.stream()
+                    .filter(e -> e.hasTag(ASSIGN))
+                    .map(e -> (JCAssign) e)
+                    .filter(assign -> TreeInfo.name(assign.lhs) == attribute)
+                    .findFirst()
+                    .ifPresent(assign -> {
+                        JCExpression rhs = TreeInfo.skipParens(assign.rhs);
+                        if (rhs.hasTag(LITERAL)
+                                && Boolean.TRUE.equals(((JCLiteral) rhs).getValue())) {
+                            sym.flags_field |= flag;
+                        }
+                    });
+        }
 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java	Mon Oct 21 15:38:26 2019 +0200
@@ -44,6 +44,7 @@
 import java.nio.file.Path;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Objects;
@@ -173,6 +174,10 @@
     private long lastUsedTime = System.currentTimeMillis();
     protected long deferredCloseTimeout = 0;
 
+    public void clear() {
+        new HashSet<>(options.keySet()).forEach(k -> options.remove(k));
+    }
+
     protected ClassLoader getClassLoader(URL[] urls) {
         ClassLoader thisClassLoader = getClass().getClassLoader();
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Oct 21 15:38:26 2019 +0200
@@ -1395,20 +1395,27 @@
                     repeatable = proxy;
                 } else if (proxy.type.tsym == syms.deprecatedType.tsym) {
                     sym.flags_field |= (DEPRECATED | DEPRECATED_ANNOTATION);
-                    for (Pair<Name, Attribute> v : proxy.values) {
-                        if (v.fst == names.forRemoval && v.snd instanceof Attribute.Constant) {
-                            Attribute.Constant c = (Attribute.Constant)v.snd;
-                            if (c.type == syms.booleanType && ((Integer)c.value) != 0) {
-                                sym.flags_field |= DEPRECATED_REMOVAL;
-                            }
-                        }
-                    }
+                    setFlagIfAttributeTrue(proxy, sym, names.forRemoval, DEPRECATED_REMOVAL);
+                }  else if (proxy.type.tsym == syms.previewFeatureType.tsym) {
+                    sym.flags_field |= PREVIEW_API;
+                    setFlagIfAttributeTrue(proxy, sym, names.essentialAPI, PREVIEW_ESSENTIAL_API);
                 }
                 proxies.append(proxy);
             }
         }
         annotate.normal(new AnnotationCompleter(sym, proxies.toList()));
     }
+    //where:
+        private void setFlagIfAttributeTrue(CompoundAnnotationProxy proxy, Symbol sym, Name attribute, long flag) {
+            for (Pair<Name, Attribute> v : proxy.values) {
+                if (v.fst == attribute && v.snd instanceof Attribute.Constant) {
+                    Attribute.Constant c = (Attribute.Constant)v.snd;
+                    if (c.type == syms.booleanType && ((Integer)c.value) != 0) {
+                        sym.flags_field |= flag;
+                    }
+                }
+            }
+        }
 
     /** Read parameter annotations.
      */
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon Oct 21 15:38:26 2019 +0200
@@ -29,7 +29,7 @@
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
-import com.sun.source.tree.CaseTree.CaseKind;
+import com.sun.source.tree.CaseTree;
 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
 import com.sun.source.tree.ModuleTree.ModuleKind;
 
@@ -1432,8 +1432,8 @@
         }
         List<JCStatement> stats = null;
         JCTree body = null;
-        @SuppressWarnings("removal")
-        CaseKind kind;
+        @SuppressWarnings("preview")
+        CaseTree.CaseKind kind;
         switch (token.kind) {
             case ARROW:
                 checkSourceLevel(Feature.SWITCH_RULE);
@@ -2897,8 +2897,8 @@
                 nextToken();
                 checkSourceLevel(Feature.SWITCH_MULTIPLE_CASE_LABELS);
             };
-            @SuppressWarnings("removal")
-            CaseKind caseKind;
+            @SuppressWarnings("preview")
+            CaseTree.CaseKind caseKind;
             JCTree body = null;
             if (token.kind == ARROW) {
                 checkSourceLevel(Feature.SWITCH_RULE);
@@ -2922,8 +2922,8 @@
         }
         case DEFAULT: {
             nextToken();
-            @SuppressWarnings("removal")
-            CaseKind caseKind;
+            @SuppressWarnings("preview")
+            CaseTree.CaseKind caseKind;
             JCTree body = null;
             if (token.kind == ARROW) {
                 checkSourceLevel(Feature.SWITCH_RULE);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Oct 21 15:38:26 2019 +0200
@@ -1775,6 +1775,14 @@
     {0} in {1} has been deprecated and marked for removal
 
 # 0: symbol
+compiler.warn.is.preview=\
+    {0} is an API that is part of a preview feature
+
+# 0: symbol
+compiler.err.is.preview=\
+    {0} is an API that is part of a preview feature
+
+# 0: symbol
 compiler.warn.has.been.deprecated.module=\
     module {0} has been deprecated
 
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java	Mon Oct 21 15:38:26 2019 +0200
@@ -47,7 +47,6 @@
 
 import javax.tools.JavaFileManager.Location;
 
-import com.sun.source.tree.CaseTree.CaseKind;
 import com.sun.source.tree.ModuleTree.ModuleKind;
 import com.sun.tools.javac.code.Directive.ExportsDirective;
 import com.sun.tools.javac.code.Directive.OpensDirective;
@@ -1250,17 +1249,17 @@
     public static class JCCase extends JCStatement implements CaseTree {
         //as CaseKind is deprecated for removal (as it is part of a preview feature),
         //using indirection through these fields to avoid unnecessary @SuppressWarnings:
-        @SuppressWarnings("removal")
+        @SuppressWarnings("preview")
         public static final CaseKind STATEMENT = CaseKind.STATEMENT;
-        @SuppressWarnings("removal")
+        @SuppressWarnings("preview")
         public static final CaseKind RULE = CaseKind.RULE;
-        @SuppressWarnings("removal")
+        @SuppressWarnings("preview")
         public final CaseKind caseKind;
         public List<JCExpression> pats;
         public List<JCStatement> stats;
         public JCTree body;
         public boolean completesNormally;
-        protected JCCase(@SuppressWarnings("removal") CaseKind caseKind, List<JCExpression> pats,
+        protected JCCase(@SuppressWarnings("preview") CaseKind caseKind, List<JCExpression> pats,
                          List<JCStatement> stats, JCTree body) {
             Assert.checkNonNull(pats);
             Assert.check(pats.isEmpty() || pats.head != null);
@@ -1277,18 +1276,18 @@
         @Override @DefinedBy(Api.COMPILER_TREE)
         public JCExpression getExpression() { return pats.head; }
         @Override @DefinedBy(Api.COMPILER_TREE)
-        @SuppressWarnings("removal")
+        @SuppressWarnings("preview")
         public List<JCExpression> getExpressions() { return pats; }
         @Override @DefinedBy(Api.COMPILER_TREE)
-        @SuppressWarnings("removal")
+        @SuppressWarnings("preview")
         public List<JCStatement> getStatements() {
             return caseKind == CaseKind.STATEMENT ? stats : null;
         }
         @Override @DefinedBy(Api.COMPILER_TREE)
-        @SuppressWarnings("removal")
+        @SuppressWarnings("preview")
         public JCTree getBody() { return body; }
         @Override @DefinedBy(Api.COMPILER_TREE)
-        @SuppressWarnings("removal")
+        @SuppressWarnings("preview")
         public CaseKind getCaseKind() {
             return caseKind;
         }
@@ -1305,7 +1304,7 @@
     /**
      * A "switch ( ) { }" construction.
      */
-    @SuppressWarnings("removal")
+    @SuppressWarnings("preview")
     public static class JCSwitchExpression extends JCPolyExpression implements SwitchExpressionTree {
         public JCExpression selector;
         public List<JCCase> cases;
@@ -1586,7 +1585,7 @@
     /**
      * A break-with from a switch expression.
      */
-    @SuppressWarnings("removal")
+    @SuppressWarnings("preview")
     public static class JCYield extends JCStatement implements YieldTree {
         public JCExpression value;
         public JCTree target;
@@ -3105,7 +3104,7 @@
         JCLabeledStatement Labelled(Name label, JCStatement body);
         JCSwitch Switch(JCExpression selector, List<JCCase> cases);
         JCSwitchExpression SwitchExpression(JCExpression selector, List<JCCase> cases);
-        JCCase Case(@SuppressWarnings("removal") CaseKind caseKind, List<JCExpression> pat,
+        JCCase Case(@SuppressWarnings("preview") CaseTree.CaseKind caseKind, List<JCExpression> pat,
                     List<JCStatement> stats, JCTree body);
         JCSynchronized Synchronized(JCExpression lock, JCBlock body);
         JCTry Try(JCBlock body, List<JCCatch> catchers, JCBlock finalizer);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java	Mon Oct 21 15:38:26 2019 +0200
@@ -27,7 +27,6 @@
 
 import java.io.*;
 
-import com.sun.source.tree.CaseTree.CaseKind;
 import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
 import com.sun.source.tree.ModuleTree.ModuleKind;
 import com.sun.tools.javac.code.*;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java	Mon Oct 21 15:38:26 2019 +0200
@@ -144,7 +144,7 @@
     }
 
     @DefinedBy(Api.COMPILER_TREE)
-    @SuppressWarnings("removal")
+    @SuppressWarnings("preview")
     public JCTree visitYield(YieldTree node, P p) {
         JCYield t = (JCYield) node;
         JCExpression value = copy(t.value, p);
@@ -380,7 +380,7 @@
     }
 
     @DefinedBy(Api.COMPILER_TREE)
-    @SuppressWarnings("removal")
+    @SuppressWarnings("preview")
     public JCTree visitSwitchExpression(SwitchExpressionTree node, P p) {
         JCSwitchExpression t = (JCSwitchExpression) node;
         JCExpression selector = copy(t.selector, p);
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java	Mon Oct 21 15:38:26 2019 +0200
@@ -27,7 +27,7 @@
 
 import java.util.Iterator;
 
-import com.sun.source.tree.CaseTree.CaseKind;
+import com.sun.source.tree.CaseTree;
 import com.sun.source.tree.ModuleTree.ModuleKind;
 import com.sun.source.tree.Tree.Kind;
 import com.sun.tools.javac.code.*;
@@ -274,7 +274,7 @@
         return tree;
     }
 
-    public JCCase Case(@SuppressWarnings("removal") CaseKind caseKind, List<JCExpression> pats,
+    public JCCase Case(@SuppressWarnings("preview") CaseTree.CaseKind caseKind, List<JCExpression> pats,
                        List<JCStatement> stats, JCTree body) {
         JCCase tree = new JCCase(caseKind, pats, stats, body);
         tree.pos = pos;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/MandatoryWarningHandler.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/MandatoryWarningHandler.java	Mon Oct 21 15:38:26 2019 +0200
@@ -186,18 +186,18 @@
     /**
      * The log to which to report warnings.
      */
-    private Log log;
+    private final Log log;
 
     /**
      * Whether or not to report individual warnings, or simply to report a
      * single aggregate warning at the end of the compilation.
      */
-    private boolean verbose;
+    private final boolean verbose;
 
     /**
      * The common prefix for all I18N message keys generated by this handler.
      */
-    private String prefix;
+    private final String prefix;
 
     /**
      * A set containing the names of the source files for which specific
@@ -262,4 +262,11 @@
         else
             log.note(file, new Note("compiler", msg, args));
     }
+
+    public void clear() {
+        sourcesWithReportedWarnings = null;
+        deferredDiagnosticKind = null;
+        deferredDiagnosticSource = null;
+        deferredDiagnosticArg = null;
+    }
 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java	Mon Oct 21 15:38:26 2019 +0200
@@ -86,6 +86,7 @@
     public final Name error;
     public final Name finalize;
     public final Name forRemoval;
+    public final Name essentialAPI;
     public final Name getClass;
     public final Name hasNext;
     public final Name hashCode;
@@ -236,6 +237,7 @@
         error = fromString("<error>");
         finalize = fromString("finalize");
         forRemoval = fromString("forRemoval");
+        essentialAPI = fromString("essentialAPI");
         getClass = fromString("getClass");
         hasNext = fromString("hasNext");
         hashCode = fromString("hashCode");
--- a/test/jdk/java/lang/String/Formatted.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/test/jdk/java/lang/String/Formatted.java	Mon Oct 21 15:38:26 2019 +0200
@@ -25,7 +25,8 @@
  * @test
  * bug 8203444
  * @summary Unit tests for instance versions of String#format
- * @run main Formatted
+ * @compile --enable-preview -source 14 Formatted.java
+ * @run main/othervm --enable-preview Formatted
  */
 
 import java.util.Locale;
--- a/test/jdk/java/lang/String/StripIndent.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/test/jdk/java/lang/String/StripIndent.java	Mon Oct 21 15:38:26 2019 +0200
@@ -25,7 +25,8 @@
  * @test
  * @bug 8223775
  * @summary This exercises String#stripIndent patterns and limits.
- * @run main StripIndent
+ * @compile --enable-preview -source 14 StripIndent.java
+ * @run main/othervm --enable-preview StripIndent
  */
 
 public class StripIndent {
--- a/test/jdk/java/lang/String/TranslateEscapes.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/test/jdk/java/lang/String/TranslateEscapes.java	Mon Oct 21 15:38:26 2019 +0200
@@ -25,7 +25,8 @@
  * @test
  * @bug 8223780
  * @summary This exercises String#translateEscapes patterns and limits.
- * @run main TranslateEscapes
+ * @compile --enable-preview -source 14 TranslateEscapes.java
+ * @run main/othervm --enable-preview TranslateEscapes
  */
 
 public class TranslateEscapes {
--- a/test/langtools/tools/javac/diags/examples.not-yet.txt	Mon Oct 21 15:11:44 2019 +0200
+++ b/test/langtools/tools/javac/diags/examples.not-yet.txt	Mon Oct 21 15:38:26 2019 +0200
@@ -11,6 +11,7 @@
 compiler.err.invalid.repeatable.annotation.invalid.value # "can't" happen
 compiler.err.invalid.repeatable.annotation.multiple.values # can't happen
 compiler.err.io.exception                               # (javah.JavahTask?)
+compiler.err.is.preview                                 # difficult to produce reliably despite future changes to java.base
 compiler.err.limit.code                                 # Code
 compiler.err.limit.code.too.large.for.try.stmt          # Gen
 compiler.err.limit.dimensions                           # Gen
@@ -111,6 +112,7 @@
 compiler.warn.illegal.char.for.encoding
 compiler.warn.incubating.modules                        # requires adjusted classfile
 compiler.warn.invalid.archive.file
+compiler.warn.is.preview                                # difficult to produce reliably despite future changes to java.base
 compiler.warn.override.bridge
 compiler.warn.position.overflow                         # CRTable: caused by files with long lines >= 1024 chars
 compiler.warn.proc.type.already.exists                  # JavacFiler: just mentioned in TODO
--- a/test/langtools/tools/javac/lib/combo/ComboInstance.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/test/langtools/tools/javac/lib/combo/ComboInstance.java	Mon Oct 21 15:38:26 2019 +0200
@@ -23,6 +23,7 @@
 
 package combo;
 
+import java.lang.reflect.Method;
 import javax.tools.StandardJavaFileManager;
 import java.util.Optional;
 
@@ -57,6 +58,14 @@
             env.info().lastError = Optional.of(ex);
         } finally {
             this.env = null;
+            try {
+                Class<?> fmClass = env.fileManager().getClass();
+                Method clear = fmClass.getMethod("clear");
+                clear.setAccessible(true);
+                clear.invoke(env.fileManager());
+            } catch (Exception ex) {
+                throw new IllegalStateException(ex);
+            }
         }
     }
 
@@ -125,4 +134,4 @@
             return success;
         }
     }
-}
\ No newline at end of file
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/preview/PreviewErrors.java	Mon Oct 21 15:38:26 2019 +0200
@@ -0,0 +1,274 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8226585
+ * @summary Verify behavior w.r.t. preview feature API errors and warnings
+ * @library /tools/lib /tools/javac/lib
+ * @modules
+ *      java.base/jdk.internal
+ *      jdk.compiler/com.sun.tools.javac.api
+ *      jdk.compiler/com.sun.tools.javac.file
+ *      jdk.compiler/com.sun.tools.javac.main
+ *      jdk.compiler/com.sun.tools.javac.util
+ * @build toolbox.ToolBox toolbox.JavacTask
+ * @build combo.ComboTestHelper
+ * @compile --enable-preview -source ${jdk.version} PreviewErrors.java
+ * @run main/othervm --enable-preview PreviewErrors
+ */
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import combo.ComboInstance;
+import combo.ComboParameter;
+import combo.ComboTask;
+import combo.ComboTestHelper;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.stream.Collectors;
+import javax.tools.Diagnostic;
+
+import jdk.internal.PreviewFeature;
+
+import toolbox.JavacTask;
+import toolbox.ToolBox;
+
+public class PreviewErrors extends ComboInstance<PreviewErrors> {
+
+    protected ToolBox tb;
+
+    PreviewErrors() {
+        super();
+        tb = new ToolBox();
+    }
+
+    public static void main(String... args) throws Exception {
+        new ComboTestHelper<PreviewErrors>()
+                .withDimension("ESSENTIAL", (x, essential) -> x.essential = essential, EssentialAPI.values())
+                .withDimension("PREVIEW", (x, preview) -> x.preview = preview, Preview.values())
+                .withDimension("LINT", (x, lint) -> x.lint = lint, Lint.values())
+                .withDimension("SUPPRESS", (x, suppress) -> x.suppress = suppress, Suppress.values())
+                .withDimension("FROM", (x, from) -> x.from = from, PreviewFrom.values())
+                .run(PreviewErrors::new);
+    }
+
+    private EssentialAPI essential;
+    private Preview preview;
+    private Lint lint;
+    private Suppress suppress;
+    private PreviewFrom from;
+
+    @Override
+    public void doWork() throws IOException {
+        Path base = Paths.get(".");
+        Path src = base.resolve("src");
+        Path srcJavaBase = src.resolve("java.base");
+        Path classes = base.resolve("classes");
+        Path classesJavaBase = classes.resolve("java.base");
+
+        Files.createDirectories(classesJavaBase);
+
+        String previewAPI = """
+                            package preview.api;
+                            public class Extra {
+                                @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.${preview}
+                                                             ${essential})
+                                public static void test() { }
+                                @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.${preview}
+                                                             ${essential})
+                                public static class Clazz {}
+                            }
+                            """.replace("${preview}", PreviewFeature.Feature.values()[0].name())
+                               .replace("${essential}", essential.expand(null));
+
+         if (from == PreviewFrom.CLASS) {
+            tb.writeJavaFiles(srcJavaBase, previewAPI);
+
+            new JavacTask(tb)
+                    .outdir(classesJavaBase)
+                    .options("--patch-module", "java.base=" + srcJavaBase.toString())
+                    .files(tb.findJavaFiles(srcJavaBase))
+                    .run()
+                    .writeAll();
+         }
+
+        ComboTask task = newCompilationTask()
+                .withSourceFromTemplate("""
+                                        package test;
+                                        public class Test {
+                                            #{SUPPRESS}
+                                            public void test() {
+                                                preview.api.Extra.test();
+                                                preview.api.Extra.Clazz c;
+                                            }
+                                        }
+                                        """)
+                .withOption("-XDrawDiagnostics")
+                .withOption("-source")
+                .withOption(String.valueOf(Runtime.version().feature()));
+
+        if (from == PreviewFrom.CLASS) {
+            task.withOption("--patch-module")
+                .withOption("java.base=" + classesJavaBase.toString())
+                .withOption("--add-exports")
+                .withOption("java.base/preview.api=ALL-UNNAMED");
+        } else {
+            task.withSourceFromTemplate("Extra", previewAPI)
+                .withOption("--add-exports")
+                .withOption("java.base/jdk.internal=ALL-UNNAMED");
+        }
+
+        if (preview.expand(null)!= null) {
+            task = task.withOption(preview.expand(null));
+        }
+
+        if (lint.expand(null) != null) {
+            task = task.withOption(lint.expand(null));
+        }
+
+        task.generate(result -> {
+                Set<String> actual = Arrays.stream(Diagnostic.Kind.values())
+                                            .flatMap(kind -> result.diagnosticsForKind(kind).stream())
+                                            .map(d -> d.getLineNumber() + ":" + d.getColumnNumber() + ":" + d.getCode())
+                                            .collect(Collectors.toSet());
+                Set<String> expected;
+                boolean ok;
+                if (essential == EssentialAPI.YES) {
+                    if (preview == Preview.YES) {
+                        if (suppress == Suppress.YES) {
+                            expected = Set.of();
+                        } else if (lint == Lint.ENABLE_PREVIEW) {
+                            expected = Set.of("5:26:compiler.warn.is.preview", "6:26:compiler.warn.is.preview");
+                        } else {
+                            expected = Set.of("-1:-1:compiler.note.preview.filename",
+                                              "-1:-1:compiler.note.preview.recompile");
+                        }
+                        ok = true;
+                    } else {
+                        expected = Set.of("5:26:compiler.err.is.preview", "6:26:compiler.err.is.preview");
+                        ok = false;
+                    }
+                } else {
+                    if (suppress == Suppress.YES) {
+                        expected = Set.of();
+                    } else if ((preview == Preview.YES && (lint == Lint.NONE || lint == Lint.DISABLE_PREVIEW)) ||
+                               (preview == Preview.NO && lint == Lint.DISABLE_PREVIEW)) {
+                        expected = Set.of("-1:-1:compiler.note.preview.filename",
+                                          "-1:-1:compiler.note.preview.recompile");
+                    } else {
+                        expected = Set.of("5:26:compiler.warn.is.preview", "6:26:compiler.warn.is.preview");
+                    }
+                    ok = true;
+                }
+                if (ok) {
+                    if (!result.get().iterator().hasNext()) {
+                        throw new IllegalStateException("Did not succeed as expected." + actual);
+                    }
+                } else {
+                    if (result.get().iterator().hasNext()) {
+                        throw new IllegalStateException("Succeed unexpectedly.");
+                    }
+                }
+                if (!expected.equals(actual)) {
+                    throw new IllegalStateException("Unexpected output for " + essential + ", " + preview + ", " + lint + ", " + suppress + ", " + from + ": actual: \"" + actual + "\", expected: \"" + expected + "\"");
+                }
+            });
+    }
+
+    public enum EssentialAPI implements ComboParameter {
+        YES(", essentialAPI=true"),
+        NO(", essentialAPI=false");
+
+        private final String code;
+
+        private EssentialAPI(String code) {
+            this.code = code;
+        }
+
+        public String expand(String optParameter) {
+            return code;
+        }
+    }
+
+    public enum Preview implements ComboParameter {
+        YES("--enable-preview"),
+        NO(null);
+
+        private final String opt;
+
+        private Preview(String opt) {
+            this.opt = opt;
+        }
+
+        public String expand(String optParameter) {
+            return opt;
+        }
+    }
+
+    public enum Lint implements ComboParameter {
+        NONE(null),
+        ENABLE_PREVIEW("-Xlint:preview"),
+        DISABLE_PREVIEW("-Xlint:-preview");
+
+        private final String opt;
+
+        private Lint(String opt) {
+            this.opt = opt;
+        }
+
+        public String expand(String optParameter) {
+            return opt;
+        }
+    }
+
+    public enum Suppress implements ComboParameter {
+        YES("@SuppressWarnings(\"preview\")"),
+        NO("");
+
+        private final String code;
+
+        private Suppress(String code) {
+            this.code = code;
+        }
+
+        public String expand(String optParameter) {
+            return code;
+        }
+    }
+
+    public enum PreviewFrom implements ComboParameter {
+        CLASS,
+        SOURCE;
+
+        private PreviewFrom() {
+        }
+
+        public String expand(String optParameter) {
+            throw new IllegalStateException();
+        }
+    }
+}
--- a/test/langtools/tools/javac/tree/NoPrivateTypesExported.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/test/langtools/tools/javac/tree/NoPrivateTypesExported.java	Mon Oct 21 15:38:26 2019 +0200
@@ -177,6 +177,7 @@
 
             if (annotationElement.getAnnotation(Documented.class) == null) {
                 note("Ignoring undocumented annotation: " + mirror.getAnnotationType());
+                continue;
             }
 
             verifyTypeAcceptable(mirror.getAnnotationType(), acceptable);
--- a/test/langtools/tools/jdeps/listdeps/ListModuleDeps.java	Mon Oct 21 15:11:44 2019 +0200
+++ b/test/langtools/tools/jdeps/listdeps/ListModuleDeps.java	Mon Oct 21 15:38:26 2019 +0200
@@ -92,6 +92,7 @@
     public Object[][] jdkModules() {
         return new Object[][]{
             {"jdk.compiler", new String[]{
+                                "java.base/jdk.internal",
                                 "java.base/jdk.internal.jmod",
                                 "java.base/jdk.internal.misc",
                                 "java.base/sun.reflect.annotation",