8145471: javac changes for enhanced deprecation
Reviewed-by: smarks, tbell, mcimadamore, jlahoda
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java Thu Oct 20 20:01:40 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Flags.java Thu Oct 20 13:44:51 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -113,7 +113,7 @@
* Internal compiler flags (no bits in the lower 16).
*****************************************/
- /** Flag is set if symbol is deprecated.
+ /** Flag is set if symbol is deprecated. See also DEPRECATED_REMOVAL.
*/
public static final int DEPRECATED = 1<<17;
@@ -293,6 +293,11 @@
*/
public static final long SYSTEM_MODULE = 1L<<53;
+ /**
+ * Flag to indicate the given symbol has been deprecated and marked for removal.
+ */
+ public static final long DEPRECATED_REMOVAL = 1L<<54;
+
/** Modifier masks.
*/
public static final int
@@ -402,7 +407,8 @@
THROWS(Flags.THROWS),
LAMBDA_METHOD(Flags.LAMBDA_METHOD),
TYPE_TRANSLATED(Flags.TYPE_TRANSLATED),
- MODULE(Flags.MODULE);
+ MODULE(Flags.MODULE),
+ DEPRECATED_REMOVAL(Flags.DEPRECATED_REMOVAL);
Flag(long flag) {
this.value = flag;
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java Thu Oct 20 20:01:40 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java Thu Oct 20 13:44:51 2016 -0700
@@ -25,11 +25,13 @@
package com.sun.tools.javac.code;
+import java.util.Arrays;
import java.util.EnumSet;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.sun.tools.javac.code.Symbol.*;
+import com.sun.tools.javac.main.Option;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Options;
@@ -81,12 +83,13 @@
}
/**
- * Returns a new Lint that has the given LintCategory suppressed.
+ * Returns a new Lint that has the given LintCategorys suppressed.
+ * @param lc one or more categories to be suppressed
*/
- public Lint suppress(LintCategory lc) {
+ public Lint suppress(LintCategory... lc) {
Lint l = new Lint(this);
- l.values.remove(lc);
- l.suppressedValues.add(lc);
+ l.values.removeAll(Arrays.asList(lc));
+ l.suppressedValues.addAll(Arrays.asList(lc));
return l;
}
@@ -100,10 +103,31 @@
protected Lint(Context context) {
// initialize values according to the lint options
Options options = Options.instance(context);
- values = EnumSet.noneOf(LintCategory.class);
- for (Map.Entry<String, LintCategory> e: map.entrySet()) {
- if (options.lint(e.getKey()))
- values.add(e.getValue());
+
+ if (options.isSet(Option.XLINT) || options.isSet(Option.XLINT_CUSTOM, "all")) {
+ // If -Xlint or -Xlint:all is given, enable all categories by default
+ values = EnumSet.allOf(LintCategory.class);
+ } else if (options.isSet(Option.XLINT_CUSTOM, "none")) {
+ // if -Xlint:none is given, disable all categories by default
+ values = EnumSet.noneOf(LintCategory.class);
+ } else {
+ // otherwise, enable on-by-default categories
+ values = EnumSet.noneOf(LintCategory.class);
+
+ Source source = Source.instance(context);
+ if (source.compareTo(Source.JDK1_9) >= 0) {
+ values.add(LintCategory.DEP_ANN);
+ }
+ values.add(LintCategory.REMOVAL);
+ }
+
+ // Look for specific overrides
+ for (LintCategory lc : LintCategory.values()) {
+ if (options.isSet(Option.XLINT_CUSTOM, lc.option)) {
+ values.add(lc);
+ } else if (options.isSet(Option.XLINT_CUSTOM, "-" + lc.option)) {
+ values.remove(lc);
+ }
}
suppressedValues = EnumSet.noneOf(LintCategory.class);
@@ -213,6 +237,11 @@
RAW("rawtypes"),
/**
+ * Warn about use of deprecated-for-removal items.
+ */
+ REMOVAL("removal"),
+
+ /**
* Warn about Serializable classes that do not provide a serial version ID.
*/
SERIAL("serial"),
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java Thu Oct 20 20:01:40 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java Thu Oct 20 13:44:51 2016 -0700
@@ -359,6 +359,10 @@
return (flags_field & DEPRECATED) != 0;
}
+ public boolean isDeprecatedForRemoval() {
+ return (flags_field & DEPRECATED_REMOVAL) != 0;
+ }
+
public boolean isDeprecatableViaAnnotation() {
switch (getKind()) {
case LOCAL_VARIABLE:
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java Thu Oct 20 20:01:40 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Annotate.java Thu Oct 20 13:44:51 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
@@ -340,6 +340,13 @@
&& toAnnotate.owner.kind != MTH
&& types.isSameType(c.type, syms.deprecatedType)) {
toAnnotate.flags_field |= Flags.DEPRECATED;
+ 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;
+ }
+ }
}
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Thu Oct 20 20:01:40 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java Thu Oct 20 13:44:51 2016 -0700
@@ -139,11 +139,14 @@
profile = Profile.instance(context);
boolean verboseDeprecated = lint.isEnabled(LintCategory.DEPRECATION);
+ boolean verboseRemoval = lint.isEnabled(LintCategory.REMOVAL);
boolean verboseUnchecked = lint.isEnabled(LintCategory.UNCHECKED);
boolean enforceMandatoryWarnings = true;
deprecationHandler = new MandatoryWarningHandler(log, verboseDeprecated,
enforceMandatoryWarnings, "deprecated", LintCategory.DEPRECATION);
+ removalHandler = new MandatoryWarningHandler(log, verboseRemoval,
+ enforceMandatoryWarnings, "removal", LintCategory.REMOVAL);
uncheckedHandler = new MandatoryWarningHandler(log, verboseUnchecked,
enforceMandatoryWarnings, "unchecked", LintCategory.UNCHECKED);
sunApiHandler = new MandatoryWarningHandler(log, false,
@@ -185,6 +188,10 @@
*/
private MandatoryWarningHandler deprecationHandler;
+ /** A handler for messages about deprecated-for-removal usage.
+ */
+ private MandatoryWarningHandler removalHandler;
+
/** A handler for messages about unchecked or unsafe usage.
*/
private MandatoryWarningHandler uncheckedHandler;
@@ -218,8 +225,13 @@
* @param sym The deprecated symbol.
*/
void warnDeprecated(DiagnosticPosition pos, Symbol sym) {
- if (!lint.isSuppressed(LintCategory.DEPRECATION))
+ if (sym.isDeprecatedForRemoval()) {
+ if (!lint.isSuppressed(LintCategory.REMOVAL)) {
+ removalHandler.report(pos, "has.been.deprecated.for.removal", sym, sym.location());
+ }
+ } else if (!lint.isSuppressed(LintCategory.DEPRECATION)) {
deprecationHandler.report(pos, "has.been.deprecated", sym, sym.location());
+ }
}
/** Warn about unchecked operation.
@@ -257,6 +269,7 @@
*/
public void reportDeferredDiagnostics() {
deprecationHandler.reportDeferredDiagnostic();
+ removalHandler.reportDeferredDiagnostic();
uncheckedHandler.reportDeferredDiagnostic();
sunApiHandler.reportDeferredDiagnostic();
}
@@ -3230,9 +3243,9 @@
}
void checkDeprecated(final DiagnosticPosition pos, final Symbol other, final Symbol s) {
- if ((s.flags() & DEPRECATED) != 0 &&
- (other.flags() & DEPRECATED) == 0 &&
- s.outermostClass() != other.outermostClass()) {
+ if ( (s.isDeprecatedForRemoval()
+ || s.isDeprecated() && !other.isDeprecated())
+ && s.outermostClass() != other.outermostClass()) {
deferredLintHandler.report(new DeferredLintHandler.LintLogger() {
@Override
public void report() {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java Thu Oct 20 20:01:40 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java Thu Oct 20 13:44:51 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, 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
@@ -103,7 +103,6 @@
private final TypeAnnotations typeAnnotations;
private final Types types;
private final JCDiagnostic.Factory diags;
- private final Source source;
private final DeferredLintHandler deferredLintHandler;
private final Lint lint;
private final TypeEnvs typeEnvs;
@@ -131,7 +130,6 @@
typeAnnotations = TypeAnnotations.instance(context);
types = Types.instance(context);
diags = JCDiagnostic.Factory.instance(context);
- source = Source.instance(context);
deferredLintHandler = DeferredLintHandler.instance(context);
lint = Lint.instance(context);
typeEnvs = TypeEnvs.instance(context);
@@ -178,6 +176,7 @@
/** Complete entering a class.
* @param sym The symbol of the class to be completed.
*/
+ @Override
public void complete(Symbol sym) throws CompletionFailure {
// Suppress some (recursive) MemberEnter invocations
if (!completionEnabled) {
@@ -414,7 +413,7 @@
Type attribImportType(JCTree tree, Env<AttrContext> env) {
Assert.check(completionEnabled);
Lint prevLint = chk.setLint(allowDeprecationOnImport ?
- lint : lint.suppress(LintCategory.DEPRECATION));
+ lint : lint.suppress(LintCategory.DEPRECATION, LintCategory.REMOVAL));
try {
// To prevent deep recursion, suppress completion of some
// types.
@@ -751,12 +750,12 @@
// can attribute the annotation types and then check to see if the
// @Deprecated annotation is present.
attr.attribAnnotationTypes(tree.mods.annotations, baseEnv);
- if (hasDeprecatedAnnotation(tree.mods.annotations))
- sym.flags_field |= DEPRECATED;
+ handleDeprecatedAnnotation(tree.mods.annotations, sym);
chk.checkNonCyclicDecl(tree);
}
//where:
+ @Override
protected JCExpression clearTypeParams(JCExpression superType) {
switch (superType.getTag()) {
case TYPEAPPLY:
@@ -767,16 +766,29 @@
}
/**
- * Check if a list of annotations contains a reference to
- * java.lang.Deprecated.
+ * If a list of annotations contains a reference to java.lang.Deprecated,
+ * set the DEPRECATED flag.
+ * If the annotation is marked forRemoval=true, also set DEPRECATED_REMOVAL.
**/
- private boolean hasDeprecatedAnnotation(List<JCAnnotation> annotations) {
+ private void handleDeprecatedAnnotation(List<JCAnnotation> annotations, Symbol sym) {
for (List<JCAnnotation> al = annotations; !al.isEmpty(); al = al.tail) {
JCAnnotation a = al.head;
- if (a.annotationType.type == syms.deprecatedType && a.args.isEmpty())
- return true;
+ if (a.annotationType.type == syms.deprecatedType) {
+ sym.flags_field |= Flags.DEPRECATED;
+ 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;
+ }
+ });
+ }
}
- return false;
}
@Override
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java Thu Oct 20 20:01:40 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java Thu Oct 20 13:44:51 2016 -0700
@@ -52,8 +52,6 @@
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
-import com.sun.tools.javac.code.Lint;
-import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.main.Option;
import com.sun.tools.javac.main.OptionHelper;
import com.sun.tools.javac.main.OptionHelper.GrumpyHelper;
@@ -85,7 +83,10 @@
log = Log.instance(context);
options = Options.instance(context);
classLoaderClass = options.get("procloader");
- locations.update(log, Lint.instance(context), FSInfo.instance(context));
+
+ // Avoid initializing Lint
+ boolean warn = options.isLintSet("path");
+ locations.update(log, warn, FSInfo.instance(context));
// Setting this option is an indication that close() should defer actually closing
// the file manager until after a specified period of inactivity.
@@ -171,14 +172,6 @@
private long lastUsedTime = System.currentTimeMillis();
protected long deferredCloseTimeout = 0;
- protected Source getSource() {
- String sourceName = options.get(Option.SOURCE);
- Source source = null;
- if (sourceName != null)
- source = Source.lookup(sourceName);
- return (source != null ? source : Source.DEFAULT);
- }
-
protected ClassLoader getClassLoader(URL[] urls) {
ClassLoader thisClassLoader = getClass().getClassLoader();
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Thu Oct 20 20:01:40 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/Locations.java Thu Oct 20 13:44:51 2016 -0700
@@ -42,7 +42,6 @@
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.ProviderNotFoundException;
-import java.nio.file.spi.FileSystemProvider;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -63,7 +62,6 @@
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import java.util.zip.ZipFile;
import javax.lang.model.SourceVersion;
import javax.tools.JavaFileManager;
@@ -159,10 +157,9 @@
}
}
- // could replace Lint by "boolean warn"
- void update(Log log, Lint lint, FSInfo fsInfo) {
+ void update(Log log, boolean warn, FSInfo fsInfo) {
this.log = log;
- warn = lint.isEnabled(Lint.LintCategory.PATH);
+ this.warn = warn;
this.fsInfo = fsInfo;
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java Thu Oct 20 20:01:40 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java Thu Oct 20 13:44:51 2016 -0700
@@ -1460,7 +1460,6 @@
ListBuffer<CompoundAnnotationProxy> proxies = new ListBuffer<>();
for (int i = 0; i<numAttributes; i++) {
CompoundAnnotationProxy proxy = readCompoundAnnotation();
-
if (proxy.type.tsym == syms.proprietaryType.tsym)
sym.flags_field |= PROPRIETARY;
else if (proxy.type.tsym == syms.profileType.tsym) {
@@ -1479,6 +1478,16 @@
target = proxy;
} else if (proxy.type.tsym == syms.repeatableType.tsym) {
repeatable = proxy;
+ } else if (proxy.type.tsym == syms.deprecatedType.tsym) {
+ sym.flags_field |= DEPRECATED;
+ 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;
+ }
+ }
+ }
}
proxies.append(proxy);
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java Thu Oct 20 20:01:40 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java Thu Oct 20 13:44:51 2016 -0700
@@ -37,6 +37,7 @@
import java.util.EnumSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.Map;
import java.util.ServiceLoader;
@@ -111,7 +112,6 @@
"all",
log.localize(PrefixKind.JAVAC, "opt.Xlint.all")));
for (LintCategory lc : LintCategory.values()) {
- if (lc.hidden) continue;
log.printRawLines(WriterKind.STDOUT,
String.format(LINT_KEY_FORMAT,
lc.option,
@@ -801,8 +801,8 @@
/** The kind of choices for this option, if any. */
private final ChoiceKind choiceKind;
- /** The choices for this option, if any, and whether or not the choices are hidden. */
- private final Map<String,Boolean> choices;
+ /** The choices for this option, if any. */
+ private final Set<String> choices;
/**
* Looks up the first option matching the given argument in the full set of options.
@@ -815,7 +815,8 @@
/**
* Looks up the first option matching the given argument within a set of options.
- * @param arg the argument to be matches
+ * @param arg the argument to be matched
+ * @param options the set of possible options
* @return the first option that matches, or null if none.
*/
public static Option lookup(String arg, Set<Option> options) {
@@ -867,7 +868,7 @@
}
Option(String text, String argsNameKey, String descrKey, OptionKind kind, OptionGroup group,
- ChoiceKind choiceKind, Map<String,Boolean> choices) {
+ ChoiceKind choiceKind, Set<String> choices) {
this(text, argsNameKey, descrKey, kind, group, choiceKind, choices, ArgKind.REQUIRED);
}
@@ -875,19 +876,12 @@
OptionKind kind, OptionGroup group,
ChoiceKind choiceKind, String... choices) {
this(text, null, descrKey, kind, group, choiceKind,
- createChoices(choices), ArgKind.REQUIRED);
+ new LinkedHashSet<>(Arrays.asList(choices)), ArgKind.REQUIRED);
}
- // where
- private static Map<String,Boolean> createChoices(String... choices) {
- Map<String,Boolean> map = new LinkedHashMap<>();
- for (String c: choices)
- map.put(c, false);
- return map;
- }
private Option(String text, String argsNameKey, String descrKey,
OptionKind kind, OptionGroup group,
- ChoiceKind choiceKind, Map<String,Boolean> choices,
+ ChoiceKind choiceKind, Set<String> choices,
ArgKind argKind) {
this.names = text.trim().split("\\s+");
Assert.check(names.length >= 1);
@@ -943,10 +937,10 @@
if (choices != null) {
String arg = option.substring(name.length());
if (choiceKind == ChoiceKind.ONEOF)
- return choices.keySet().contains(arg);
+ return choices.contains(arg);
else {
for (String a: arg.split(",+")) {
- if (!choices.keySet().contains(a))
+ if (!choices.contains(a))
return false;
}
}
@@ -1016,7 +1010,7 @@
if (choices != null) {
if (choiceKind == ChoiceKind.ONEOF) {
// some clients like to see just one of option+choice set
- for (String s: choices.keySet())
+ for (String s : choices)
helper.remove(primaryName + s);
String opt = primaryName + arg;
helper.put(opt, opt);
@@ -1113,12 +1107,10 @@
if (argsNameKey == null) {
if (choices != null) {
String sep = "{";
- for (Map.Entry<String,Boolean> e: choices.entrySet()) {
- if (!e.getValue()) {
- sb.append(sep);
- sb.append(e.getKey());
- sep = ",";
- }
+ for (String choice : choices) {
+ sb.append(sep);
+ sb.append(choices);
+ sep = ",";
}
sb.append("}");
}
@@ -1163,14 +1155,14 @@
}
}
- private static Map<String,Boolean> getXLintChoices() {
- Map<String,Boolean> choices = new LinkedHashMap<>();
- choices.put("all", false);
- for (Lint.LintCategory c : Lint.LintCategory.values())
- choices.put(c.option, c.hidden);
- for (Lint.LintCategory c : Lint.LintCategory.values())
- choices.put("-" + c.option, c.hidden);
- choices.put("none", false);
+ private static Set<String> getXLintChoices() {
+ Set<String> choices = new LinkedHashSet<>();
+ choices.add("all");
+ for (Lint.LintCategory c : Lint.LintCategory.values()) {
+ choices.add(c.option);
+ choices.add("-" + c.option);
+ }
+ choices.add("none");
return choices;
}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Oct 20 20:01:40 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties Thu Oct 20 13:44:51 2016 -0700
@@ -1321,14 +1321,31 @@
Some input files additionally use or override a deprecated API.
# 0: file name
+compiler.note.removal.filename=\
+ {0} uses or overrides a deprecated API that is marked for removal.
+
+compiler.note.removal.plural=\
+ Some input files use or override a deprecated API that is marked for removal.
+
+# The following string may appear after one of the above removal messages.
+compiler.note.removal.recompile=\
+ Recompile with -Xlint:removal for details.
+
+# 0: file name
+compiler.note.removal.filename.additional=\
+ {0} has additional uses or overrides of a deprecated API that is marked for removal.
+
+compiler.note.removal.plural.additional=\
+ Some input files additionally use or override a deprecated API that is marked for removal.
+
+# 0: file name
compiler.note.unchecked.filename=\
{0} uses unchecked or unsafe operations.
compiler.note.unchecked.plural=\
Some input files use unchecked or unsafe operations.
-# The following string may appear after one of the above deprecation
-# messages.
+# The following string may appear after one of the above unchecked messages.
compiler.note.unchecked.recompile=\
Recompile with -Xlint:unchecked for details.
@@ -1441,6 +1458,10 @@
compiler.warn.has.been.deprecated=\
{0} in {1} has been deprecated
+# 0: symbol, 1: symbol
+compiler.warn.has.been.deprecated.for.removal=\
+ {0} in {1} has been deprecated and marked for removal
+
# 0: symbol
compiler.warn.sun.proprietary=\
{0} is internal proprietary API and may be removed in a future release
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties Thu Oct 20 20:01:40 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties Thu Oct 20 13:44:51 2016 -0700
@@ -219,6 +219,9 @@
javac.opt.Xlint.desc.rawtypes=\
Warn about use of raw types.
+javac.opt.Xlint.desc.removal=\
+ Warn about use of API that has been marked for removal.
+
javac.opt.Xlint.desc.serial=\
Warn about Serializable classes that do not provide a serial version ID. \n\
\ Also warn about access to non-public members from a serializable element.
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java Thu Oct 20 20:01:40 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Names.java Thu Oct 20 13:44:51 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2016, 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
@@ -87,6 +87,7 @@
public final Name family;
public final Name finalize;
public final Name forName;
+ public final Name forRemoval;
public final Name getClass;
public final Name getClassLoader;
public final Name getComponentType;
@@ -242,6 +243,7 @@
family = fromString("family");
finalize = fromString("finalize");
forName = fromString("forName");
+ forRemoval = fromString("forRemoval");
getClass = fromString("getClass");
getClassLoader = fromString("getClassLoader");
getComponentType = fromString("getComponentType");
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Options.java Thu Oct 20 20:01:40 2016 +0000
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Options.java Thu Oct 20 13:44:51 2016 -0700
@@ -27,7 +27,6 @@
import java.util.*;
-import com.sun.tools.javac.code.Source;
import com.sun.tools.javac.main.Option;
import static com.sun.tools.javac.main.Option.*;
@@ -113,6 +112,18 @@
return (values.get(option.primaryName + value) != null);
}
+ /** Check if the value for a lint option has been explicitly set, either with -Xlint:opt
+ * or if all lint options have enabled and this one not disabled with -Xlint:-opt.
+ */
+ public boolean isLintSet(String s) {
+ // return true if either the specific option is enabled, or
+ // they are all enabled without the specific one being
+ // disabled
+ return
+ isSet(XLINT_CUSTOM, s) ||
+ (isSet(XLINT) || isSet(XLINT_CUSTOM, "all")) && isUnset(XLINT_CUSTOM, "-" + s);
+ }
+
/**
* Check if the value for an undocumented option has not been set.
*/
@@ -170,25 +181,4 @@
for (Runnable r: listeners)
r.run();
}
-
- /** Check for a lint suboption. */
- public boolean lint(String s) {
- // return true if either the specific option is enabled, or
- // they are all enabled without the specific one being
- // disabled
- return
- isSet(XLINT_CUSTOM, s) ||
- (isSet(XLINT) || isSet(XLINT_CUSTOM, "all") || (s.equals("dep-ann") && depAnnOnByDefault())) &&
- isUnset(XLINT_CUSTOM, "-" + s);
- }
- // where
- private boolean depAnnOnByDefault() {
- String sourceName = get(Option.SOURCE);
- Source source = null;
- if (sourceName != null)
- source = Source.lookup(sourceName);
- if (source == null)
- source = Source.DEFAULT;
- return source.compareTo(Source.JDK1_9) >= 0;
- }
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RemovalFilename.java Thu Oct 20 13:44:51 2016 -0700
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2010, 2016, 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.
+ */
+
+// key: compiler.note.removal.filename
+// key: compiler.note.removal.recompile
+// options: -Xlint:-removal
+
+class RemovalFilename {
+ RemovalClass d;
+}
+
+@Deprecated(forRemoval=true)
+class RemovalClass { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RemovalFilenameAdditional.java Thu Oct 20 13:44:51 2016 -0700
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010, 2016, 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.
+ */
+
+// key: compiler.note.removal.filename.additional
+// key: compiler.warn.has.been.deprecated.for.removal
+// options: -Xmaxwarns 1
+
+class RemovalFilename {
+ RemovalClass d;
+}
+
+class RemovalFilenameAdditional {
+ RemovalClass d;
+}
+
+@Deprecated(forRemoval=true)
+class RemovalClass { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RemovalPlural/RemovalClass.java Thu Oct 20 13:44:51 2016 -0700
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2010, 2016, 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.
+ */
+
+@Deprecated(forRemoval=true)
+class RemovalClass { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RemovalPlural/RemovalFilename.java Thu Oct 20 13:44:51 2016 -0700
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010, 2016, 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.
+ */
+
+class RemovalFileName {
+ RemovalClass d;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RemovalPlural/RemovalPlural.java Thu Oct 20 13:44:51 2016 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2010, 2016, 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.
+ */
+
+// key: compiler.note.removal.plural
+// key: compiler.note.removal.recompile
+// options: -Xlint:-removal
+
+class RemovalPlural {
+ RemovalClass d;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RemovalPluralAdditional/RemovalClass.java Thu Oct 20 13:44:51 2016 -0700
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2010, 2016, 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.
+ */
+
+@Deprecated(forRemoval=true)
+class RemovalClass { }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RemovalPluralAdditional/RemovalFilename.java Thu Oct 20 13:44:51 2016 -0700
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010, 2016, 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.
+ */
+
+class RemovalFileName {
+ RemovalClass d;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RemovalPluralAdditional/RemovalPlural.java Thu Oct 20 13:44:51 2016 -0700
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010, 2016, 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.
+ */
+
+class RemovalPlural {
+ RemovalClass d;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/diags/examples/RemovalPluralAdditional/RemovalPluralAdditional.java Thu Oct 20 13:44:51 2016 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2010, 2016, 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.
+ */
+
+// key: compiler.note.removal.plural.additional
+// key: compiler.warn.has.been.deprecated.for.removal
+// options: -Xlint:deprecation -Xmaxwarns 1
+
+class RemovalPluralAdditional {
+ RemovalClass d;
+}
--- a/langtools/test/tools/javac/processing/rounds/OverwriteBetweenCompilations.java Thu Oct 20 20:01:40 2016 +0000
+++ b/langtools/test/tools/javac/processing/rounds/OverwriteBetweenCompilations.java Thu Oct 20 13:44:51 2016 -0700
@@ -25,7 +25,7 @@
* @test
* @bug 8038455
* @summary Verify that annotation processor can overwrite source and class files it generated
- * during previous compilations, and that the Symbols are updated appropriatelly.
+ * during previous compilations, and that the Symbols are updated appropriately.
* @library /tools/lib /tools/javac/lib/
* @modules jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
--- a/langtools/test/tools/javac/profiles/ProfileOptionTest.java Thu Oct 20 20:01:40 2016 +0000
+++ b/langtools/test/tools/javac/profiles/ProfileOptionTest.java Thu Oct 20 13:44:51 2016 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2016, 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
@@ -176,9 +176,14 @@
Arrays.asList(fo));
task.analyze();
- List<String> expectDiagCodes = (p.value >= e.getKey().value)
- ? Collections.<String>emptyList()
- : Arrays.asList("compiler.err.not.in.profile");
+ List<String> expectDiagCodes = new ArrayList<>();
+ if (fo.getName().equals("TPolicyFile.java")) {
+ expectDiagCodes.add("compiler.warn.has.been.deprecated.for.removal");
+ }
+
+ if (p.value < e.getKey().value) {
+ expectDiagCodes.add("compiler.err.not.in.profile");
+ }
checkDiags(opts + " " + fo.getName(), dl.getDiagnostics(), expectDiagCodes);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/warnings/Removal.java Thu Oct 20 13:44:51 2016 -0700
@@ -0,0 +1,544 @@
+/*
+ * Copyright (c) 2016, 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 8145471
+ * @summary javac changes for enhanced deprecation
+ * @library /tools/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ * @modules jdk.compiler/com.sun.tools.javac.main
+ * @build toolbox.JavacTask toolbox.TestRunner toolbox.ToolBox
+ * @run main Removal
+ */
+
+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.Arrays;
+import java.util.EnumMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import toolbox.JavacTask;
+import toolbox.Task.Expect;
+import toolbox.Task.OutputKind;
+import toolbox.TestRunner;
+import toolbox.ToolBox;
+
+/*
+ * From JEP 277, JDK-8085614
+ *
+ * use site | API declaration site
+ * context | not dep. ord. dep. term. dep.
+ * +----------------------------------
+ * not dep. | N W W
+ * |
+ * ord. dep. | N N (2) W (4)
+ * |
+ * term. dep. | N N (3) W (5)
+ */
+
+public class Removal extends TestRunner {
+ public static void main(String... args) throws Exception {
+ Removal r = new Removal();
+ r.runTests(m -> new Object[] { Paths.get(m.getName()) });
+ r.report();
+ }
+
+ private final ToolBox tb = new ToolBox();
+ private final Path libSrc = Paths.get("lib").resolve("src");
+ private final Path libClasses = Paths.get("lib").resolve("classes");
+ int testCount = 0;
+
+ /**
+ * Options that may be used during compilation.
+ */
+ enum Options {
+ DEFAULT(),
+ XLINT_DEPRECATED("-Xlint:deprecation"),
+ XLINT_NO_REMOVAL("-Xlint:-removal");
+
+ Options(String... opts) {
+ this.opts = Arrays.asList(opts);
+ }
+
+ final List<String> opts;
+ }
+
+ /**
+ * The kind of deprecation.
+ */
+ enum DeprKind {
+ NONE("", null),
+ DEPRECATED("@Deprecated ", "compiler.warn.has.been.deprecated"),
+ REMOVAL("@Deprecated(forRemoval=true) ", "compiler.warn.has.been.deprecated.for.removal");
+ DeprKind(String anno, String warn) {
+ this.anno = anno;
+ this.warn = warn;
+ }
+ final String anno;
+ final String warn;
+ }
+
+ final String[] lib = {
+ "package lib; public class Class {\n"
+ + " public static void method() { }\n"
+ + " @Deprecated public static void depMethod() { }\n"
+ + " @Deprecated(forRemoval=true) public static void remMethod() { }\n"
+ + " public static int field;\n"
+ + " @Deprecated public static int depField;\n"
+ + " @Deprecated(forRemoval=true) public static int remField;\n"
+ + "}",
+ "package lib; @Deprecated public class DepClass { }",
+ "package lib; @Deprecated(forRemoval=true) public class RemClass { }"
+ };
+
+ /**
+ * The kind of declaration to be referenced at the use site.
+ */
+ enum RefKind {
+ CLASS("lib.%s c;", "Class", "DepClass", "RemClass"),
+ METHOD("{ lib.Class.%s(); }", "method", "depMethod", "remMethod"),
+ FIELD("int i = lib.Class.%s;", "field", "depField", "remField");
+
+ RefKind(String template, String def, String dep, String rem) {
+ fragments.put(DeprKind.NONE, String.format(template, def));
+ fragments.put(DeprKind.DEPRECATED, String.format(template, dep));
+ fragments.put(DeprKind.REMOVAL, String.format(template, rem));
+ }
+
+ String getFragment(DeprKind k) {
+ return fragments.get(k);
+ }
+
+ private final Map<DeprKind, String> fragments = new EnumMap<>(DeprKind.class);
+ }
+
+ /**
+ * Get source code for a reference to a possibly-deprecated item declared in a library.
+ * @param refKind the kind of element (class, method, field) being referenced
+ * @param declDeprKind the kind of deprecation on the declaration of the item being referenced
+ * @param useDeprKind the kind of deprecation enclosing the use site
+ * @return
+ */
+ static String getSource(RefKind refKind, DeprKind declDeprKind, DeprKind useDeprKind) {
+ return "package p; "
+ + useDeprKind.anno
+ + "class Class { "
+ + refKind.getFragment(declDeprKind)
+ + " }";
+ }
+
+ private static final String NO_OUTPUT = null;
+
+ public Removal() throws IOException {
+ super(System.err);
+ initLib();
+ }
+
+ void initLib() throws IOException {
+ tb.writeJavaFiles(libSrc, lib);
+
+ new JavacTask(tb)
+ .outdir(Files.createDirectories(libClasses))
+ .files(tb.findJavaFiles(libSrc))
+ .run()
+ .writeAll();
+ }
+
+ void report() {
+ out.println(testCount + " test cases");
+ }
+
+ /*
+ * Declaration site: not deprecated; use site: not deprecated
+ * Options: default
+ * Expect: no warnings
+ */
+ @Test
+ public void test_DeclNone_UseNone(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ test(base,
+ getSource(rk, DeprKind.NONE, DeprKind.NONE),
+ Options.DEFAULT,
+ NO_OUTPUT);
+ }
+ }
+
+ /*
+ * Declaration site: not deprecated; use site: deprecated
+ * Options: default
+ * Expect: no warnings
+ */
+ @Test
+ public void test_DeclNone_UseDeprecated(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ test(base,
+ getSource(rk, DeprKind.NONE, DeprKind.DEPRECATED),
+ Options.DEFAULT,
+ NO_OUTPUT);
+ }
+ }
+
+ /*
+ * Declaration site: not deprecated; use site: deprecated for removal
+ * Options: default
+ * Expect: no warnings
+ */
+ @Test
+ public void test_DeclNone_UseRemoval(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ test(base,
+ getSource(rk, DeprKind.NONE, DeprKind.REMOVAL),
+ Options.DEFAULT,
+ NO_OUTPUT);
+ }
+ }
+
+ /*
+ * Declaration site: deprecated; use site: not deprecated
+ * Options: default
+ * Expect: deprecated note
+ */
+ @Test
+ public void test_DeclDeprecated_UseNone_Default(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ test(base,
+ getSource(rk, DeprKind.DEPRECATED, DeprKind.NONE),
+ Options.DEFAULT,
+ "compiler.note.deprecated.filename: Class.java");
+ }
+ }
+
+ /*
+ * Declaration site: deprecated; use site: not deprecated
+ * Options: -Xlint:deprecation
+ * Expect: deprecated warning
+ */
+ @Test
+ public void test_DeclDeprecated_UseNone_XlintDep(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ String error = "<unset>";
+ switch (rk) {
+ case CLASS:
+ error = "Class.java:1:29: compiler.warn.has.been.deprecated: lib.DepClass, lib";
+ break;
+
+ case METHOD:
+ error = "Class.java:1:37: compiler.warn.has.been.deprecated: depMethod(), lib.Class";
+ break;
+
+ case FIELD:
+ error = "Class.java:1:43: compiler.warn.has.been.deprecated: depField, lib.Class";
+ break;
+ }
+
+ test(base,
+ getSource(rk, DeprKind.DEPRECATED, DeprKind.NONE),
+ Options.XLINT_DEPRECATED,
+ error);
+ }
+ }
+
+ /*
+ * Declaration site: deprecated; use site: deprecated
+ * Options: default
+ * Expect: no warnings
+ */
+ @Test
+ public void test_DeclDeprecated_UseDeprecated(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ test(base,
+ getSource(rk, DeprKind.DEPRECATED, DeprKind.DEPRECATED),
+ Options.DEFAULT,
+ NO_OUTPUT);
+ }
+ }
+
+ /*
+ * Declaration site: deprecated; use site: deprecated for removal
+ * Options: default
+ * Expect: no warnings
+ */
+ @Test
+ public void test_DeclDeprecated_UseRemoval(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ test(base,
+ getSource(rk, DeprKind.DEPRECATED, DeprKind.REMOVAL),
+ Options.DEFAULT,
+ NO_OUTPUT);
+ }
+ }
+
+ /*
+ * Declaration site: deprecated for removal; use site: not deprecated
+ * Options: default
+ * Expect: removal warning
+ */
+ @Test
+ public void test_DeclRemoval_UseNone_Default(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ String error = "<unset>";
+ switch (rk) {
+ case CLASS:
+ error = "Class.java:1:29: compiler.warn.has.been.deprecated.for.removal: lib.RemClass, lib";
+ break;
+
+ case METHOD:
+ error = "Class.java:1:37: compiler.warn.has.been.deprecated.for.removal: remMethod(), lib.Class";
+ break;
+
+ case FIELD:
+ error = "Class.java:1:43: compiler.warn.has.been.deprecated.for.removal: remField, lib.Class";
+ break;
+ }
+
+ test(base,
+ getSource(rk, DeprKind.REMOVAL, DeprKind.NONE),
+ Options.DEFAULT,
+ error);
+ }
+ }
+
+ /*
+ * Declaration site: deprecated for removal; use site: not deprecated
+ * Options: default, @SuppressWarnings("removal")
+ * Expect: removal warning
+ */
+ @Test
+ public void test_DeclRemoval_UseNone_SuppressRemoval(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ String source =
+ getSource(rk, DeprKind.REMOVAL, DeprKind.NONE)
+ .replace("class Class", "@SuppressWarnings(\"removal\") class Class");
+
+ test(base,
+ source,
+ Options.DEFAULT,
+ null);
+ }
+ }
+
+ /*
+ * Declaration site: deprecated for removal; use site: not deprecated
+ * Options: -Xlint:-removal
+ * Expect: removal note
+ */
+ @Test
+ public void test_DeclRemoval_UseNone_XlintNoRemoval(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ test(base,
+ getSource(rk, DeprKind.REMOVAL, DeprKind.NONE),
+ Options.XLINT_NO_REMOVAL,
+ "compiler.note.removal.filename: Class.java");
+ }
+ }
+
+ /*
+ * Declaration site: deprecated for removal; use site: deprecated
+ * Options: default
+ * Expect: removal warning
+ */
+ @Test
+ public void test_DeclRemoval_UseDeprecated_Default(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ String error = "<unset>";
+ switch (rk) {
+ case CLASS:
+ error = "Class.java:1:41: compiler.warn.has.been.deprecated.for.removal: lib.RemClass, lib";
+ break;
+
+ case METHOD:
+ error = "Class.java:1:49: compiler.warn.has.been.deprecated.for.removal: remMethod(), lib.Class";
+ break;
+
+ case FIELD:
+ error = "Class.java:1:55: compiler.warn.has.been.deprecated.for.removal: remField, lib.Class";
+ break;
+ }
+
+ test(base,
+ getSource(rk, DeprKind.REMOVAL, DeprKind.DEPRECATED),
+ Options.DEFAULT,
+ error);
+ }
+ }
+
+ /*
+ * Declaration site: deprecated for removal; use site: deprecated
+ * Options: -Xlint:-removal
+ * Expect: removal note
+ */
+ @Test
+ public void test_DeclRemoval_UseDeprecated_XlintNoRemoval(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ test(base,
+ getSource(rk, DeprKind.REMOVAL, DeprKind.DEPRECATED),
+ Options.XLINT_NO_REMOVAL,
+ "compiler.note.removal.filename: Class.java");
+ }
+ }
+
+ /*
+ * Declaration site: deprecated for removal; use site: deprecated for removal
+ * Options: default
+ * Expect: removal warning
+ */
+ @Test
+ public void test_DeclRemoval_UseRemoval_Default(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ String error = "<unset>";
+ switch (rk) {
+ case CLASS:
+ error = "Class.java:1:58: compiler.warn.has.been.deprecated.for.removal: lib.RemClass, lib";
+ break;
+
+ case METHOD:
+ error = "Class.java:1:66: compiler.warn.has.been.deprecated.for.removal: remMethod(), lib.Class";
+ break;
+
+ case FIELD:
+ error = "Class.java:1:72: compiler.warn.has.been.deprecated.for.removal: remField, lib.Class";
+ break;
+ }
+
+ test(base,
+ getSource(rk, DeprKind.REMOVAL, DeprKind.REMOVAL),
+ Options.DEFAULT,
+ error);
+ }
+ }
+
+ /*
+ * Declaration site: deprecated for removal; use site: deprecated for removal
+ * Options: -Xlint:-removal
+ * Expect: removal note
+ */
+ @Test
+ public void test_DeclRemoval_UseRemoval_XlintNoRemoval(Path base) throws IOException {
+ for (RefKind rk : RefKind.values()) {
+ test(base,
+ getSource(rk, DeprKind.REMOVAL, DeprKind.REMOVAL),
+ Options.XLINT_NO_REMOVAL,
+ "compiler.note.removal.filename: Class.java");
+ }
+ }
+
+ /*
+ * Additional special case:
+ * there should not be any warnings for any reference in a type-import statement.
+ */
+ @Test
+ public void test_UseImports(Path base) throws IOException {
+ String source =
+ "import lib.Class;\n"
+ + "import lib.DepClass;\n"
+ + "import lib.RemClass;\n"
+ + "class C { }";
+ for (Options o : Options.values()) {
+ test(base, source, o, NO_OUTPUT);
+ }
+ }
+
+ /**
+ * Compile source code with given options, and check for expected output.
+ * The compilation is done twice, first against the library in source form,
+ * and then again, against the compiled library.
+ * @param base base working directory
+ * @param source the source code to be compiled
+ * @param options the options for the compilation
+ * @param expectText the expected output, or NO_OUTPUT, if none expected.
+ * @throws IOException if an error occurs during the compilation
+ */
+ private void test(Path base, String source, Options options, String expectText) throws IOException {
+ test(base.resolve("lib-source"), libSrc, source, options, expectText);
+ test(base.resolve("lib-classes"), libClasses, source, options, expectText);
+ }
+
+ /**
+ * Compile source code with given options against a given version of the library,
+ * and check for expected output.
+ * @param base base working directory
+ * @param lib the directory containing the library, in either source or compiled form
+ * @param source the source code to be compiled
+ * @param options the options for the compilation
+ * @param expectText the expected output, or NO_OUTPUT, if none expected.
+ * @throws IOException if an error occurs during the compilation
+ */
+ private void test(Path base, Path lib, String source, Options options, String expectText)
+ throws IOException {
+ Expect expect = (expectText != null && expectText.contains("compiler.warn.")) ? Expect.FAIL : Expect.SUCCESS;
+ test(base, lib, source, options.opts, expect, expectText);
+ }
+
+ /**
+ * Compile source code with given options against a given version of the library,
+ * and check for expected exit code and expected output.
+ * @param base base working directory
+ * @param lib the directory containing the library, in either source or compiled form
+ * @param source the source code to be compiled
+ * @param options the options for the compilation
+ * @param expect the expected outcome of the compilation
+ * @param expectText the expected output, or NO_OUTPUT, if none expected.
+ * @throws IOException if an error occurs during the compilation
+ */
+ private void test(Path base, Path lib, String source, List<String> options,
+ Expect expect, String expectText) throws IOException {
+ testCount++;
+
+ Path src = base.resolve("src");
+ Path classes = Files.createDirectories(base.resolve("classes"));
+ tb.writeJavaFiles(src, source);
+
+ List<String> allOptions = new ArrayList<>();
+ allOptions.add("-XDrawDiagnostics");
+ allOptions.add("-Werror");
+ allOptions.addAll(options);
+
+ out.println("Source: " + source);
+ out.println("Classpath: " + lib);
+ out.println("Options: " + options.stream().collect(Collectors.joining(" ")));
+
+ String log = new JavacTask(tb)
+ .outdir(classes)
+ .classpath(lib) // use classpath for libSrc or libClasses
+ .files(tb.findJavaFiles(src))
+ .options(allOptions.toArray(new String[0]))
+ .run(expect)
+ .writeAll()
+ .getOutput(OutputKind.DIRECT);
+
+ if (expectText == null) {
+ if (!log.trim().isEmpty())
+ error("Unexpected text found: >>>" + log + "<<<");
+ } else {
+ if (!log.contains(expectText))
+ error("expected text not found: >>>" + expectText + "<<<");
+ }
+ }
+}
+