8226585: Improve javac messages for using a preview API

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.

Co-authored-by: Joe Darcy <joe.darcy@oracle.com>
Reviewed-by: erikj, mcimadamore, alanb
This commit is contained in:
Jan Lahoda 2019-10-21 15:38:26 +02:00
parent f771978f53
commit a1894385b3
43 changed files with 794 additions and 166 deletions

View File

@ -49,6 +49,13 @@ $(BUILDTOOLS_OUTPUTDIR)/gensrc/%.interim/module-info.java: \
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 @@ define SetupInterimModule
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

View File

@ -95,6 +95,7 @@ JAVADOC_TAGS := \
-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) \
#

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package build.tools.taglet;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import javax.lang.model.element.Element;
import com.sun.source.doctree.DocTree;
import com.sun.source.doctree.TextTree;
import com.sun.source.doctree.UnknownInlineTagTree;
import jdk.javadoc.doclet.Taglet;
import static jdk.javadoc.doclet.Taglet.Location.*;
/**
* An block tag to insert a standard warning about a preview API.
*/
public class Preview implements Taglet {
/** Returns the set of locations in which a taglet may be used. */
@Override
public Set<Location> getAllowedLocations() {
return EnumSet.of(MODULE, PACKAGE, TYPE, CONSTRUCTOR, METHOD, FIELD);
}
@Override
public boolean isInlineTag() {
return true;
}
@Override
public String getName() {
return "preview";
}
@Override
public String toString(List<? extends DocTree> tags, Element elem) {
UnknownInlineTagTree previewTag = (UnknownInlineTagTree) tags.get(0);
List<? extends DocTree> previewContent = previewTag.getContent();
String previewText = ((TextTree) previewContent.get(0)).getBody();
String[] summaryAndDetails = previewText.split("\n\r?\n\r?");
String summary = summaryAndDetails[0];
String details = summaryAndDetails.length > 1 ? summaryAndDetails[1] : summaryAndDetails[0];
StackTraceElement[] stackTrace = new Exception().getStackTrace();
Predicate<StackTraceElement> isSummary =
el -> el.getClassName().endsWith("HtmlDocletWriter") &&
el.getMethodName().equals("addSummaryComment");
if (Arrays.stream(stackTrace).anyMatch(isSummary)) {
return "<div style=\"display:inline-block; font-weight:bold\">" + summary + "</div><br>";
}
return "<div style=\"border: 1px solid red; border-radius: 5px; padding: 5px; display:inline-block; font-size: larger\">" + details + "</div><br>";
}
}

View File

@ -2888,6 +2888,15 @@ public final class String
}
/**
* {@preview Associated with text blocks, a preview feature of
* the Java language.
*
* This method is associated with <i>text blocks</i>, a preview
* feature of the Java language. Programs can only use this
* method when preview features are enabled. Preview features
* may be removed in a future release, or upgraded to permanent
* features of the Java language.}
*
* Returns a string whose value is this string, with incidental
* {@linkplain Character#isWhitespace(int) white space} removed from
* the beginning and end of every line.
@ -2963,10 +2972,9 @@ public final class String
*
* @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 @@ public final class String
}
/**
* {@preview Associated with text blocks, a preview feature of
* the Java language.
*
* This method is associated with <i>text blocks</i>, a preview
* feature of the Java language. Programs can only use this
* method when preview features are enabled. Preview features
* may be removed in a future release, or upgraded to permanent
* features of the Java language.}
*
* Returns a string whose value is this string, with escape sequences
* translated as if in a string literal.
* <p>
@ -3079,11 +3096,9 @@ public final class String
* @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 @@ public final class String
}
/**
* {@preview Associated with text blocks, a preview feature of
* the Java language.
*
* This method is associated with <i>text blocks</i>, a preview
* feature of the Java language. Programs can only use this
* method when preview features are enabled. Preview features
* may be removed in a future release, or upgraded to permanent
* features of the Java language.}
*
* Formats using this string as the format string, and the supplied
* arguments.
*
@ -3324,10 +3348,9 @@ public final class String
*
* @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();
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.internal;
import java.lang.annotation.*;
/**
* Indicates the API declaration in question is associated with a
* <em>preview feature</em>. See JEP 12: "Preview Language and VM
* Features" (http://openjdk.java.net/jeps/12).
* @since 14
*/
// Match the meaningful targets of java.lang.Deprecated, omit local
// variables and parameter declarations
@Target({ElementType.METHOD,
ElementType.CONSTRUCTOR,
ElementType.FIELD,
ElementType.PACKAGE,
ElementType.MODULE,
ElementType.TYPE})
// CLASS retention will hopefully be sufficient for the purposes at hand
@Retention(RetentionPolicy.CLASS)
// *Not* @Documented
public @interface PreviewFeature {
/**
* Name of the preview feature the annotated API is associated
* with.
*/
public Feature feature();
public boolean essentialAPI() default false;
public enum Feature {
SWITCH_EXPRESSIONS,
TEXT_BLOCKS;
}
}

View File

@ -135,7 +135,8 @@ module java.base {
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,

View File

@ -55,17 +55,25 @@ public interface CaseTree extends Tree {
ExpressionTree getExpression();
/**
* {@preview Associated with switch expressions, a preview feature of
* the Java language.
*
* This method is associated with <i>switch expressions</i>, a preview
* feature of the Java language. Preview features
* may be removed in a future release, or upgraded to permanent
* features of the Java language.}
*
* Returns the labels for this case.
* For default case, returns an empty list.
*
* @return labels for this case
* @since 12
*
* @deprecated This method is modeling a case with multiple labels,
* @preview This method is modeling a case with multiple labels,
* which is part of a preview feature and may be removed
* if the preview feature is removed.
*/
@Deprecated(forRemoval=true, since="12")
@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SWITCH_EXPRESSIONS)
List<? extends ExpressionTree> getExpressions();
/**
@ -78,6 +86,14 @@ public interface CaseTree extends Tree {
List<? extends StatementTree> getStatements();
/**
* {@preview Associated with switch expressions, a preview feature of
* the Java language.
*
* This method is associated with <i>switch expressions</i>, a preview
* feature of the Java language. Preview features
* may be removed in a future release, or upgraded to permanent
* features of the Java language.}
*
* For case with kind {@linkplain CaseKind#RULE},
* returns the statement or expression after the arrow.
* Returns {@code null} for case with kind
@ -85,32 +101,41 @@ public interface CaseTree extends Tree {
*
* @return case value or null
* @since 12
*
* @deprecated This method is modeling a rule case,
* which is part of a preview feature and may be removed
* if the preview feature is removed.
*/
@Deprecated(forRemoval=true, since="12")
@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SWITCH_EXPRESSIONS)
public default Tree getBody() {
return null;
}
/**
* {@preview Associated with switch expressions, a preview feature of
* the Java language.
*
* This method is associated with <i>switch expressions</i>, a preview
* feature of the Java language. Preview features
* may be removed in a future release, or upgraded to permanent
* features of the Java language.}
*
* Returns the kind of this case.
*
* @return the kind of this case
* @since 12
*
* @deprecated This method is used to model a rule case,
* which is part of a preview feature and may be removed
* if the preview feature is removed.
*/
@Deprecated(forRemoval=true, since="12")
@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SWITCH_EXPRESSIONS)
@SuppressWarnings("preview")
public default CaseKind getCaseKind() {
return CaseKind.STATEMENT;
}
/**
* {@preview Associated with switch expressions, a preview feature of
* the Java language.
*
* This enum is associated with <i>switch expressions</i>, a preview
* feature of the Java language. Preview features
* may be removed in a future release, or upgraded to permanent
* features of the Java language.}
*
* The syntatic form of this case:
* <ul>
* <li>STATEMENT: {@code case <expression>: <statements>}</li>
@ -118,12 +143,9 @@ public interface CaseTree extends Tree {
* </ul>
*
* @since 12
*
* @deprecated This enum is used to model a rule case,
* which is part of a preview feature and may be removed
* if the preview feature is removed.
*/
@Deprecated(forRemoval=true, since="12")
@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SWITCH_EXPRESSIONS)
@SuppressWarnings("preview")
public enum CaseKind {
/**
* Case is in the form: {@code case <expression>: <statements>}.

View File

@ -28,6 +28,14 @@ package com.sun.source.tree;
import java.util.List;
/**
* {@preview Associated with switch expressions, a preview feature of
* the Java language.
*
* This interface is associated with <i>switch expressions</i>, a preview
* feature of the Java language. Preview features
* may be removed in a future release, or upgraded to permanent
* features of the Java language.}
*
* A tree node for a {@code switch} expression.
*
* For example:
@ -40,12 +48,8 @@ import java.util.List;
* @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.

View File

@ -240,17 +240,20 @@ public interface Tree {
SWITCH(SwitchTree.class),
/**
* {@preview Associated with switch expressions, a preview feature of
* the Java language.
*
* This enum constant is associated with <i>switch expressions</i>, a preview
* feature of the Java language. Preview features
* may be removed in a future release, or upgraded to permanent
* features of the Java language.}
*
* Used for instances of {@link SwitchExpressionTree}.
*
* @since 12
*
* @deprecated
* This enum constant is modeling switch expressions,
* which are part of a preview feature and may be removed
* if the preview feature is removed.
*/
@Deprecated(forRemoval=true, since="12")
@SuppressWarnings("removal")
@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SWITCH_EXPRESSIONS)
@SuppressWarnings("preview")
SWITCH_EXPRESSION(SwitchExpressionTree.class),
/**
@ -659,17 +662,20 @@ public interface Tree {
OTHER(null),
/**
* {@preview Associated with switch expressions, a preview feature of
* the Java language.
*
* This enum constant is associated with <i>switch expressions</i>, a preview
* feature of the Java language. Preview features
* may be removed in a future release, or upgraded to permanent
* features of the Java language.}
*
* Used for instances of {@link YieldTree}.
*
* @since 13
*
* @deprecated
* This enum constant is modeling yield statement,
* which are part of a preview feature and may be removed
* if the preview feature is removed.
*/
@Deprecated(forRemoval=true, since="13")
@SuppressWarnings("removal")
@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SWITCH_EXPRESSIONS)
@SuppressWarnings("preview")
YIELD(YieldTree.class);

View File

@ -354,20 +354,23 @@ public interface TreeVisitor<R,P> {
R visitSwitch(SwitchTree node, P p);
/**
* {@preview Associated with switch expressions, a preview feature of
* the Java language.
*
* This method is associated with <i>switch expressions</i>, a preview
* feature of the Java language. Preview features
* may be removed in a future release, or upgraded to permanent
* features of the Java language.}
*
* Visits a SwitchExpressionTree node.
*
* @param node the node being visited
* @param p a parameter value
* @return a result value
* @since 12
*
* @deprecated
* This method is modeling switch expressions,
* which are part of a preview feature and may be removed
* if the preview feature is removed.
*/
@Deprecated(forRemoval=true, since="12")
@SuppressWarnings("removal")
@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SWITCH_EXPRESSIONS)
@SuppressWarnings("preview")
R visitSwitchExpression(SwitchExpressionTree node, P p);
/**
@ -557,18 +560,21 @@ public interface TreeVisitor<R,P> {
R visitOther(Tree node, P p);
/**
* {@preview Associated with switch expressions, a preview feature of
* the Java language.
*
* This method is associated with <i>switch expressions</i>, a preview
* feature of the Java language. Preview features
* may be removed in a future release, or upgraded to permanent
* features of the Java language.}
*
* Visits a YieldTree node.
* @param node the node being visited
* @param p a parameter value
* @return a result value
* @since 13
*
* @deprecated
* This method is modeling yield statement,
* which are part of a preview feature and may be removed
* if the preview feature is removed.
*/
@Deprecated(forRemoval=true, since="13")
@SuppressWarnings("removal")
@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.SWITCH_EXPRESSIONS)
@SuppressWarnings("preview")
R visitYield(YieldTree node, P p);
}

View File

@ -26,6 +26,14 @@
package com.sun.source.tree;
/**
* {@preview Associated with switch expressions, a preview feature of
* the Java language.
*
* This method is associated with <i>switch expressions</i>, a preview
* feature of the Java language. Preview features
* may be removed in a future release, or upgraded to permanent
* features of the Java language.}
*
* A tree node for a {@code yield} statement.
*
* For example:
@ -36,12 +44,8 @@ package com.sun.source.tree;
* @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 {
/**

View File

@ -264,20 +264,23 @@ public class SimpleTreeVisitor <R,P> implements TreeVisitor<R,P> {
}
/**
* {@preview Associated with switch expressions, a preview feature of
* the Java language.
*
* This method is associated with <i>switch expressions</i>, a preview
* feature of the Java language. Preview features
* may be removed in a future release, or upgraded to permanent
* features of the Java language.}
*
* {@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 @@ public class SimpleTreeVisitor <R,P> implements TreeVisitor<R,P> {
* @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);
}

View File

@ -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 @@ public class TreeScanner<R,P> implements TreeVisitor<R,P> {
}
/**
* {@preview Associated with switch expressions, a preview feature of
* the Java language.
*
* This method is associated with <i>switch expressions</i>, a preview
* feature of the Java language. Preview features
* may be removed in a future release, or upgraded to permanent
* features of the Java language.}
*
* {@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 @@ public class TreeScanner<R,P> implements TreeVisitor<R,P> {
* @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 @@ public class TreeScanner<R,P> implements TreeVisitor<R,P> {
}
/**
* {@preview Associated with switch expressions, a preview feature of
* the Java language.
*
* This method is associated with <i>switch expressions</i>, a preview
* feature of the Java language. Preview features
* may be removed in a future release, or upgraded to permanent
* features of the Java language.}
*
* {@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);
}

View File

@ -52,6 +52,7 @@ import com.sun.source.util.TaskEvent.Kind;
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 @@ public class JavacTaskPool {
((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();

View File

@ -286,7 +286,17 @@ public class Flags {
/**
* 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 class Flags {
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 class Flags {
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 @@ public class Flags {
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;

View File

@ -122,6 +122,9 @@ public class Lint
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

View File

@ -27,7 +27,6 @@ package com.sun.tools.javac.code;
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.Context;
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 @@ import static com.sun.tools.javac.main.Option.PREVIEW;
*/
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 class Preview {
}
}
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 class Preview {
public void reportDeferredDiagnostics() {
previewHandler.reportDeferredDiagnostic();
}
public void clear() {
previewHandler.clear();
}
}

View File

@ -378,6 +378,10 @@ public abstract class Symbol extends AnnoConstruct implements PoolConstant, Elem
return (flags_field & DEPRECATED_REMOVAL) != 0;
}
public boolean isPreviewApi() {
return (flags_field & PREVIEW_API) != 0;
}
public boolean isDeprecatableViaAnnotation() {
switch (getKind()) {
case LOCAL_VARIABLE:

View File

@ -214,6 +214,7 @@ public class Symtab {
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 @@ public class Symtab {
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);

View File

@ -364,12 +364,17 @@ public class Annotate {
&& (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 @@ public class Annotate {
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

View File

@ -32,7 +32,7 @@ import java.util.stream.Collectors;
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 @@ public class Attr extends JCTree.Visitor {
// check that there are no duplicate case labels or default clauses.
Set<Object> labels = new HashSet<>(); // The set of case labels.
boolean hasDefault = false; // Is there a default label?
@SuppressWarnings("removal")
CaseKind caseKind = null;
@SuppressWarnings("preview")
CaseTree.CaseKind caseKind = null;
boolean wasError = false;
for (List<JCCase> l = cases; l.nonEmpty(); l = l.tail) {
JCCase c = l.head;
@ -4092,6 +4092,7 @@ public class Attr extends JCTree.Visitor {
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

View File

@ -93,6 +93,7 @@ public class Check {
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 @@ public class Check {
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 @@ public class Check {
}
}
/** 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 @@ public class Check {
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 @@ public class Check {
}
}
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.
**************************************************************************/

View File

@ -30,7 +30,6 @@ import java.util.Map.Entry;
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;

View File

@ -2819,6 +2819,7 @@ public class Resolve {
typeargtypes, allowBoxing,
useVarargs);
chk.checkDeprecated(pos, env.info.scope.owner, sym);
chk.checkPreview(pos, sym);
return sym;
}

View File

@ -1156,19 +1156,26 @@ public class TypeEnter implements Completer {
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;
}
});
}
}

View File

@ -44,6 +44,7 @@ import java.nio.charset.UnsupportedCharsetException;
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 @@ public abstract class BaseFileManager implements JavaFileManager {
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();

View File

@ -1395,20 +1395,27 @@ public class ClassReader {
repeatable = proxy;
} else if (proxy.type.tsym == syms.deprecatedType.tsym) {
sym.flags_field |= (DEPRECATED | DEPRECATED_ANNOTATION);
for (Pair<Name, Attribute> v : proxy.values) {
if (v.fst == names.forRemoval && v.snd instanceof Attribute.Constant) {
Attribute.Constant c = (Attribute.Constant)v.snd;
if (c.type == syms.booleanType && ((Integer)c.value) != 0) {
sym.flags_field |= DEPRECATED_REMOVAL;
}
}
}
setFlagIfAttributeTrue(proxy, sym, names.forRemoval, DEPRECATED_REMOVAL);
} else if (proxy.type.tsym == syms.previewFeatureType.tsym) {
sym.flags_field |= PREVIEW_API;
setFlagIfAttributeTrue(proxy, sym, names.essentialAPI, PREVIEW_ESSENTIAL_API);
}
proxies.append(proxy);
}
}
annotate.normal(new AnnotationCompleter(sym, proxies.toList()));
}
//where:
private void setFlagIfAttributeTrue(CompoundAnnotationProxy proxy, Symbol sym, Name attribute, long flag) {
for (Pair<Name, Attribute> v : proxy.values) {
if (v.fst == attribute && v.snd instanceof Attribute.Constant) {
Attribute.Constant c = (Attribute.Constant)v.snd;
if (c.type == syms.booleanType && ((Integer)c.value) != 0) {
sym.flags_field |= flag;
}
}
}
}
/** Read parameter annotations.
*/

View File

@ -29,7 +29,7 @@ import java.util.*;
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 @@ public class JavacParser implements Parser {
}
List<JCStatement> stats = null;
JCTree body = null;
@SuppressWarnings("removal")
CaseKind kind;
@SuppressWarnings("preview")
CaseTree.CaseKind kind;
switch (token.kind) {
case ARROW:
checkSourceLevel(Feature.SWITCH_RULE);
@ -2897,8 +2897,8 @@ public class JavacParser implements Parser {
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 @@ public class JavacParser implements Parser {
}
case DEFAULT: {
nextToken();
@SuppressWarnings("removal")
CaseKind caseKind;
@SuppressWarnings("preview")
CaseTree.CaseKind caseKind;
JCTree body = null;
if (token.kind == ARROW) {
checkSourceLevel(Feature.SWITCH_RULE);

View File

@ -1774,6 +1774,14 @@ compiler.warn.has.been.deprecated=\
compiler.warn.has.been.deprecated.for.removal=\
{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

View File

@ -47,7 +47,6 @@ import static com.sun.tools.javac.tree.JCTree.Tag.*;
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 abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public static class JCCase extends JCStatement implements CaseTree {
//as CaseKind is deprecated for removal (as it is part of a preview feature),
//using indirection through these fields to avoid unnecessary @SuppressWarnings:
@SuppressWarnings("removal")
@SuppressWarnings("preview")
public static final CaseKind STATEMENT = CaseKind.STATEMENT;
@SuppressWarnings("removal")
@SuppressWarnings("preview")
public static final CaseKind RULE = CaseKind.RULE;
@SuppressWarnings("removal")
@SuppressWarnings("preview")
public final CaseKind caseKind;
public List<JCExpression> pats;
public List<JCStatement> stats;
public JCTree body;
public boolean completesNormally;
protected JCCase(@SuppressWarnings("removal") CaseKind caseKind, List<JCExpression> pats,
protected JCCase(@SuppressWarnings("preview") CaseKind caseKind, List<JCExpression> pats,
List<JCStatement> stats, JCTree body) {
Assert.checkNonNull(pats);
Assert.check(pats.isEmpty() || pats.head != null);
@ -1277,18 +1276,18 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
@Override @DefinedBy(Api.COMPILER_TREE)
public JCExpression getExpression() { return pats.head; }
@Override @DefinedBy(Api.COMPILER_TREE)
@SuppressWarnings("removal")
@SuppressWarnings("preview")
public List<JCExpression> getExpressions() { return pats; }
@Override @DefinedBy(Api.COMPILER_TREE)
@SuppressWarnings("removal")
@SuppressWarnings("preview")
public List<JCStatement> getStatements() {
return caseKind == CaseKind.STATEMENT ? stats : null;
}
@Override @DefinedBy(Api.COMPILER_TREE)
@SuppressWarnings("removal")
@SuppressWarnings("preview")
public JCTree getBody() { return body; }
@Override @DefinedBy(Api.COMPILER_TREE)
@SuppressWarnings("removal")
@SuppressWarnings("preview")
public CaseKind getCaseKind() {
return caseKind;
}
@ -1305,7 +1304,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
/**
* A "switch ( ) { }" construction.
*/
@SuppressWarnings("removal")
@SuppressWarnings("preview")
public static class JCSwitchExpression extends JCPolyExpression implements SwitchExpressionTree {
public JCExpression selector;
public List<JCCase> cases;
@ -1586,7 +1585,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
/**
* 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 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
JCLabeledStatement Labelled(Name label, JCStatement body);
JCSwitch Switch(JCExpression selector, List<JCCase> cases);
JCSwitchExpression SwitchExpression(JCExpression selector, List<JCCase> cases);
JCCase Case(@SuppressWarnings("removal") CaseKind caseKind, List<JCExpression> pat,
JCCase Case(@SuppressWarnings("preview") CaseTree.CaseKind caseKind, List<JCExpression> pat,
List<JCStatement> stats, JCTree body);
JCSynchronized Synchronized(JCExpression lock, JCBlock body);
JCTry Try(JCBlock body, List<JCCatch> catchers, JCBlock finalizer);

View File

@ -27,7 +27,6 @@ package com.sun.tools.javac.tree;
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.*;

View File

@ -144,7 +144,7 @@ public class TreeCopier<P> implements TreeVisitor<JCTree,P> {
}
@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 @@ public class TreeCopier<P> implements TreeVisitor<JCTree,P> {
}
@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);

View File

@ -27,7 +27,7 @@ package com.sun.tools.javac.tree;
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 @@ public class TreeMaker implements JCTree.Factory {
return tree;
}
public JCCase Case(@SuppressWarnings("removal") CaseKind caseKind, List<JCExpression> pats,
public JCCase Case(@SuppressWarnings("preview") CaseTree.CaseKind caseKind, List<JCExpression> pats,
List<JCStatement> stats, JCTree body) {
JCCase tree = new JCCase(caseKind, pats, stats, body);
tree.pos = pos;

View File

@ -186,18 +186,18 @@ public class MandatoryWarningHandler {
/**
* 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 @@ public class MandatoryWarningHandler {
else
log.note(file, new Note("compiler", msg, args));
}
public void clear() {
sourcesWithReportedWarnings = null;
deferredDiagnosticKind = null;
deferredDiagnosticSource = null;
deferredDiagnosticArg = null;
}
}

View File

@ -86,6 +86,7 @@ public class Names {
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 @@ public class Names {
error = fromString("<error>");
finalize = fromString("finalize");
forRemoval = fromString("forRemoval");
essentialAPI = fromString("essentialAPI");
getClass = fromString("getClass");
hasNext = fromString("hasNext");
hashCode = fromString("hashCode");

View File

@ -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;

View File

@ -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 {

View File

@ -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 {

View File

@ -11,6 +11,7 @@ compiler.err.invalid.repeatable.annotation # should not happen
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.future.attr # ClassReader
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

View File

@ -23,6 +23,7 @@
package combo;
import java.lang.reflect.Method;
import javax.tools.StandardJavaFileManager;
import java.util.Optional;
@ -57,6 +58,14 @@ public abstract class ComboInstance<X extends ComboInstance<X>> {
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 @@ public abstract class ComboInstance<X extends ComboInstance<X>> {
return success;
}
}
}
}

View File

@ -0,0 +1,274 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8226585
* @summary Verify behavior w.r.t. preview feature API errors and warnings
* @library /tools/lib /tools/javac/lib
* @modules
* java.base/jdk.internal
* jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.file
* jdk.compiler/com.sun.tools.javac.main
* jdk.compiler/com.sun.tools.javac.util
* @build toolbox.ToolBox toolbox.JavacTask
* @build combo.ComboTestHelper
* @compile --enable-preview -source ${jdk.version} PreviewErrors.java
* @run main/othervm --enable-preview PreviewErrors
*/
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import combo.ComboInstance;
import combo.ComboParameter;
import combo.ComboTask;
import combo.ComboTestHelper;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
import javax.tools.Diagnostic;
import jdk.internal.PreviewFeature;
import toolbox.JavacTask;
import toolbox.ToolBox;
public class PreviewErrors extends ComboInstance<PreviewErrors> {
protected ToolBox tb;
PreviewErrors() {
super();
tb = new ToolBox();
}
public static void main(String... args) throws Exception {
new ComboTestHelper<PreviewErrors>()
.withDimension("ESSENTIAL", (x, essential) -> x.essential = essential, EssentialAPI.values())
.withDimension("PREVIEW", (x, preview) -> x.preview = preview, Preview.values())
.withDimension("LINT", (x, lint) -> x.lint = lint, Lint.values())
.withDimension("SUPPRESS", (x, suppress) -> x.suppress = suppress, Suppress.values())
.withDimension("FROM", (x, from) -> x.from = from, PreviewFrom.values())
.run(PreviewErrors::new);
}
private EssentialAPI essential;
private Preview preview;
private Lint lint;
private Suppress suppress;
private PreviewFrom from;
@Override
public void doWork() throws IOException {
Path base = Paths.get(".");
Path src = base.resolve("src");
Path srcJavaBase = src.resolve("java.base");
Path classes = base.resolve("classes");
Path classesJavaBase = classes.resolve("java.base");
Files.createDirectories(classesJavaBase);
String previewAPI = """
package preview.api;
public class Extra {
@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.${preview}
${essential})
public static void test() { }
@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.${preview}
${essential})
public static class Clazz {}
}
""".replace("${preview}", PreviewFeature.Feature.values()[0].name())
.replace("${essential}", essential.expand(null));
if (from == PreviewFrom.CLASS) {
tb.writeJavaFiles(srcJavaBase, previewAPI);
new JavacTask(tb)
.outdir(classesJavaBase)
.options("--patch-module", "java.base=" + srcJavaBase.toString())
.files(tb.findJavaFiles(srcJavaBase))
.run()
.writeAll();
}
ComboTask task = newCompilationTask()
.withSourceFromTemplate("""
package test;
public class Test {
#{SUPPRESS}
public void test() {
preview.api.Extra.test();
preview.api.Extra.Clazz c;
}
}
""")
.withOption("-XDrawDiagnostics")
.withOption("-source")
.withOption(String.valueOf(Runtime.version().feature()));
if (from == PreviewFrom.CLASS) {
task.withOption("--patch-module")
.withOption("java.base=" + classesJavaBase.toString())
.withOption("--add-exports")
.withOption("java.base/preview.api=ALL-UNNAMED");
} else {
task.withSourceFromTemplate("Extra", previewAPI)
.withOption("--add-exports")
.withOption("java.base/jdk.internal=ALL-UNNAMED");
}
if (preview.expand(null)!= null) {
task = task.withOption(preview.expand(null));
}
if (lint.expand(null) != null) {
task = task.withOption(lint.expand(null));
}
task.generate(result -> {
Set<String> actual = Arrays.stream(Diagnostic.Kind.values())
.flatMap(kind -> result.diagnosticsForKind(kind).stream())
.map(d -> d.getLineNumber() + ":" + d.getColumnNumber() + ":" + d.getCode())
.collect(Collectors.toSet());
Set<String> expected;
boolean ok;
if (essential == EssentialAPI.YES) {
if (preview == Preview.YES) {
if (suppress == Suppress.YES) {
expected = Set.of();
} else if (lint == Lint.ENABLE_PREVIEW) {
expected = Set.of("5:26:compiler.warn.is.preview", "6:26:compiler.warn.is.preview");
} else {
expected = Set.of("-1:-1:compiler.note.preview.filename",
"-1:-1:compiler.note.preview.recompile");
}
ok = true;
} else {
expected = Set.of("5:26:compiler.err.is.preview", "6:26:compiler.err.is.preview");
ok = false;
}
} else {
if (suppress == Suppress.YES) {
expected = Set.of();
} else if ((preview == Preview.YES && (lint == Lint.NONE || lint == Lint.DISABLE_PREVIEW)) ||
(preview == Preview.NO && lint == Lint.DISABLE_PREVIEW)) {
expected = Set.of("-1:-1:compiler.note.preview.filename",
"-1:-1:compiler.note.preview.recompile");
} else {
expected = Set.of("5:26:compiler.warn.is.preview", "6:26:compiler.warn.is.preview");
}
ok = true;
}
if (ok) {
if (!result.get().iterator().hasNext()) {
throw new IllegalStateException("Did not succeed as expected." + actual);
}
} else {
if (result.get().iterator().hasNext()) {
throw new IllegalStateException("Succeed unexpectedly.");
}
}
if (!expected.equals(actual)) {
throw new IllegalStateException("Unexpected output for " + essential + ", " + preview + ", " + lint + ", " + suppress + ", " + from + ": actual: \"" + actual + "\", expected: \"" + expected + "\"");
}
});
}
public enum EssentialAPI implements ComboParameter {
YES(", essentialAPI=true"),
NO(", essentialAPI=false");
private final String code;
private EssentialAPI(String code) {
this.code = code;
}
public String expand(String optParameter) {
return code;
}
}
public enum Preview implements ComboParameter {
YES("--enable-preview"),
NO(null);
private final String opt;
private Preview(String opt) {
this.opt = opt;
}
public String expand(String optParameter) {
return opt;
}
}
public enum Lint implements ComboParameter {
NONE(null),
ENABLE_PREVIEW("-Xlint:preview"),
DISABLE_PREVIEW("-Xlint:-preview");
private final String opt;
private Lint(String opt) {
this.opt = opt;
}
public String expand(String optParameter) {
return opt;
}
}
public enum Suppress implements ComboParameter {
YES("@SuppressWarnings(\"preview\")"),
NO("");
private final String code;
private Suppress(String code) {
this.code = code;
}
public String expand(String optParameter) {
return code;
}
}
public enum PreviewFrom implements ComboParameter {
CLASS,
SOURCE;
private PreviewFrom() {
}
public String expand(String optParameter) {
throw new IllegalStateException();
}
}
}

View File

@ -177,6 +177,7 @@ public class NoPrivateTypesExported extends JavacTestingAbstractProcessor {
if (annotationElement.getAnnotation(Documented.class) == null) {
note("Ignoring undocumented annotation: " + mirror.getAnnotationType());
continue;
}
verifyTypeAcceptable(mirror.getAnnotationType(), acceptable);

View File

@ -92,6 +92,7 @@ public class ListModuleDeps {
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",