提交 d6dd33dc 编写于 作者: J jjg

6960424: new option -Xpkginfo for better control of when package-info.class is generated

Reviewed-by: mcimadamore
上级 3c29ac68
...@@ -295,4 +295,11 @@ public abstract class Attribute implements AnnotationValue { ...@@ -295,4 +295,11 @@ public abstract class Attribute implements AnnotationValue {
void visitEnum(Attribute.Enum e); void visitEnum(Attribute.Enum e);
void visitError(Attribute.Error e); void visitError(Attribute.Error e);
} }
/** A mirror of java.lang.annotation.RetentionPolicy. */
public static enum RetentionPolicy {
SOURCE,
CLASS,
RUNTIME
}
} }
...@@ -32,6 +32,7 @@ import com.sun.tools.javac.util.*; ...@@ -32,6 +32,7 @@ import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.List;
import com.sun.tools.javac.jvm.ClassReader; import com.sun.tools.javac.jvm.ClassReader;
import com.sun.tools.javac.code.Attribute.RetentionPolicy;
import com.sun.tools.javac.comp.Check; import com.sun.tools.javac.comp.Check;
import static com.sun.tools.javac.code.Type.*; import static com.sun.tools.javac.code.Type.*;
...@@ -3554,4 +3555,24 @@ public class Types { ...@@ -3554,4 +3555,24 @@ public class Types {
public Type visitType(Type t, S s) { return t; } public Type visitType(Type t, S s) { return t; }
} }
// </editor-fold> // </editor-fold>
// <editor-fold defaultstate="collapsed" desc="Annotation support">
public RetentionPolicy getRetention(Attribute.Compound a) {
RetentionPolicy vis = RetentionPolicy.CLASS; // the default
Attribute.Compound c = a.type.tsym.attribute(syms.retentionType.tsym);
if (c != null) {
Attribute value = c.member(names.value);
if (value != null && value instanceof Attribute.Enum) {
Name levelName = ((Attribute.Enum)value).value.name;
if (levelName == names.SOURCE) vis = RetentionPolicy.SOURCE;
else if (levelName == names.CLASS) vis = RetentionPolicy.CLASS;
else if (levelName == names.RUNTIME) vis = RetentionPolicy.RUNTIME;
else ;// /* fail soft */ throw new AssertionError(levelName);
}
}
return vis;
}
// </editor-fold>
} }
...@@ -38,6 +38,7 @@ import com.sun.tools.javac.util.List; ...@@ -38,6 +38,7 @@ import com.sun.tools.javac.util.List;
import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.main.RecognizedOptions.PkgInfo;
import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.tree.JCTree.*;
import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Flags.*;
...@@ -102,6 +103,7 @@ public class Enter extends JCTree.Visitor { ...@@ -102,6 +103,7 @@ public class Enter extends JCTree.Visitor {
Lint lint; Lint lint;
Names names; Names names;
JavaFileManager fileManager; JavaFileManager fileManager;
PkgInfo pkginfoOpt;
private final Todo todo; private final Todo todo;
...@@ -132,6 +134,9 @@ public class Enter extends JCTree.Visitor { ...@@ -132,6 +134,9 @@ public class Enter extends JCTree.Visitor {
predefClassDef.sym = syms.predefClass; predefClassDef.sym = syms.predefClass;
todo = Todo.instance(context); todo = Todo.instance(context);
fileManager = context.get(JavaFileManager.class); fileManager = context.get(JavaFileManager.class);
Options options = Options.instance(context);
pkginfoOpt = PkgInfo.get(options);
} }
/** A hashtable mapping classes and packages to the environments current /** A hashtable mapping classes and packages to the environments current
...@@ -278,7 +283,7 @@ public class Enter extends JCTree.Visitor { ...@@ -278,7 +283,7 @@ public class Enter extends JCTree.Visitor {
JavaFileObject.Kind.SOURCE); JavaFileObject.Kind.SOURCE);
if (tree.pid != null) { if (tree.pid != null) {
tree.packge = reader.enterPackage(TreeInfo.fullName(tree.pid)); tree.packge = reader.enterPackage(TreeInfo.fullName(tree.pid));
if (tree.packageAnnotations.nonEmpty()) { if (tree.packageAnnotations.nonEmpty() || pkginfoOpt == PkgInfo.ALWAYS) {
if (isPkgInfo) { if (isPkgInfo) {
addEnv = true; addEnv = true;
} else { } else {
......
...@@ -29,6 +29,7 @@ import java.util.*; ...@@ -29,6 +29,7 @@ import java.util.*;
import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.*;
import com.sun.tools.javac.jvm.*; import com.sun.tools.javac.jvm.*;
import com.sun.tools.javac.main.RecognizedOptions.PkgInfo;
import com.sun.tools.javac.tree.*; import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
...@@ -82,6 +83,7 @@ public class Lower extends TreeTranslator { ...@@ -82,6 +83,7 @@ public class Lower extends TreeTranslator {
private final Name classDollar; private final Name classDollar;
private Types types; private Types types;
private boolean debugLower; private boolean debugLower;
private PkgInfo pkginfoOpt;
protected Lower(Context context) { protected Lower(Context context) {
context.put(lowerKey, this); context.put(lowerKey, this);
...@@ -106,6 +108,7 @@ public class Lower extends TreeTranslator { ...@@ -106,6 +108,7 @@ public class Lower extends TreeTranslator {
types = Types.instance(context); types = Types.instance(context);
Options options = Options.instance(context); Options options = Options.instance(context);
debugLower = options.get("debuglower") != null; debugLower = options.get("debuglower") != null;
pkginfoOpt = PkgInfo.get(options);
} }
/** The currently enclosing class. /** The currently enclosing class.
...@@ -2161,7 +2164,7 @@ public class Lower extends TreeTranslator { ...@@ -2161,7 +2164,7 @@ public class Lower extends TreeTranslator {
} }
public void visitTopLevel(JCCompilationUnit tree) { public void visitTopLevel(JCCompilationUnit tree) {
if (tree.packageAnnotations.nonEmpty()) { if (needPackageInfoClass(tree)) {
Name name = names.package_info; Name name = names.package_info;
long flags = Flags.ABSTRACT | Flags.INTERFACE; long flags = Flags.ABSTRACT | Flags.INTERFACE;
if (target.isPackageInfoSynthetic()) if (target.isPackageInfoSynthetic())
...@@ -2183,6 +2186,23 @@ public class Lower extends TreeTranslator { ...@@ -2183,6 +2186,23 @@ public class Lower extends TreeTranslator {
translated.append(packageAnnotationsClass); translated.append(packageAnnotationsClass);
} }
} }
// where
private boolean needPackageInfoClass(JCCompilationUnit tree) {
switch (pkginfoOpt) {
case ALWAYS:
return true;
case LEGACY:
return tree.packageAnnotations.nonEmpty();
case NONEMPTY:
for (Attribute.Compound a: tree.packge.attributes_field) {
Attribute.RetentionPolicy p = types.getRetention(a);
if (p != Attribute.RetentionPolicy.SOURCE)
return true;
}
return false;
}
throw new AssertionError();
}
public void visitClassDef(JCClassDecl tree) { public void visitClassDef(JCClassDecl tree) {
ClassSymbol currentClassPrev = currentClass; ClassSymbol currentClassPrev = currentClass;
......
...@@ -34,6 +34,7 @@ import javax.tools.FileObject; ...@@ -34,6 +34,7 @@ import javax.tools.FileObject;
import javax.tools.JavaFileObject; import javax.tools.JavaFileObject;
import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Attribute.RetentionPolicy;
import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.file.BaseFileObject; import com.sun.tools.javac.file.BaseFileObject;
...@@ -692,7 +693,7 @@ public class ClassWriter extends ClassFile { ...@@ -692,7 +693,7 @@ public class ClassWriter extends ClassFile {
boolean hasInvisible = false; boolean hasInvisible = false;
if (m.params != null) for (VarSymbol s : m.params) { if (m.params != null) for (VarSymbol s : m.params) {
for (Attribute.Compound a : s.getAnnotationMirrors()) { for (Attribute.Compound a : s.getAnnotationMirrors()) {
switch (getRetention(a.type.tsym)) { switch (types.getRetention(a)) {
case SOURCE: break; case SOURCE: break;
case CLASS: hasInvisible = true; break; case CLASS: hasInvisible = true; break;
case RUNTIME: hasVisible = true; break; case RUNTIME: hasVisible = true; break;
...@@ -708,7 +709,7 @@ public class ClassWriter extends ClassFile { ...@@ -708,7 +709,7 @@ public class ClassWriter extends ClassFile {
for (VarSymbol s : m.params) { for (VarSymbol s : m.params) {
ListBuffer<Attribute.Compound> buf = new ListBuffer<Attribute.Compound>(); ListBuffer<Attribute.Compound> buf = new ListBuffer<Attribute.Compound>();
for (Attribute.Compound a : s.getAnnotationMirrors()) for (Attribute.Compound a : s.getAnnotationMirrors())
if (getRetention(a.type.tsym) == RetentionPolicy.RUNTIME) if (types.getRetention(a) == RetentionPolicy.RUNTIME)
buf.append(a); buf.append(a);
databuf.appendChar(buf.length()); databuf.appendChar(buf.length());
for (Attribute.Compound a : buf) for (Attribute.Compound a : buf)
...@@ -723,7 +724,7 @@ public class ClassWriter extends ClassFile { ...@@ -723,7 +724,7 @@ public class ClassWriter extends ClassFile {
for (VarSymbol s : m.params) { for (VarSymbol s : m.params) {
ListBuffer<Attribute.Compound> buf = new ListBuffer<Attribute.Compound>(); ListBuffer<Attribute.Compound> buf = new ListBuffer<Attribute.Compound>();
for (Attribute.Compound a : s.getAnnotationMirrors()) for (Attribute.Compound a : s.getAnnotationMirrors())
if (getRetention(a.type.tsym) == RetentionPolicy.CLASS) if (types.getRetention(a) == RetentionPolicy.CLASS)
buf.append(a); buf.append(a);
databuf.appendChar(buf.length()); databuf.appendChar(buf.length());
for (Attribute.Compound a : buf) for (Attribute.Compound a : buf)
...@@ -747,7 +748,7 @@ public class ClassWriter extends ClassFile { ...@@ -747,7 +748,7 @@ public class ClassWriter extends ClassFile {
ListBuffer<Attribute.Compound> visibles = new ListBuffer<Attribute.Compound>(); ListBuffer<Attribute.Compound> visibles = new ListBuffer<Attribute.Compound>();
ListBuffer<Attribute.Compound> invisibles = new ListBuffer<Attribute.Compound>(); ListBuffer<Attribute.Compound> invisibles = new ListBuffer<Attribute.Compound>();
for (Attribute.Compound a : attrs) { for (Attribute.Compound a : attrs) {
switch (getRetention(a.type.tsym)) { switch (types.getRetention(a)) {
case SOURCE: break; case SOURCE: break;
case CLASS: invisibles.append(a); break; case CLASS: invisibles.append(a); break;
case RUNTIME: visibles.append(a); break; case RUNTIME: visibles.append(a); break;
...@@ -785,7 +786,7 @@ public class ClassWriter extends ClassFile { ...@@ -785,7 +786,7 @@ public class ClassWriter extends ClassFile {
if (tc.position.type == TargetType.UNKNOWN if (tc.position.type == TargetType.UNKNOWN
|| !tc.position.emitToClassfile()) || !tc.position.emitToClassfile())
continue; continue;
switch (getRetention(tc.type.tsym)) { switch (types.getRetention(tc)) {
case SOURCE: break; case SOURCE: break;
case CLASS: invisibles.append(tc); break; case CLASS: invisibles.append(tc); break;
case RUNTIME: visibles.append(tc); break; case RUNTIME: visibles.append(tc); break;
...@@ -815,29 +816,6 @@ public class ClassWriter extends ClassFile { ...@@ -815,29 +816,6 @@ public class ClassWriter extends ClassFile {
return attrCount; return attrCount;
} }
/** A mirror of java.lang.annotation.RetentionPolicy. */
enum RetentionPolicy {
SOURCE,
CLASS,
RUNTIME
}
RetentionPolicy getRetention(TypeSymbol annotationType) {
RetentionPolicy vis = RetentionPolicy.CLASS; // the default
Attribute.Compound c = annotationType.attribute(syms.retentionType.tsym);
if (c != null) {
Attribute value = c.member(names.value);
if (value != null && value instanceof Attribute.Enum) {
Name levelName = ((Attribute.Enum)value).value.name;
if (levelName == names.SOURCE) vis = RetentionPolicy.SOURCE;
else if (levelName == names.CLASS) vis = RetentionPolicy.CLASS;
else if (levelName == names.RUNTIME) vis = RetentionPolicy.RUNTIME;
else ;// /* fail soft */ throw new AssertionError(levelName);
}
}
return vis;
}
/** A visitor to write an attribute including its leading /** A visitor to write an attribute including its leading
* single-character marker. * single-character marker.
*/ */
......
...@@ -80,6 +80,7 @@ public enum OptionName { ...@@ -80,6 +80,7 @@ public enum OptionName {
XMAXERRS("-Xmaxerrs"), XMAXERRS("-Xmaxerrs"),
XMAXWARNS("-Xmaxwarns"), XMAXWARNS("-Xmaxwarns"),
XSTDOUT("-Xstdout"), XSTDOUT("-Xstdout"),
XPKGINFO("-Xpkginfo:"),
XPRINT("-Xprint"), XPRINT("-Xprint"),
XPRINTROUNDS("-XprintRounds"), XPRINTROUNDS("-XprintRounds"),
XPRINTPROCESSORINFO("-XprintProcessorInfo"), XPRINTPROCESSORINFO("-XprintProcessorInfo"),
......
...@@ -160,6 +160,7 @@ public class RecognizedOptions { ...@@ -160,6 +160,7 @@ public class RecognizedOptions {
XMAXERRS, XMAXERRS,
XMAXWARNS, XMAXWARNS,
XSTDOUT, XSTDOUT,
XPKGINFO,
XPRINT, XPRINT,
XPRINTROUNDS, XPRINTROUNDS,
XPRINTPROCESSORINFO, XPRINTPROCESSORINFO,
...@@ -217,6 +218,7 @@ public class RecognizedOptions { ...@@ -217,6 +218,7 @@ public class RecognizedOptions {
XMAXERRS, XMAXERRS,
XMAXWARNS, XMAXWARNS,
// XSTDOUT, // XSTDOUT,
XPKGINFO,
XPRINT, XPRINT,
XPRINTROUNDS, XPRINTROUNDS,
XPRINTPROCESSORINFO, XPRINTPROCESSORINFO,
...@@ -532,6 +534,9 @@ public class RecognizedOptions { ...@@ -532,6 +534,9 @@ public class RecognizedOptions {
new XOption(XPREFER, "opt.prefer", new XOption(XPREFER, "opt.prefer",
Option.ChoiceKind.ONEOF, "source", "newer"), Option.ChoiceKind.ONEOF, "source", "newer"),
new XOption(XPKGINFO, "opt.pkginfo",
Option.ChoiceKind.ONEOF, "always", "legacy", "nonempty"),
/* -O is a no-op, accepted for backward compatibility. */ /* -O is a no-op, accepted for backward compatibility. */
new HiddenOption(O), new HiddenOption(O),
...@@ -598,6 +603,16 @@ public class RecognizedOptions { ...@@ -598,6 +603,16 @@ public class RecognizedOptions {
}; };
} }
public enum PkgInfo {
ALWAYS, LEGACY, NONEMPTY;
public static PkgInfo get(Options options) {
String v = options.get(XPKGINFO);
return (v == null
? PkgInfo.LEGACY
: PkgInfo.valueOf(v.toUpperCase()));
}
}
private static Map<String,Boolean> getXLintChoices() { private static Map<String,Boolean> getXLintChoices() {
Map<String,Boolean> choices = new LinkedHashMap<String,Boolean>(); Map<String,Boolean> choices = new LinkedHashMap<String,Boolean>();
choices.put("all", false); choices.put("all", false);
......
...@@ -74,7 +74,9 @@ javac.opt.Werror=\ ...@@ -74,7 +74,9 @@ javac.opt.Werror=\
javac.opt.A=\ javac.opt.A=\
Options to pass to annotation processors Options to pass to annotation processors
javac.opt.implicit=\ javac.opt.implicit=\
Specify whether or not to generate class files for implicitly referenced files Specify whether or not to generate class files for implicitly referenced files
javac.opt.pkginfo=\
Specify handling of package-info files
javac.opt.arg.class=\ javac.opt.arg.class=\
<class> <class>
javac.opt.arg.class.list=\ javac.opt.arg.class.list=\
...@@ -189,7 +191,7 @@ javac.msg.usage=\ ...@@ -189,7 +191,7 @@ javac.msg.usage=\
javac.msg.usage.nonstandard.footer=\ javac.msg.usage.nonstandard.footer=\
These options are non-standard and subject to change without notice. These options are non-standard and subject to change without notice.
javac.msg.bug=\ javac.msg.bug=\
An exception has occurred in the compiler ({0}). \ An exception has occurred in the compiler ({0}). \
Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport) \ Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport) \
......
/*
* Copyright (c) 2010, 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 6960424
* @summary new option -Xpkginfo for better control of when package-info.class is generated
*/
import java.io.*;
import java.util.*;
public class TestPkgInfo {
enum OptKind {
NONE(null),
ALWAYS("-Xpkginfo:always"),
NONEMPTY("-Xpkginfo:nonempty"),
LEGACY("-Xpkginfo:legacy");
OptKind(String opt) { this.opt = opt; }
final String opt;
};
public static void main(String... args) throws Exception {
new TestPkgInfo().run(args);
}
public void run(String... args) throws Exception {
boolean[] booleanValues = { false, true };
for (OptKind ok: OptKind.values()) {
for (boolean sr: booleanValues) {
for (boolean cr: booleanValues) {
for (boolean rr: booleanValues) {
try {
test(ok, sr, cr, rr);
} catch (Exception e) {
error("Exception: " + e);
}
if (errors > 0) throw new AssertionError();
}
}
}
}
if (errors > 0)
throw new Exception(errors + " errors occurred");
}
void test(OptKind ok, boolean sr, boolean cr, boolean rr) throws Exception {
count++;
System.err.println("Test " + count + ": ok:" + ok + " sr:" + sr + " cr:" + cr + " rr:" + rr);
StringBuilder sb = new StringBuilder();
// create annotated package statement with all combinations of retention policy
if (sr) sb.append("@SR\n");
if (cr) sb.append("@CR\n");
if (rr) sb.append("@RR\n");
sb.append("package p;\n");
sb.append("\n");
sb.append("import java.lang.annotation.*;\n");
sb.append("@Retention(RetentionPolicy.SOURCE) @interface SR { }\n");
sb.append("@Retention(RetentionPolicy.CLASS) @interface CR { }\n");
sb.append("@Retention(RetentionPolicy.RUNTIME) @interface RR { }\n");
// test specific tmp directory
File tmpDir = new File("tmp.test" + count);
File classesDir = new File(tmpDir, "classes");
classesDir.mkdirs();
File pkginfo_java = new File(new File(tmpDir, "src"), "package-info.java");
writeFile(pkginfo_java, sb.toString());
// build up list of options and files to be compiled
List<String> opts = new ArrayList<String>();
List<File> files = new ArrayList<File>();
opts.add("-d");
opts.add(classesDir.getPath());
if (ok.opt != null)
opts.add(ok.opt);
//opts.add("-verbose");
files.add(pkginfo_java);
compile(opts, files);
File pkginfo_class = new File(new File(classesDir, "p"), "package-info.class");
boolean exists = pkginfo_class.exists();
boolean expected;
switch (ok) {
case ALWAYS:
expected = true;
break;
case LEGACY:
case NONE:
expected = (sr || cr || rr ); // any annotation
break;
case NONEMPTY:
expected = (cr || rr ); // any annotation in class file
break;
default:
throw new IllegalStateException();
}
if (exists && !expected)
error("package-info.class found but not expected");
if (!exists && expected)
error("package-info.class expected but not found");
}
/** Compile files with options provided. */
void compile(List<String> opts, List<File> files) throws Exception {
System.err.println("javac: " + opts + " " + files);
List<String> args = new ArrayList<String>();
args.addAll(opts);
for (File f: files)
args.add(f.getPath());
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()]), pw);
pw.flush();
if (sw.getBuffer().length() > 0)
System.err.println(sw.toString());
if (rc != 0)
throw new Exception("compilation failed: rc=" + rc);
}
/** Write a file with a given body. */
void writeFile(File f, String body) throws Exception {
if (f.getParentFile() != null)
f.getParentFile().mkdirs();
Writer out = new FileWriter(f);
try {
out.write(body);
} finally {
out.close();
}
}
/** Report an error. */
void error(String msg) {
System.err.println("Error: " + msg);
errors++;
}
/** Test case counter. */
int count;
/** Number of errors found. */
int errors;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册