Updating javac behavior w.r.t. preview API. Based on darcy's patch.
--- a/make/CompileInterimLangtools.gmk Thu Sep 05 12:39:48 2019 +0200
+++ b/make/CompileInterimLangtools.gmk Thu Sep 12 17:47:24 2019 +0200
@@ -49,6 +49,14 @@
TARGETS += $(patsubst %, $(BUILDTOOLS_OUTPUTDIR)/gensrc/%/module-info.java, \
$(INTERIM_LANGTOOLS_MODULES))
+$(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim/jdk/internal/PreviewFeature.java: \
+ $(TOPDIR)/src/java.base/share/classes/jdk/internal/PreviewFeature.java
+ $(call LogInfo, Copying PreviewFeature.java)
+ $(call MakeDir, $(@D))
+ $(CP) $< $@
+
+TARGETS += $(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim/jdk/internal/PreviewFeature.java
+
################################################################################
# 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,6 +80,8 @@
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, \
))
--- a/src/java.base/share/classes/java/lang/String.java Thu Sep 05 12:39:48 2019 +0200
+++ b/src/java.base/share/classes/java/lang/String.java Thu Sep 12 17:47:24 2019 +0200
@@ -2963,10 +2963,11 @@
*
* @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.
+ * @preview 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) {
@@ -3080,10 +3081,11 @@
*
* @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.
+ * @preview 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 "";
@@ -3324,10 +3326,11 @@
*
* @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.
+ * @preview 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 Thu Sep 12 17:47:24 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 13
+ */
+// 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 Thu Sep 05 12:39:48 2019 +0200
+++ b/src/java.base/share/classes/module-info.java Thu Sep 12 17:47:24 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 Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/CaseTree.java Thu Sep 12 17:47:24 2019 +0200
@@ -61,11 +61,11 @@
* @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();
/**
@@ -86,11 +86,11 @@
* @return case value or null
* @since 12
*
- * @deprecated This method is modeling a rule case,
+ * @preview 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;
}
@@ -101,11 +101,12 @@
* @return the kind of this case
* @since 12
*
- * @deprecated This method is used to model a rule case,
+ * @preview 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;
}
@@ -119,11 +120,12 @@
*
* @since 12
*
- * @deprecated This enum is used to model a rule case,
+ * @preview 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 Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/SwitchExpressionTree.java Thu Sep 12 17:47:24 2019 +0200
@@ -41,11 +41,11 @@
*
* @since 12
*
- * @deprecated This method is modeling switch expressions,
+ * @preview 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 Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java Thu Sep 12 17:47:24 2019 +0200
@@ -244,13 +244,13 @@
*
* @since 12
*
- * @deprecated
+ * @preview
* 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),
/**
@@ -663,13 +663,13 @@
*
* @since 13
*
- * @deprecated
+ * @preview
* 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 Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java Thu Sep 12 17:47:24 2019 +0200
@@ -361,13 +361,13 @@
* @return a result value
* @since 12
*
- * @deprecated
+ * @preview
* 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);
/**
@@ -563,12 +563,12 @@
* @return a result value
* @since 13
*
- * @deprecated
+ * @preview
* 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 Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/YieldTree.java Thu Sep 12 17:47:24 2019 +0200
@@ -37,11 +37,11 @@
*
* @since 13
*
- * @deprecated This class is modeling yield from switch expressions,
+ * @preview 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 Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java Thu Sep 12 17:47:24 2019 +0200
@@ -270,14 +270,14 @@
* @param p {@inheritDoc}
* @return the result of {@code defaultAction}
*
- * @deprecated
+ * @preview
* 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 +791,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 Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java Thu Sep 12 17:47:24 2019 +0200
@@ -341,14 +341,14 @@
* @param p {@inheritDoc}
* @return the result of scanning
*
- * @deprecated
+ * @preview
* 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,7 +363,7 @@
* @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)
@@ -942,14 +942,14 @@
* @param p {@inheritDoc}
* @return the result of scanning
*
- * @deprecated
+ * @preview
* 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/code/Flags.java Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java Thu Sep 12 17:47:24 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,8 @@
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);
Flag(long flag) {
this.value = flag;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java Thu Sep 12 17:47:24 2019 +0200
@@ -122,6 +122,10 @@
values.add(LintCategory.OPENS);
values.add(LintCategory.MODULE);
values.add(LintCategory.REMOVAL);
+ Preview preview = Preview.instance(context);
+ if (!preview.isEnabled()) {
+ values.add(LintCategory.PREVIEW);
+ }
}
// Look for specific overrides
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java Thu Sep 12 17:47:24 2019 +0200
@@ -27,7 +27,7 @@
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.comp.Check;
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 +36,11 @@
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.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,12 +56,9 @@
*/
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 */
- private final MandatoryWarningHandler previewHandler;
-
/** test flag: should all features be considered as preview features? */
private final boolean forcePreview;
@@ -75,8 +66,7 @@
private final Map<Integer, Source> majorVersionToSource;
- private final Lint lint;
- private final Log log;
+ private final Check check;
private static final Context.Key<Preview> previewKey = new Context.Key<>();
@@ -92,10 +82,7 @@
context.put(previewKey, this);
Options options = Options.instance(context);
enabled = options.isSet(PREVIEW);
- log = Log.instance(context);
- lint = Lint.instance(context);
- this.previewHandler =
- new MandatoryWarningHandler(log, lint.isEnabled(LintCategory.PREVIEW), true, "preview", LintCategory.PREVIEW);
+ check = Check.instance(context);
forcePreview = options.isSet("forcePreview");
majorVersionToSource = initMajorVersionToSourceMap();
}
@@ -131,11 +118,9 @@
public void warnPreview(DiagnosticPosition pos, Feature feature) {
Assert.check(isEnabled());
Assert.check(isPreview(feature));
- if (!lint.isSuppressed(LintCategory.PREVIEW)) {
- previewHandler.report(pos, feature.isPlural() ?
+ check.warnPreview(pos, feature.isPlural() ?
Warnings.PreviewFeatureUsePlural(feature.nameFragment()) :
Warnings.PreviewFeatureUse(feature.nameFragment()));
- }
}
/**
@@ -145,10 +130,8 @@
*/
public void warnPreview(JavaFileObject classfile, int majorVersion) {
Assert.check(isEnabled());
- if (!lint.isSuppressed(LintCategory.PREVIEW)) {
- previewHandler.report(null,
+ check.warnPreview(null,
Warnings.PreviewFeatureUseClassfile(classfile, majorVersionToSource.get(majorVersion).name));
- }
}
/**
@@ -200,10 +183,4 @@
return Errors.PreviewFeatureDisabledClassfile(classfile, majorVersionToSource.get(majorVersion).name);
}
- /**
- * Report any deferred diagnostics.
- */
- public void reportDeferredDiagnostics() {
- previewHandler.reportDeferredDiagnostic();
- }
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java Thu Sep 12 17:47:24 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 Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java Thu Sep 12 17:47:24 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/Attr.java Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Thu Sep 12 17:47:24 2019 +0200
@@ -1486,7 +1486,7 @@
// 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")
+ @SuppressWarnings("preview")
CaseKind caseKind = null;
boolean wasError = false;
for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) {
@@ -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 Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Thu Sep 12 17:47:24 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,10 +140,12 @@
syntheticNameChar = target.syntheticNameChar();
profile = Profile.instance(context);
+ preview = Preview.instance(context);
boolean verboseDeprecated = lint.isEnabled(LintCategory.DEPRECATION);
boolean verboseRemoval = lint.isEnabled(LintCategory.REMOVAL);
boolean verboseUnchecked = lint.isEnabled(LintCategory.UNCHECKED);
+ boolean verbosePreview = lint.isEnabled(LintCategory.PREVIEW);
boolean enforceMandatoryWarnings = true;
deprecationHandler = new MandatoryWarningHandler(log, verboseDeprecated,
@@ -153,6 +156,8 @@
enforceMandatoryWarnings, "unchecked", LintCategory.UNCHECKED);
sunApiHandler = new MandatoryWarningHandler(log, false,
enforceMandatoryWarnings, "sunapi", null);
+ previewHandler = new MandatoryWarningHandler(log, verbosePreview,
+ enforceMandatoryWarnings, "preview", null);
deferredLintHandler = DeferredLintHandler.instance(context);
}
@@ -182,6 +187,10 @@
*/
private MandatoryWarningHandler sunApiHandler;
+ /** A handler for messages about preview features.
+ */
+ private MandatoryWarningHandler previewHandler;
+
/** A handler for deferred lint warnings.
*/
private DeferredLintHandler deferredLintHandler;
@@ -224,6 +233,27 @@
}
}
+ /** Warn about deprecated symbol.
+ * @param pos Position to be used for error reporting.
+ * @param sym The deprecated symbol.
+ */
+ void warnPreview(DiagnosticPosition pos, Symbol sym) {
+ if ((sym.flags() & PREVIEW_ESSENTIAL_API) != 0) {
+ previewHandler.report(pos, Warnings.IsPreview(sym));
+ } else {
+ 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))
+ previewHandler.report(pos, warnKey);
+ }
+
/** Warn about unchecked operation.
* @param pos Position to be used for error reporting.
* @param msg A string describing the problem.
@@ -262,6 +292,7 @@
removalHandler.reportDeferredDiagnostic();
uncheckedHandler.reportDeferredDiagnostic();
sunApiHandler.reportDeferredDiagnostic();
+ previewHandler.reportDeferredDiagnostic();
}
@@ -3290,6 +3321,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/Resolve.java Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java Thu Sep 12 17:47:24 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 Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java Thu Sep 12 17:47:24 2019 +0200
@@ -433,7 +433,7 @@
Type attribImportType(JCTree tree, Env<AttrContext> env) {
Assert.check(completionEnabled);
Lint prevLint = chk.setLint(allowDeprecationOnImport ?
- lint : lint.suppress(LintCategory.DEPRECATION, LintCategory.REMOVAL));
+ lint : lint.suppress(LintCategory.DEPRECATION, LintCategory.REMOVAL, LintCategory.PREVIEW));
try {
// To prevent deep recursion, suppress completion of some
// types.
@@ -1168,6 +1168,8 @@
sym.flags_field |= DEPRECATED_REMOVAL;
}
});
+ } else if (a.annotationType.type == syms.previewFeatureType) {
+ sym.flags_field |= Flags.PREVIEW_API;
}
}
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java Thu Sep 12 17:47:24 2019 +0200
@@ -1403,6 +1403,16 @@
}
}
}
+ } else if (proxy.type.tsym == syms.previewFeatureType.tsym) {
+ for (Pair<Name, Attribute> v : proxy.values) {
+ if (v.fst == names.essentialAPI && v.snd instanceof Attribute.Constant) {
+ Attribute.Constant c = (Attribute.Constant)v.snd;
+ if (c.type == syms.booleanType && ((Integer)c.value) != 0) {
+ sym.flags_field |= PREVIEW_ESSENTIAL_API;
+ }
+ }
+ }
+ sym.flags_field |= PREVIEW_API;
}
proxies.append(proxy);
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Thu Sep 12 17:47:24 2019 +0200
@@ -1735,7 +1735,6 @@
log.warning(Warnings.ProcUseProcOrImplicit);
}
chk.reportDeferredDiagnostics();
- preview.reportDeferredDiagnostics();
if (log.compressedOutput) {
log.mandatoryNote(null, Notes.CompressedDiags);
}
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java Thu Sep 12 17:47:24 2019 +0200
@@ -1432,7 +1432,7 @@
}
List<JCStatement> stats = null;
JCTree body = null;
- @SuppressWarnings("removal")
+ @SuppressWarnings("preview")
CaseKind kind;
switch (token.kind) {
case ARROW:
@@ -2897,7 +2897,7 @@
nextToken();
checkSourceLevel(Feature.SWITCH_MULTIPLE_CASE_LABELS);
};
- @SuppressWarnings("removal")
+ @SuppressWarnings("preview")
CaseKind caseKind;
JCTree body = null;
if (token.kind == ARROW) {
@@ -2922,7 +2922,7 @@
}
case DEFAULT: {
nextToken();
- @SuppressWarnings("removal")
+ @SuppressWarnings("preview")
CaseKind caseKind;
JCTree body = null;
if (token.kind == ARROW) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Sep 12 17:47:24 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 Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java Thu Sep 12 17:47:24 2019 +0200
@@ -1250,17 +1250,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 +1277,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 +1305,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 +1586,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 +3105,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") 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/TreeCopier.java Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeCopier.java Thu Sep 12 17:47:24 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 Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeMaker.java Thu Sep 12 17:47:24 2019 +0200
@@ -274,7 +274,7 @@
return tree;
}
- public JCCase Case(@SuppressWarnings("removal") CaseKind caseKind, List<JCExpression> pats,
+ public JCCase Case(@SuppressWarnings("preview") 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/Names.java Thu Sep 05 12:39:48 2019 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java Thu Sep 12 17:47:24 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");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/preview/PreviewErrors.java Thu Sep 12 17:47:24 2019 +0200
@@ -0,0 +1,251 @@
+/*
+ * 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
+ * @modules
+ * java.base/jdk.internal
+ * jdk.compiler/com.sun.tools.javac.api
+ * jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.ToolBox toolbox.JavacTask
+ * @compile --enable-preview -source ${jdk.version} PreviewErrors.java
+ * @run main/othervm --enable-preview PreviewErrors
+ */
+
+import toolbox.JavacTask;
+import toolbox.Task;
+import toolbox.TestRunner;
+import toolbox.ToolBox;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import jdk.internal.PreviewFeature;
+
+public class PreviewErrors extends TestRunner {
+
+ protected ToolBox tb;
+
+ PreviewErrors() {
+ super(System.err);
+ tb = new ToolBox();
+ }
+
+ public static void main(String... args) throws Exception {
+ PreviewErrors t = new PreviewErrors();
+ t.runTests();
+ }
+
+ /**
+ * Run all methods annotated with @Test, and throw an exception if any
+ * errors are reported..
+ *
+ * @throws Exception if any errors occurred
+ */
+ protected void runTests() throws Exception {
+ runTests(m -> new Object[] { Paths.get(m.getName()) });
+ }
+
+ Path[] findJavaFiles(Path... paths) throws IOException {
+ return tb.findJavaFiles(paths);
+ }
+
+ @Test
+ public void essentialApi(Path base) throws Exception {
+ 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);
+
+ Path srcTest = src.resolve("test");
+ Path classesTest = classes.resolve("test");
+
+ Files.createDirectories(classesTest);
+
+ for (EssentialAPI essential : EssentialAPI.values()) {
+ tb.writeJavaFiles(srcJavaBase,
+ """
+ package java.lang;
+ public class Extra {
+ @jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.${preview}
+ ${essential})
+ public static void test() { }
+ }
+ """.replace("${preview}", PreviewFeature.Feature.values()[0].name())
+ .replace("${essential}", essential.code()));
+
+ new JavacTask(tb)
+ .outdir(classesJavaBase)
+ .options("--patch-module", "java.base=" + srcJavaBase.toString())
+ .files(findJavaFiles(srcJavaBase))
+ .run()
+ .writeAll();
+
+ for (Preview preview : Preview.values()) {
+ for (Lint lint : Lint.values()) {
+ for (Suppress suppress : Suppress.values()) {
+ tb.writeJavaFiles(srcTest,
+ """
+ package test;
+ public class Test {
+ ${suppress}
+ public void test() {
+ Extra.test();
+ }
+ }
+ """.replace("${suppress}", suppress.code()));
+
+ List<String> options = new ArrayList<>();
+
+ options.add("-XDrawDiagnostics");
+ options.add("--patch-module");
+ options.add("java.base=" + classesJavaBase.toString());
+ options.add("-source");
+ options.add(String.valueOf(Runtime.version().feature()));
+
+ if (preview.opt() != null) {
+ options.add(preview.opt());
+ }
+
+ if (lint.opt() != null) {
+ options.add(lint.opt());
+ }
+ List<String> output;
+ List<String> expected;
+ Task.Expect expect;
+
+ if (essential == EssentialAPI.YES) {
+ if (preview == Preview.YES) {
+ if (lint == Lint.ENABLE_PREVIEW) {
+ expected = List.of("Test.java:5:14: compiler.warn.is.preview: test()",
+ "1 warning");
+ } else {
+ expected = List.of("- compiler.note.preview.filename: Test.java",
+ "- compiler.note.preview.recompile");
+ }
+ expect = Task.Expect.SUCCESS;
+ } else {
+ expected = List.of("Test.java:5:14: compiler.err.is.preview: test()",
+ "1 error");
+ expect = Task.Expect.FAIL;
+ }
+ } else {
+ if (suppress == Suppress.YES) {
+ expected = List.of("");
+ } else if ((preview == Preview.YES && (lint == Lint.NONE || lint == Lint.DISABLE_PREVIEW)) ||
+ (preview == Preview.NO && lint == Lint.DISABLE_PREVIEW)) {
+ expected = List.of("- compiler.note.preview.filename: Test.java",
+ "- compiler.note.preview.recompile");
+ } else {
+ expected = List.of("Test.java:5:14: compiler.warn.is.preview: test()",
+ "1 warning");
+ }
+ expect = Task.Expect.SUCCESS;
+ }
+
+ output = new JavacTask(tb)
+ .outdir(classesTest)
+ .options(options)
+ .files(findJavaFiles(srcTest))
+ .run(expect)
+ .writeAll()
+ .getOutputLines(Task.OutputKind.DIRECT);
+
+ if (!expected.equals(output)) {
+ throw new IllegalStateException("Unexpected output for " + essential + ", " + preview + ", " + lint + ", " + suppress + ": " + output);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public enum EssentialAPI {
+ YES(", essentialAPI=true"),
+ NO(", essentialAPI=false");
+
+ private final String code;
+
+ private EssentialAPI(String code) {
+ this.code = code;
+ }
+
+ public String code() {
+ return code;
+ }
+ }
+
+ public enum Preview {
+ YES("--enable-preview"),
+ NO(null);
+
+ private final String opt;
+
+ private Preview(String opt) {
+ this.opt = opt;
+ }
+
+ public String opt() {
+ return opt;
+ }
+ }
+
+ public enum Lint {
+ NONE(null),
+ ENABLE_PREVIEW("-Xlint:preview"),
+ DISABLE_PREVIEW("-Xlint:-preview");
+
+ private final String opt;
+
+ private Lint(String opt) {
+ this.opt = opt;
+ }
+
+ public String opt() {
+ return opt;
+ }
+ }
+
+ public enum Suppress {
+ YES("@SuppressWarnings(\"preview\")"),
+ NO("");
+
+ private final String code;
+
+ private Suppress(String code) {
+ this.code = code;
+ }
+
+ public String code() {
+ return code;
+ }
+ }
+}