# HG changeset patch # User jlahoda # Date 1571665106 -7200 # Node ID ad69fd32778ebb6d4440d04ee2984362be129210 # Parent 14e098407bb01b0e6118e42956afb6ba87648da2 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 diff -r 14e098407bb0 -r ad69fd32778e make/CompileInterimLangtools.gmk --- 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 diff -r 14e098407bb0 -r ad69fd32778e make/Docs.gmk --- 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) \ # diff -r 14e098407bb0 -r ad69fd32778e make/jdk/src/classes/build/tools/taglet/Preview.java --- /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 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 tags, Element elem) { + UnknownInlineTagTree previewTag = (UnknownInlineTagTree) tags.get(0); + List 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 isSummary = + el -> el.getClassName().endsWith("HtmlDocletWriter") && + el.getMethodName().equals("addSummaryComment"); + if (Arrays.stream(stackTrace).anyMatch(isSummary)) { + return "
" + summary + "

"; + } + return "
" + details + "

"; + } +} + diff -r 14e098407bb0 -r ad69fd32778e src/java.base/share/classes/java/lang/String.java --- 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 text blocks, 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 text blocks, 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. *

@@ -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 text blocks, 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(); } diff -r 14e098407bb0 -r ad69fd32778e src/java.base/share/classes/jdk/internal/PreviewFeature.java --- /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 + * preview feature. 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; + } +} diff -r 14e098407bb0 -r ad69fd32778e src/java.base/share/classes/module-info.java --- 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, diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/source/tree/CaseTree.java --- 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 switch expressions, 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 getExpressions(); /** @@ -78,6 +86,14 @@ List getStatements(); /** + * {@preview Associated with switch expressions, a preview feature of + * the Java language. + * + * This method is associated with switch expressions, 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 switch expressions, 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 switch expressions, 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: *

* * @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 : }. diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/source/tree/SwitchExpressionTree.java --- 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 switch expressions, 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. diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java --- 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 switch expressions, 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 switch expressions, 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); diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java --- 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 switch expressions, 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 switch expressions, 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); } diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/source/tree/YieldTree.java --- 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 switch expressions, 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 { /** diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java --- 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 switch expressions, 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); } diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java --- 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 switch expressions, 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 switch expressions, 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); } diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTaskPool.java --- 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(); diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java --- 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; diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java --- 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 diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java --- 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(); + } + } diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java --- 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: diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java --- 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); diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java --- 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 diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java --- 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 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 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 diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java --- 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. **************************************************************************/ diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Lower.java --- 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; diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java --- 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; } diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java --- 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; + } + }); + } } diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java --- 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(); diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java --- 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 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 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. */ diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java --- 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 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); diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties --- 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 diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java --- 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 pats; public List stats; public JCTree body; public boolean completesNormally; - protected JCCase(@SuppressWarnings("removal") CaseKind caseKind, List pats, + protected JCCase(@SuppressWarnings("preview") CaseKind caseKind, List pats, List 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 getExpressions() { return pats; } @Override @DefinedBy(Api.COMPILER_TREE) - @SuppressWarnings("removal") + @SuppressWarnings("preview") public List 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 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 cases); JCSwitchExpression SwitchExpression(JCExpression selector, List cases); - JCCase Case(@SuppressWarnings("removal") CaseKind caseKind, List pat, + JCCase Case(@SuppressWarnings("preview") CaseTree.CaseKind caseKind, List pat, List stats, JCTree body); JCSynchronized Synchronized(JCExpression lock, JCBlock body); JCTry Try(JCBlock body, List catchers, JCBlock finalizer); diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/tools/javac/tree/Pretty.java --- 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.*; diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java --- 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); diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java --- 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 pats, + public JCCase Case(@SuppressWarnings("preview") CaseTree.CaseKind caseKind, List pats, List stats, JCTree body) { JCCase tree = new JCCase(caseKind, pats, stats, body); tree.pos = pos; diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/tools/javac/util/MandatoryWarningHandler.java --- 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; + } } diff -r 14e098407bb0 -r ad69fd32778e src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java --- 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(""); finalize = fromString("finalize"); forRemoval = fromString("forRemoval"); + essentialAPI = fromString("essentialAPI"); getClass = fromString("getClass"); hasNext = fromString("hasNext"); hashCode = fromString("hashCode"); diff -r 14e098407bb0 -r ad69fd32778e test/jdk/java/lang/String/Formatted.java --- 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; diff -r 14e098407bb0 -r ad69fd32778e test/jdk/java/lang/String/StripIndent.java --- 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 { diff -r 14e098407bb0 -r ad69fd32778e test/jdk/java/lang/String/TranslateEscapes.java --- 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 { diff -r 14e098407bb0 -r ad69fd32778e test/langtools/tools/javac/diags/examples.not-yet.txt --- 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 diff -r 14e098407bb0 -r ad69fd32778e test/langtools/tools/javac/lib/combo/ComboInstance.java --- 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 +} diff -r 14e098407bb0 -r ad69fd32778e test/langtools/tools/javac/preview/PreviewErrors.java --- /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 { + + protected ToolBox tb; + + PreviewErrors() { + super(); + tb = new ToolBox(); + } + + public static void main(String... args) throws Exception { + new ComboTestHelper() + .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 actual = Arrays.stream(Diagnostic.Kind.values()) + .flatMap(kind -> result.diagnosticsForKind(kind).stream()) + .map(d -> d.getLineNumber() + ":" + d.getColumnNumber() + ":" + d.getCode()) + .collect(Collectors.toSet()); + Set 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(); + } + } +} diff -r 14e098407bb0 -r ad69fd32778e test/langtools/tools/javac/tree/NoPrivateTypesExported.java --- 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); diff -r 14e098407bb0 -r ad69fd32778e test/langtools/tools/jdeps/listdeps/ListModuleDeps.java --- 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",