提交 177f654c 编写于 作者: T tbell

Merge

...@@ -76,6 +76,10 @@ public class AccessFlags { ...@@ -76,6 +76,10 @@ public class AccessFlags {
return (flags & mask) != 0; return (flags & mask) != 0;
} }
public int byteLength() {
return 2;
}
private static final int[] classModifiers = { private static final int[] classModifiers = {
ACC_PUBLIC, ACC_FINAL, ACC_ABSTRACT, ACC_MODULE ACC_PUBLIC, ACC_FINAL, ACC_ABSTRACT, ACC_MODULE
}; };
......
...@@ -166,6 +166,10 @@ public abstract class Attribute { ...@@ -166,6 +166,10 @@ public abstract class Attribute {
public abstract <R,D> R accept(Attribute.Visitor<R,D> visitor, D data); public abstract <R,D> R accept(Attribute.Visitor<R,D> visitor, D data);
public int byteLength() {
return 6 + attribute_length;
}
public final int attribute_name_index; public final int attribute_name_index;
public final int attribute_length; public final int attribute_length;
......
...@@ -95,6 +95,13 @@ public class Attributes implements Iterable<Attribute> { ...@@ -95,6 +95,13 @@ public class Attributes implements Iterable<Attribute> {
return attrs.length; return attrs.length;
} }
public int byteLength() {
int length = 2;
for (Attribute a: attrs)
length += a.byteLength();
return length;
}
public final Attribute[] attrs; public final Attribute[] attrs;
public final Map<String, Attribute> map; public final Map<String, Attribute> map;
} }
...@@ -58,7 +58,7 @@ public class CharacterRangeTable_attribute extends Attribute { ...@@ -58,7 +58,7 @@ public class CharacterRangeTable_attribute extends Attribute {
} }
public CharacterRangeTable_attribute(int name_index, Entry[] character_range_table) { public CharacterRangeTable_attribute(int name_index, Entry[] character_range_table) {
super(name_index, character_range_table.length * Entry.length()); super(name_index, 2 + character_range_table.length * Entry.length());
this.character_range_table = character_range_table; this.character_range_table = character_range_table;
} }
......
...@@ -139,6 +139,38 @@ public class ClassFile { ...@@ -139,6 +139,38 @@ public class ClassFile {
return access_flags.is(ACC_INTERFACE); return access_flags.is(ACC_INTERFACE);
} }
public int byteLength() {
return 4 + // magic
2 + // minor
2 + // major
constant_pool.byteLength() +
2 + // access flags
2 + // this_class
2 + // super_class
byteLength(interfaces) +
byteLength(fields) +
byteLength(methods) +
attributes.byteLength();
}
private int byteLength(int[] indices) {
return 2 + 2 * indices.length;
}
private int byteLength(Field[] fields) {
int length = 2;
for (Field f: fields)
length += f.byteLength();
return length;
}
private int byteLength(Method[] methods) {
int length = 2;
for (Method m: methods)
length += m.byteLength();
return length;
}
public final int magic; public final int magic;
public final int minor_version; public final int minor_version;
public final int major_version; public final int major_version;
......
...@@ -25,7 +25,9 @@ ...@@ -25,7 +25,9 @@
package com.sun.tools.classfile; package com.sun.tools.classfile;
import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator; import java.util.Iterator;
/** /**
...@@ -179,6 +181,16 @@ public class ConstantPool { ...@@ -179,6 +181,16 @@ public class ConstantPool {
return pool.length; return pool.length;
} }
public int byteLength() {
int length = 2;
for (int i = 1; i < size(); ) {
CPInfo cpInfo = pool[i];
length += cpInfo.byteLength();
i += cpInfo.size();
}
return length;
}
public CPInfo get(int index) throws InvalidIndex { public CPInfo get(int index) throws InvalidIndex {
if (index <= 0 || index >= pool.length) if (index <= 0 || index >= pool.length)
throw new InvalidIndex(index); throw new InvalidIndex(index);
...@@ -291,6 +303,8 @@ public class ConstantPool { ...@@ -291,6 +303,8 @@ public class ConstantPool {
return 1; return 1;
} }
public abstract int byteLength();
public abstract <R,D> R accept(Visitor<R,D> visitor, D data); public abstract <R,D> R accept(Visitor<R,D> visitor, D data);
protected final ConstantPool cp; protected final ConstantPool cp;
...@@ -315,6 +329,10 @@ public class ConstantPool { ...@@ -315,6 +329,10 @@ public class ConstantPool {
return tag; return tag;
} }
public int byteLength() {
return 5;
}
public CONSTANT_Class_info getClassInfo() throws ConstantPoolException { public CONSTANT_Class_info getClassInfo() throws ConstantPoolException {
return cp.getClassInfo(class_index); return cp.getClassInfo(class_index);
} }
...@@ -347,6 +365,10 @@ public class ConstantPool { ...@@ -347,6 +365,10 @@ public class ConstantPool {
return CONSTANT_Class; return CONSTANT_Class;
} }
public int byteLength() {
return 3;
}
public String getName() throws ConstantPoolException { public String getName() throws ConstantPoolException {
return cp.getUTF8Value(name_index); return cp.getUTF8Value(name_index);
} }
...@@ -390,6 +412,10 @@ public class ConstantPool { ...@@ -390,6 +412,10 @@ public class ConstantPool {
return CONSTANT_Double; return CONSTANT_Double;
} }
public int byteLength() {
return 9;
}
@Override @Override
public int size() { public int size() {
return 2; return 2;
...@@ -439,6 +465,10 @@ public class ConstantPool { ...@@ -439,6 +465,10 @@ public class ConstantPool {
return CONSTANT_Float; return CONSTANT_Float;
} }
public int byteLength() {
return 5;
}
@Override @Override
public String toString() { public String toString() {
return "CONSTANT_Float_info[value: " + value + "]"; return "CONSTANT_Float_info[value: " + value + "]";
...@@ -464,6 +494,10 @@ public class ConstantPool { ...@@ -464,6 +494,10 @@ public class ConstantPool {
return CONSTANT_Integer; return CONSTANT_Integer;
} }
public int byteLength() {
return 5;
}
@Override @Override
public String toString() { public String toString() {
return "CONSTANT_Integer_info[value: " + value + "]"; return "CONSTANT_Integer_info[value: " + value + "]";
...@@ -513,6 +547,10 @@ public class ConstantPool { ...@@ -513,6 +547,10 @@ public class ConstantPool {
return 2; return 2;
} }
public int byteLength() {
return 9;
}
@Override @Override
public String toString() { public String toString() {
return "CONSTANT_Long_info[value: " + value + "]"; return "CONSTANT_Long_info[value: " + value + "]";
...@@ -561,6 +599,10 @@ public class ConstantPool { ...@@ -561,6 +599,10 @@ public class ConstantPool {
return CONSTANT_NameAndType; return CONSTANT_NameAndType;
} }
public int byteLength() {
return 5;
}
public String getName() throws ConstantPoolException { public String getName() throws ConstantPoolException {
return cp.getUTF8Value(name_index); return cp.getUTF8Value(name_index);
} }
...@@ -597,6 +639,10 @@ public class ConstantPool { ...@@ -597,6 +639,10 @@ public class ConstantPool {
return CONSTANT_String; return CONSTANT_String;
} }
public int byteLength() {
return 3;
}
public String getString() throws ConstantPoolException { public String getString() throws ConstantPoolException {
return cp.getUTF8Value(string_index); return cp.getUTF8Value(string_index);
} }
...@@ -626,6 +672,20 @@ public class ConstantPool { ...@@ -626,6 +672,20 @@ public class ConstantPool {
return CONSTANT_Utf8; return CONSTANT_Utf8;
} }
public int byteLength() {
class SizeOutputStream extends OutputStream {
@Override
public void write(int b) throws IOException {
size++;
}
int size;
}
SizeOutputStream sizeOut = new SizeOutputStream();
DataOutputStream out = new DataOutputStream(sizeOut);
try { out.writeUTF(value); } catch (IOException ignore) { }
return 1 + sizeOut.size;
}
@Override @Override
public String toString() { public String toString() {
if (value.length() < 32 && isPrintableAscii(value)) if (value.length() < 32 && isPrintableAscii(value))
......
...@@ -260,9 +260,6 @@ public class ExtendedAnnotation { ...@@ -260,9 +260,6 @@ public class ExtendedAnnotation {
// For generic/array types. // For generic/array types.
public List<Integer> location = new ArrayList<Integer>(); public List<Integer> location = new ArrayList<Integer>();
// Tree position.
public int pos = -1;
// For typecasts, type tests, new (and locals, as start_pc). // For typecasts, type tests, new (and locals, as start_pc).
public int offset = -1; public int offset = -1;
...@@ -391,9 +388,6 @@ public class ExtendedAnnotation { ...@@ -391,9 +388,6 @@ public class ExtendedAnnotation {
sb.append(")"); sb.append(")");
} }
sb.append(", pos = ");
sb.append(pos);
sb.append(']'); sb.append(']');
return sb.toString(); return sb.toString();
} }
......
...@@ -50,6 +50,10 @@ public class Field { ...@@ -50,6 +50,10 @@ public class Field {
this.attributes = attributes; this.attributes = attributes;
} }
public int byteLength() {
return 6 + attributes.byteLength();
}
public String getName(ConstantPool constant_pool) throws ConstantPoolException { public String getName(ConstantPool constant_pool) throws ConstantPoolException {
return constant_pool.getUTF8Value(name_index); return constant_pool.getUTF8Value(name_index);
} }
......
...@@ -50,7 +50,7 @@ public class LineNumberTable_attribute extends Attribute { ...@@ -50,7 +50,7 @@ public class LineNumberTable_attribute extends Attribute {
} }
public LineNumberTable_attribute(int name_index, Entry[] line_number_table) { public LineNumberTable_attribute(int name_index, Entry[] line_number_table) {
super(name_index, line_number_table.length * Entry.length()); super(name_index, 2 + line_number_table.length * Entry.length());
this.line_number_table_length = line_number_table.length; this.line_number_table_length = line_number_table.length;
this.line_number_table = line_number_table; this.line_number_table = line_number_table;
} }
......
...@@ -50,7 +50,7 @@ public class LocalVariableTable_attribute extends Attribute { ...@@ -50,7 +50,7 @@ public class LocalVariableTable_attribute extends Attribute {
} }
public LocalVariableTable_attribute(int name_index, Entry[] local_variable_table) { public LocalVariableTable_attribute(int name_index, Entry[] local_variable_table) {
super(name_index, local_variable_table.length * Entry.length()); super(name_index, 2 + local_variable_table.length * Entry.length());
this.local_variable_table_length = local_variable_table.length; this.local_variable_table_length = local_variable_table.length;
this.local_variable_table = local_variable_table; this.local_variable_table = local_variable_table;
} }
......
...@@ -50,7 +50,7 @@ public class LocalVariableTypeTable_attribute extends Attribute { ...@@ -50,7 +50,7 @@ public class LocalVariableTypeTable_attribute extends Attribute {
} }
public LocalVariableTypeTable_attribute(int name_index, Entry[] local_variable_table) { public LocalVariableTypeTable_attribute(int name_index, Entry[] local_variable_table) {
super(name_index, local_variable_table.length * Entry.length()); super(name_index, 2 + local_variable_table.length * Entry.length());
this.local_variable_table_length = local_variable_table.length; this.local_variable_table_length = local_variable_table.length;
this.local_variable_table = local_variable_table; this.local_variable_table = local_variable_table;
} }
......
...@@ -50,6 +50,10 @@ public class Method { ...@@ -50,6 +50,10 @@ public class Method {
this.attributes = attributes; this.attributes = attributes;
} }
public int byteLength() {
return 6 + attributes.byteLength();
}
public String getName(ConstantPool constant_pool) throws ConstantPoolException { public String getName(ConstantPool constant_pool) throws ConstantPoolException {
return constant_pool.getUTF8Value(name_index); return constant_pool.getUTF8Value(name_index);
} }
......
...@@ -50,7 +50,7 @@ public class ModuleExportTable_attribute extends Attribute { ...@@ -50,7 +50,7 @@ public class ModuleExportTable_attribute extends Attribute {
} }
public ModuleExportTable_attribute(int name_index, int[] export_type_table) { public ModuleExportTable_attribute(int name_index, int[] export_type_table) {
super(name_index, 2 * export_type_table.length); super(name_index, 2 + 2 * export_type_table.length);
this.export_type_table = export_type_table; this.export_type_table = export_type_table;
} }
......
...@@ -49,7 +49,7 @@ public class ModuleMemberTable_attribute extends Attribute { ...@@ -49,7 +49,7 @@ public class ModuleMemberTable_attribute extends Attribute {
} }
public ModuleMemberTable_attribute(int name_index, int[] package_member_table) { public ModuleMemberTable_attribute(int name_index, int[] package_member_table) {
super(name_index, 2 * package_member_table.length); super(name_index, 2 + 2 * package_member_table.length);
this.package_member_table = package_member_table; this.package_member_table = package_member_table;
} }
......
...@@ -1197,21 +1197,9 @@ public abstract class Symbol implements Element { ...@@ -1197,21 +1197,9 @@ public abstract class Symbol implements Element {
* as possible implementations. * as possible implementations.
*/ */
public MethodSymbol implementation(TypeSymbol origin, Types types, boolean checkResult) { public MethodSymbol implementation(TypeSymbol origin, Types types, boolean checkResult) {
for (Type t = origin.type; t.tag == CLASS || t.tag == TYPEVAR; t = types.supertype(t)) { MethodSymbol res = types.implementation(this, origin, types, checkResult);
while (t.tag == TYPEVAR) if (res != null)
t = t.getUpperBound(); return res;
TypeSymbol c = t.tsym;
for (Scope.Entry e = c.members().lookup(name);
e.scope != null;
e = e.next()) {
if (e.sym.kind == MTH) {
MethodSymbol m = (MethodSymbol) e.sym;
if (m.overrides(this, origin, types, checkResult) &&
(m.flags() & SYNTHETIC) == 0)
return m;
}
}
}
// if origin is derived from a raw type, we might have missed // if origin is derived from a raw type, we might have missed
// an implementation because we do not know enough about instantiations. // an implementation because we do not know enough about instantiations.
// in this case continue with the supertype as origin. // in this case continue with the supertype as origin.
......
...@@ -25,10 +25,9 @@ ...@@ -25,10 +25,9 @@
package com.sun.tools.javac.code; package com.sun.tools.javac.code;
import java.lang.ref.SoftReference;
import java.util.*; import java.util.*;
import com.sun.tools.javac.api.Messages;
import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.List;
...@@ -1442,7 +1441,7 @@ public class Types { ...@@ -1442,7 +1441,7 @@ public class Types {
return (sym.flags() & STATIC) != 0 return (sym.flags() & STATIC) != 0
? sym.type ? sym.type
: memberType.visit(t, sym); : memberType.visit(t, sym);
} }
// where // where
private SimpleVisitor<Type,Symbol> memberType = new SimpleVisitor<Type,Symbol>() { private SimpleVisitor<Type,Symbol> memberType = new SimpleVisitor<Type,Symbol>() {
...@@ -1552,7 +1551,7 @@ public class Types { ...@@ -1552,7 +1551,7 @@ public class Types {
return t; /* fast special case */ return t; /* fast special case */
else else
return erasure.visit(t, recurse); return erasure.visit(t, recurse);
} }
// where // where
private SimpleVisitor<Type, Boolean> erasure = new SimpleVisitor<Type, Boolean>() { private SimpleVisitor<Type, Boolean> erasure = new SimpleVisitor<Type, Boolean>() {
public Type visitType(Type t, Boolean recurse) { public Type visitType(Type t, Boolean recurse) {
...@@ -1946,6 +1945,45 @@ public class Types { ...@@ -1946,6 +1945,45 @@ public class Types {
hasSameArgs(t, erasure(s)) || hasSameArgs(erasure(t), s); hasSameArgs(t, erasure(s)) || hasSameArgs(erasure(t), s);
} }
private WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, MethodSymbol>>> implCache_check =
new WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, MethodSymbol>>>();
private WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, MethodSymbol>>> implCache_nocheck =
new WeakHashMap<MethodSymbol, SoftReference<Map<TypeSymbol, MethodSymbol>>>();
public MethodSymbol implementation(MethodSymbol ms, TypeSymbol origin, Types types, boolean checkResult) {
Map<MethodSymbol, SoftReference<Map<TypeSymbol, MethodSymbol>>> implCache = checkResult ?
implCache_check : implCache_nocheck;
SoftReference<Map<TypeSymbol, MethodSymbol>> ref_cache = implCache.get(ms);
Map<TypeSymbol, MethodSymbol> cache = ref_cache != null ? ref_cache.get() : null;
if (cache == null) {
cache = new HashMap<TypeSymbol, MethodSymbol>();
implCache.put(ms, new SoftReference<Map<TypeSymbol, MethodSymbol>>(cache));
}
MethodSymbol impl = cache.get(origin);
if (impl == null) {
for (Type t = origin.type; t.tag == CLASS || t.tag == TYPEVAR; t = types.supertype(t)) {
while (t.tag == TYPEVAR)
t = t.getUpperBound();
TypeSymbol c = t.tsym;
for (Scope.Entry e = c.members().lookup(ms.name);
e.scope != null;
e = e.next()) {
if (e.sym.kind == Kinds.MTH) {
MethodSymbol m = (MethodSymbol) e.sym;
if (m.overrides(ms, origin, types, checkResult) &&
(m.flags() & SYNTHETIC) == 0) {
impl = m;
cache.put(origin, m);
return impl;
}
}
}
}
}
return impl;
}
/** /**
* Does t have the same arguments as s? It is assumed that both * Does t have the same arguments as s? It is assumed that both
* types are (possibly polymorphic) method types. Monomorphic * types are (possibly polymorphic) method types. Monomorphic
......
...@@ -1040,15 +1040,6 @@ public class MemberEnter extends JCTree.Visitor implements Completer { ...@@ -1040,15 +1040,6 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
JavaFileObject prev = log.useSource(env.toplevel.sourcefile); JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
try { try {
enterTypeAnnotations(annotations); enterTypeAnnotations(annotations);
// enrich type parameter symbols... easier for annotation processors
if (tree instanceof JCTypeParameter) {
JCTypeParameter typeparam = (JCTypeParameter)tree;
ListBuffer<Attribute.Compound> buf = ListBuffer.lb();
for (JCTypeAnnotation anno : annotations)
buf.add(anno.attribute_field);
typeparam.type.tsym.attributes_field = buf.toList();
}
} finally { } finally {
log.useSource(prev); log.useSource(prev);
} }
......
...@@ -817,6 +817,23 @@ public class TransTypes extends TreeTranslator { ...@@ -817,6 +817,23 @@ public class TransTypes extends TreeTranslator {
pop(); pop();
} }
private boolean inClass = false;
@Override
public void visitClassDef(JCClassDecl tree) {
if (!inClass) {
// Do not recurse into nested and inner classes since
// TransTypes.visitClassDef makes an invocation for each class
// separately.
inClass = true;
try {
super.visitClassDef(tree);
} finally {
inClass = false;
}
}
}
private TypeAnnotationPosition resolveFrame(JCTree tree, JCTree frame, private TypeAnnotationPosition resolveFrame(JCTree tree, JCTree frame,
List<JCTree> path, TypeAnnotationPosition p) { List<JCTree> path, TypeAnnotationPosition p) {
switch (frame.getKind()) { switch (frame.getKind()) {
......
...@@ -1003,7 +1003,7 @@ compiler.misc.inferred.do.not.conform.to.bounds=\ ...@@ -1003,7 +1003,7 @@ compiler.misc.inferred.do.not.conform.to.bounds=\
inferred: {0}\n\ inferred: {0}\n\
bound(s): {1} bound(s): {1}
compiler.misc.inferred.do.not.conform.to.params=\ compiler.misc.inferred.do.not.conform.to.params=\
actual arguments do not conforms to inferred formal arguments\n\ actual arguments do not conform to inferred formal arguments\n\
required: {0}\n\ required: {0}\n\
found: {1} found: {1}
......
...@@ -208,6 +208,32 @@ public class RichDiagnosticFormatter extends ...@@ -208,6 +208,32 @@ public class RichDiagnosticFormatter extends
} }
return clauses.reverse(); return clauses.reverse();
} }
private int indexOf(Type type, WhereClauseKind kind) {
int index = 1;
for (Type t : whereClauses.get(kind).keySet()) {
if (t.tsym == type.tsym) {
return index;
}
if (kind != WhereClauseKind.TYPEVAR ||
t.toString().equals(type.toString())) {
index++;
}
}
return -1;
}
private boolean unique(TypeVar typevar) {
int found = 0;
for (Type t : whereClauses.get(WhereClauseKind.TYPEVAR).keySet()) {
if (t.toString().equals(typevar.toString())) {
found++;
}
}
if (found < 1)
throw new AssertionError("Missing type variable in where clause " + typevar);
return found == 1;
}
//where //where
/** /**
* This enum defines all posssible kinds of where clauses that can be * This enum defines all posssible kinds of where clauses that can be
...@@ -366,33 +392,6 @@ public class RichDiagnosticFormatter extends ...@@ -366,33 +392,6 @@ public class RichDiagnosticFormatter extends
} }
} }
private int indexOf(Type type, WhereClauseKind kind) {
int index = 0;
boolean found = false;
for (Type t : whereClauses.get(kind).keySet()) {
if (t == type) {
found = true;
break;
}
index++;
}
if (!found)
throw new AssertionError("Missing symbol in where clause " + type);
return index + 1;
}
private boolean unique(TypeVar typevar) {
int found = 0;
for (Type t : whereClauses.get(WhereClauseKind.TYPEVAR).keySet()) {
if (t.toString().equals(typevar.toString())) {
found++;
}
}
if (found < 1)
throw new AssertionError("Missing type variable in where clause " + typevar);
return found == 1;
}
@Override @Override
protected String printMethodArgs(List<Type> args, boolean varArgs, Locale locale) { protected String printMethodArgs(List<Type> args, boolean varArgs, Locale locale) {
return super.printMethodArgs(args, varArgs, locale); return super.printMethodArgs(args, varArgs, locale);
...@@ -492,7 +491,7 @@ public class RichDiagnosticFormatter extends ...@@ -492,7 +491,7 @@ public class RichDiagnosticFormatter extends
@Override @Override
public Void visitCapturedType(CapturedType t, Void ignored) { public Void visitCapturedType(CapturedType t, Void ignored) {
if (!whereClauses.get(WhereClauseKind.CAPTURED).containsKey(t)) { if (indexOf(t, WhereClauseKind.CAPTURED) == -1) {
String suffix = t.lower == syms.botType ? ".1" : ""; String suffix = t.lower == syms.botType ? ".1" : "";
JCDiagnostic d = diags.fragment("where.captured"+ suffix, t, t.bound, t.lower, t.wildcard); JCDiagnostic d = diags.fragment("where.captured"+ suffix, t, t.bound, t.lower, t.wildcard);
whereClauses.get(WhereClauseKind.CAPTURED).put(t, d); whereClauses.get(WhereClauseKind.CAPTURED).put(t, d);
...@@ -506,7 +505,7 @@ public class RichDiagnosticFormatter extends ...@@ -506,7 +505,7 @@ public class RichDiagnosticFormatter extends
@Override @Override
public Void visitClassType(ClassType t, Void ignored) { public Void visitClassType(ClassType t, Void ignored) {
if (t.isCompound()) { if (t.isCompound()) {
if (!whereClauses.get(WhereClauseKind.INTERSECTION).containsKey(t)) { if (indexOf(t, WhereClauseKind.INTERSECTION) == -1) {
Type supertype = types.supertype(t); Type supertype = types.supertype(t);
List<Type> interfaces = types.interfaces(t); List<Type> interfaces = types.interfaces(t);
JCDiagnostic d = diags.fragment("where.intersection", t, interfaces.prepend(supertype)); JCDiagnostic d = diags.fragment("where.intersection", t, interfaces.prepend(supertype));
...@@ -524,11 +523,17 @@ public class RichDiagnosticFormatter extends ...@@ -524,11 +523,17 @@ public class RichDiagnosticFormatter extends
@Override @Override
public Void visitTypeVar(TypeVar t, Void ignored) { public Void visitTypeVar(TypeVar t, Void ignored) {
if (!whereClauses.get(WhereClauseKind.TYPEVAR).containsKey(t)) { if (indexOf(t, WhereClauseKind.TYPEVAR) == -1) {
//access the bound type and skip error types
Type bound = t.bound; Type bound = t.bound;
while ((bound instanceof ErrorType)) while ((bound instanceof ErrorType))
bound = ((ErrorType)bound).getOriginalType(); bound = ((ErrorType)bound).getOriginalType();
List<Type> bounds = types.getBounds(t); //retrieve the bound list - if the type variable
//has not been attributed the bound is not set
List<Type> bounds = bound != null ?
types.getBounds(t) :
List.<Type>nil();
nameSimplifier.addUsage(t.tsym); nameSimplifier.addUsage(t.tsym);
boolean boundErroneous = bounds.head == null || boolean boundErroneous = bounds.head == null ||
......
...@@ -32,6 +32,10 @@ import com.sun.tools.classfile.Annotation.Array_element_value; ...@@ -32,6 +32,10 @@ import com.sun.tools.classfile.Annotation.Array_element_value;
import com.sun.tools.classfile.Annotation.Class_element_value; import com.sun.tools.classfile.Annotation.Class_element_value;
import com.sun.tools.classfile.Annotation.Enum_element_value; import com.sun.tools.classfile.Annotation.Enum_element_value;
import com.sun.tools.classfile.Annotation.Primitive_element_value; import com.sun.tools.classfile.Annotation.Primitive_element_value;
import com.sun.tools.classfile.ConstantPool;
import com.sun.tools.classfile.ConstantPoolException;
import com.sun.tools.classfile.Descriptor;
import com.sun.tools.classfile.Descriptor.InvalidDescriptor;
/** /**
* A writer for writing annotations as text. * A writer for writing annotations as text.
...@@ -51,71 +55,243 @@ public class AnnotationWriter extends BasicWriter { ...@@ -51,71 +55,243 @@ public class AnnotationWriter extends BasicWriter {
protected AnnotationWriter(Context context) { protected AnnotationWriter(Context context) {
super(context); super(context);
classWriter = ClassWriter.instance(context);
constantWriter = ConstantWriter.instance(context);
} }
public void write(Annotation annot) { public void write(Annotation annot) {
print("#" + annot.type_index + "("); write(annot, false);
}
public void write(Annotation annot, boolean resolveIndices) {
writeDescriptor(annot.type_index, resolveIndices);
boolean showParens = annot.num_element_value_pairs > 0 || !resolveIndices;
if (showParens)
print("(");
for (int i = 0; i < annot.num_element_value_pairs; i++) { for (int i = 0; i < annot.num_element_value_pairs; i++) {
if (i > 0) if (i > 0)
print(","); print(",");
write(annot.element_value_pairs[i]); write(annot.element_value_pairs[i], resolveIndices);
} }
print(")"); if (showParens)
print(")");
} }
public void write(ExtendedAnnotation annot) { public void write(ExtendedAnnotation annot) {
write(annot.annotation); write(annot, true, false);
print('@'); }
print(annot.position.toString());
public void write(ExtendedAnnotation annot, boolean showOffsets, boolean resolveIndices) {
write(annot.annotation, resolveIndices);
print(": ");
write(annot.position, showOffsets);
}
public void write(ExtendedAnnotation.Position pos, boolean showOffsets) {
print(pos.type);
switch (pos.type) {
// type case
case TYPECAST:
case TYPECAST_GENERIC_OR_ARRAY:
// object creation
case INSTANCEOF:
case INSTANCEOF_GENERIC_OR_ARRAY:
// new expression
case NEW:
case NEW_GENERIC_OR_ARRAY:
case NEW_TYPE_ARGUMENT:
case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
if (showOffsets) {
print(", offset=");
print(pos.offset);
}
break;
// local variable
case LOCAL_VARIABLE:
case LOCAL_VARIABLE_GENERIC_OR_ARRAY:
print(", {");
for (int i = 0; i < pos.lvarOffset.length; ++i) {
if (i != 0) print("; ");
if (showOffsets) {
print(", start_pc=");
print(pos.lvarOffset[i]);
}
print(", length=");
print(pos.lvarLength[i]);
print(", index=");
print(pos.lvarIndex[i]);
}
print("}");
break;
// method receiver
case METHOD_RECEIVER:
// Do nothing
break;
// type parameters
case CLASS_TYPE_PARAMETER:
case METHOD_TYPE_PARAMETER:
print(", param_index=");
print(pos.parameter_index);
break;
// type parameters bound
case CLASS_TYPE_PARAMETER_BOUND:
case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
case METHOD_TYPE_PARAMETER_BOUND:
case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
print(", param_index=");
print(pos.parameter_index);
print(", bound_index=");
print(pos.bound_index);
break;
// wildcard
case WILDCARD_BOUND:
case WILDCARD_BOUND_GENERIC_OR_ARRAY:
print(", wild_card=");
print(pos.wildcard_position);
break;
// Class extends and implements clauses
case CLASS_EXTENDS:
case CLASS_EXTENDS_GENERIC_OR_ARRAY:
print(", type_index=");
print(pos.type_index);
break;
// throws
case THROWS:
print(", type_index=");
print(pos.type_index);
break;
case CLASS_LITERAL:
if (showOffsets) {
print(", offset=");
print(pos.offset);
}
break;
// method parameter: not specified
case METHOD_PARAMETER_GENERIC_OR_ARRAY:
print(", param_index=");
print(pos.parameter_index);
break;
// method type argument: wasn't specified
case METHOD_TYPE_ARGUMENT:
case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
if (showOffsets) {
print(", offset=");
print(pos.offset);
}
print(", type_index=");
print(pos.type_index);
break;
// We don't need to worry abut these
case METHOD_RETURN_GENERIC_OR_ARRAY:
case FIELD_GENERIC_OR_ARRAY:
break;
case UNKNOWN:
break;
default:
throw new AssertionError("unknown type: " + pos.type);
}
// Append location data for generics/arrays.
if (pos.type.hasLocation()) {
print(", location=");
print(pos.location);
}
} }
public void write(Annotation.element_value_pair pair) { public void write(Annotation.element_value_pair pair) {
print("#" + pair.element_name_index + ":"); write(pair, false);
write(pair.value); }
public void write(Annotation.element_value_pair pair, boolean resolveIndices) {
writeIndex(pair.element_name_index, resolveIndices);
print("=");
write(pair.value, resolveIndices);
} }
public void write(Annotation.element_value value) { public void write(Annotation.element_value value) {
ev_writer.write(value); write(value, false);
}
public void write(Annotation.element_value value, boolean resolveIndices) {
ev_writer.write(value, resolveIndices);
}
private void writeDescriptor(int index, boolean resolveIndices) {
if (resolveIndices) {
try {
ConstantPool constant_pool = classWriter.getClassFile().constant_pool;
Descriptor d = new Descriptor(index);
print(d.getFieldType(constant_pool));
return;
} catch (ConstantPoolException ignore) {
} catch (InvalidDescriptor ignore) {
}
}
print("#" + index);
}
private void writeIndex(int index, boolean resolveIndices) {
if (resolveIndices) {
print(constantWriter.stringValue(index));
} else
print("#" + index);
} }
element_value_Writer ev_writer = new element_value_Writer(); element_value_Writer ev_writer = new element_value_Writer();
class element_value_Writer implements Annotation.element_value.Visitor<Void,Void> { class element_value_Writer implements Annotation.element_value.Visitor<Void,Boolean> {
public void write(Annotation.element_value value) { public void write(Annotation.element_value value, boolean resolveIndices) {
value.accept(this, null); value.accept(this, resolveIndices);
} }
public Void visitPrimitive(Primitive_element_value ev, Void p) { public Void visitPrimitive(Primitive_element_value ev, Boolean resolveIndices) {
print(((char) ev.tag) + "#" + ev.const_value_index); if (resolveIndices)
writeIndex(ev.const_value_index, resolveIndices);
else
print(((char) ev.tag) + "#" + ev.const_value_index);
return null; return null;
} }
public Void visitEnum(Enum_element_value ev, Void p) { public Void visitEnum(Enum_element_value ev, Boolean resolveIndices) {
print(((char) ev.tag) + "#" + ev.type_name_index + ".#" + ev.const_name_index); if (resolveIndices) {
writeIndex(ev.type_name_index, resolveIndices);
print(".");
writeIndex(ev.const_name_index, resolveIndices);
} else
print(((char) ev.tag) + "#" + ev.type_name_index + ".#" + ev.const_name_index);
return null; return null;
} }
public Void visitClass(Class_element_value ev, Void p) { public Void visitClass(Class_element_value ev, Boolean resolveIndices) {
print(((char) ev.tag) + "#" + ev.class_info_index); if (resolveIndices) {
writeIndex(ev.class_info_index, resolveIndices);
print(".class");
} else
print(((char) ev.tag) + "#" + ev.class_info_index);
return null; return null;
} }
public Void visitAnnotation(Annotation_element_value ev, Void p) { public Void visitAnnotation(Annotation_element_value ev, Boolean resolveIndices) {
print((char) ev.tag); print((char) ev.tag);
AnnotationWriter.this.write(ev.annotation_value); AnnotationWriter.this.write(ev.annotation_value, resolveIndices);
return null; return null;
} }
public Void visitArray(Array_element_value ev, Void p) { public Void visitArray(Array_element_value ev, Boolean resolveIndices) {
print("["); print("[");
for (int i = 0; i < ev.num_values; i++) { for (int i = 0; i < ev.num_values; i++) {
if (i > 0) if (i > 0)
print(","); print(",");
write(ev.values[i]); write(ev.values[i], resolveIndices);
} }
print("]"); print("]");
return null; return null;
} }
} }
private ClassWriter classWriter;
private ConstantWriter constantWriter;
} }
...@@ -64,6 +64,7 @@ class CodeWriter extends BasicWriter { ...@@ -64,6 +64,7 @@ class CodeWriter extends BasicWriter {
stackMapWriter = StackMapWriter.instance(context); stackMapWriter = StackMapWriter.instance(context);
localVariableTableWriter = LocalVariableTableWriter.instance(context); localVariableTableWriter = LocalVariableTableWriter.instance(context);
localVariableTypeTableWriter = LocalVariableTypeTableWriter.instance(context); localVariableTypeTableWriter = LocalVariableTypeTableWriter.instance(context);
typeAnnotationWriter = TypeAnnotationWriter.instance(context);
options = Options.instance(context); options = Options.instance(context);
} }
...@@ -253,6 +254,11 @@ class CodeWriter extends BasicWriter { ...@@ -253,6 +254,11 @@ class CodeWriter extends BasicWriter {
detailWriters.add(tryBlockWriter); detailWriters.add(tryBlockWriter);
} }
if (options.details.contains(InstructionDetailWriter.Kind.TYPE_ANNOS)) {
typeAnnotationWriter.reset(attr);
detailWriters.add(typeAnnotationWriter);
}
return detailWriters; return detailWriters;
} }
...@@ -261,6 +267,7 @@ class CodeWriter extends BasicWriter { ...@@ -261,6 +267,7 @@ class CodeWriter extends BasicWriter {
private ConstantWriter constantWriter; private ConstantWriter constantWriter;
private LocalVariableTableWriter localVariableTableWriter; private LocalVariableTableWriter localVariableTableWriter;
private LocalVariableTypeTableWriter localVariableTypeTableWriter; private LocalVariableTypeTableWriter localVariableTypeTableWriter;
private TypeAnnotationWriter typeAnnotationWriter;
private SourceWriter sourceWriter; private SourceWriter sourceWriter;
private StackMapWriter stackMapWriter; private StackMapWriter stackMapWriter;
private TryBlockWriter tryBlockWriter; private TryBlockWriter tryBlockWriter;
......
...@@ -42,7 +42,8 @@ public abstract class InstructionDetailWriter extends BasicWriter { ...@@ -42,7 +42,8 @@ public abstract class InstructionDetailWriter extends BasicWriter {
LOCAL_VAR_TYPES("localVariableTypes"), LOCAL_VAR_TYPES("localVariableTypes"),
SOURCE("source"), SOURCE("source"),
STACKMAPS("stackMaps"), STACKMAPS("stackMaps"),
TRY_BLOCKS("tryBlocks"); TRY_BLOCKS("tryBlocks"),
TYPE_ANNOS("typeAnnotations");
Kind(String option) { Kind(String option) {
this.option = option; this.option = option;
} }
......
...@@ -41,13 +41,13 @@ import com.sun.tools.javac.util.Context; ...@@ -41,13 +41,13 @@ import com.sun.tools.javac.util.Context;
* This code and its internal interfaces are subject to change or * This code and its internal interfaces are subject to change or
* deletion without notice.</b> * deletion without notice.</b>
*/ */
class JavapFileManager extends JavacFileManager { public class JavapFileManager extends JavacFileManager {
private JavapFileManager(Context context, Charset charset) { private JavapFileManager(Context context, Charset charset) {
super(context, true, charset); super(context, true, charset);
setIgnoreSymbolFile(true); setIgnoreSymbolFile(true);
} }
static JavapFileManager create(final DiagnosticListener<? super JavaFileObject> dl, PrintWriter log, Options options) { public static JavapFileManager create(final DiagnosticListener<? super JavaFileObject> dl, PrintWriter log) {
Context javac_context = new Context(); Context javac_context = new Context();
if (dl != null) if (dl != null)
......
...@@ -289,6 +289,12 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { ...@@ -289,6 +289,12 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
void process(JavapTask task, String opt, String arg) { void process(JavapTask task, String opt, String arg) {
task.options.showConstants = true; task.options.showConstants = true;
} }
},
new Option(false, "-XDinner") {
void process(JavapTask task, String opt, String arg) {
task.options.showInnerClasses = true;
}
} }
}; };
...@@ -316,17 +322,17 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { ...@@ -316,17 +322,17 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
Iterable<String> classes) { Iterable<String> classes) {
this(out, fileManager, diagnosticListener); this(out, fileManager, diagnosticListener);
try {
handleOptions(options, false);
} catch (BadArgs e) {
throw new IllegalArgumentException(e.getMessage());
}
this.classes = new ArrayList<String>(); this.classes = new ArrayList<String>();
for (String classname: classes) { for (String classname: classes) {
classname.getClass(); // null-check classname.getClass(); // null-check
this.classes.add(classname); this.classes.add(classname);
} }
try {
handleOptions(options, false);
} catch (BadArgs e) {
throw new IllegalArgumentException(e.getMessage());
}
} }
public void setLocale(Locale locale) { public void setLocale(Locale locale) {
...@@ -372,10 +378,18 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { ...@@ -372,10 +378,18 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
final PrintWriter pw = getPrintWriterForWriter(w); final PrintWriter pw = getPrintWriterForWriter(w);
return new DiagnosticListener<JavaFileObject> () { return new DiagnosticListener<JavaFileObject> () {
public void report(Diagnostic<? extends JavaFileObject> diagnostic) { public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
if (diagnostic.getKind() == Diagnostic.Kind.ERROR) { switch (diagnostic.getKind()) {
case ERROR:
pw.print(getMessage("err.prefix")); pw.print(getMessage("err.prefix"));
pw.print(" "); break;
case WARNING:
pw.print(getMessage("warn.prefix"));
break;
case NOTE:
pw.print(getMessage("note.prefix"));
break;
} }
pw.print(" ");
pw.println(diagnostic.getMessage(null)); pw.println(diagnostic.getMessage(null));
} }
}; };
...@@ -405,7 +419,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { ...@@ -405,7 +419,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
boolean ok = run(); boolean ok = run();
return ok ? EXIT_OK : EXIT_ERROR; return ok ? EXIT_OK : EXIT_ERROR;
} catch (BadArgs e) { } catch (BadArgs e) {
diagnosticListener.report(createDiagnostic(e.key, e.args)); reportError(e.key, e.args);
if (e.showUsage) { if (e.showUsage) {
log.println(getMessage("main.usage.summary", progname)); log.println(getMessage("main.usage.summary", progname));
} }
...@@ -419,7 +433,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { ...@@ -419,7 +433,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
e_args[0] = e.getCause(); e_args[0] = e.getCause();
System.arraycopy(e.args, 0, e_args, 1, e.args.length); System.arraycopy(e.args, 0, e_args, 1, e.args.length);
} }
diagnosticListener.report(createDiagnostic("err.internal.error", e_args)); reportError("err.internal.error", e_args);
return EXIT_ABNORMAL; return EXIT_ABNORMAL;
} finally { } finally {
log.flush(); log.flush();
...@@ -521,64 +535,37 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { ...@@ -521,64 +535,37 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
SourceWriter sourceWriter = SourceWriter.instance(context); SourceWriter sourceWriter = SourceWriter.instance(context);
sourceWriter.setFileManager(fileManager); sourceWriter.setFileManager(fileManager);
attributeFactory.setCompat(options.compat);
attributeFactory.setJSR277(options.jsr277);
boolean ok = true; boolean ok = true;
for (String className: classes) { for (String className: classes) {
JavaFileObject fo; JavaFileObject fo;
try { try {
if (className.endsWith(".class")) { writeClass(classWriter, className);
if (fileManager instanceof StandardJavaFileManager) {
StandardJavaFileManager sfm = (StandardJavaFileManager) fileManager;
fo = sfm.getJavaFileObjects(className).iterator().next();
} else {
diagnosticListener.report(createDiagnostic("err.not.standard.file.manager", className));
ok = false;
continue;
}
} else {
fo = getClassFileObject(className);
if (fo == null) {
// see if it is an inner class, by replacing dots to $, starting from the right
String cn = className;
int lastDot;
while (fo == null && (lastDot = cn.lastIndexOf(".")) != -1) {
cn = cn.substring(0, lastDot) + "$" + cn.substring(lastDot + 1);
fo = getClassFileObject(cn);
}
}
if (fo == null) {
diagnosticListener.report(createDiagnostic("err.class.not.found", className));
ok = false;
continue;
}
}
attributeFactory.setCompat(options.compat);
attributeFactory.setJSR277(options.jsr277);
write(read(fo));
} catch (ConstantPoolException e) { } catch (ConstantPoolException e) {
diagnosticListener.report(createDiagnostic("err.bad.constant.pool", className, e.getLocalizedMessage())); reportError("err.bad.constant.pool", className, e.getLocalizedMessage());
ok = false; ok = false;
} catch (EOFException e) { } catch (EOFException e) {
diagnosticListener.report(createDiagnostic("err.end.of.file", className)); reportError("err.end.of.file", className);
ok = false; ok = false;
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
diagnosticListener.report(createDiagnostic("err.file.not.found", e.getLocalizedMessage())); reportError("err.file.not.found", e.getLocalizedMessage());
ok = false; ok = false;
} catch (IOException e) { } catch (IOException e) {
//e.printStackTrace(); //e.printStackTrace();
Object msg = e.getLocalizedMessage(); Object msg = e.getLocalizedMessage();
if (msg == null) if (msg == null)
msg = e; msg = e;
diagnosticListener.report(createDiagnostic("err.ioerror", className, msg)); reportError("err.ioerror", className, msg);
ok = false; ok = false;
} catch (Throwable t) { } catch (Throwable t) {
StringWriter sw = new StringWriter(); StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw); PrintWriter pw = new PrintWriter(sw);
t.printStackTrace(pw); t.printStackTrace(pw);
pw.close(); pw.close();
diagnosticListener.report(createDiagnostic("err.crash", t.toString(), sw.toString())); reportError("err.crash", t.toString(), sw.toString());
ok = false; ok = false;
} }
} }
...@@ -586,6 +573,76 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { ...@@ -586,6 +573,76 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
return ok; return ok;
} }
protected boolean writeClass(ClassWriter classWriter, String className)
throws IOException, ConstantPoolException {
JavaFileObject fo;
if (className.endsWith(".class")) {
if (fileManager instanceof StandardJavaFileManager) {
StandardJavaFileManager sfm = (StandardJavaFileManager) fileManager;
fo = sfm.getJavaFileObjects(className).iterator().next();
} else {
reportError("err.not.standard.file.manager", className);
return false;
}
} else {
fo = getClassFileObject(className);
if (fo == null) {
// see if it is an inner class, by replacing dots to $, starting from the right
String cn = className;
int lastDot;
while (fo == null && (lastDot = cn.lastIndexOf(".")) != -1) {
cn = cn.substring(0, lastDot) + "$" + cn.substring(lastDot + 1);
fo = getClassFileObject(cn);
}
}
if (fo == null) {
reportError("err.class.not.found", className);
return false;
}
}
ClassFileInfo cfInfo = read(fo);
if (!className.endsWith(".class")) {
String cfName = cfInfo.cf.getName();
if (!cfName.replaceAll("[/$]", ".").equals(className.replaceAll("[/$]", ".")))
reportWarning("warn.unexpected.class", className, cfName.replace('/', '.'));
}
write(cfInfo);
if (options.showInnerClasses) {
ClassFile cf = cfInfo.cf;
Attribute a = cf.getAttribute(Attribute.InnerClasses);
if (a instanceof InnerClasses_attribute) {
InnerClasses_attribute inners = (InnerClasses_attribute) a;
try {
boolean ok = true;
for (int i = 0; i < inners.classes.length; i++) {
int outerIndex = inners.classes[i].outer_class_info_index;
ConstantPool.CONSTANT_Class_info outerClassInfo = cf.constant_pool.getClassInfo(outerIndex);
String outerClassName = outerClassInfo.getName();
if (outerClassName.equals(cf.getName())) {
int innerIndex = inners.classes[i].inner_class_info_index;
ConstantPool.CONSTANT_Class_info innerClassInfo = cf.constant_pool.getClassInfo(innerIndex);
String innerClassName = innerClassInfo.getName();
classWriter.println("// inner class " + innerClassName.replaceAll("[/$]", "."));
classWriter.println();
ok = ok & writeClass(classWriter, innerClassName);
}
}
return ok;
} catch (ConstantPoolException e) {
reportError("err.bad.innerclasses.attribute", className);
return false;
}
} else if (a != null) {
reportError("err.bad.innerclasses.attribute", className);
return false;
}
}
return true;
}
public static class ClassFileInfo { public static class ClassFileInfo {
ClassFileInfo(JavaFileObject fo, ClassFile cf, byte[] digest, int size) { ClassFileInfo(JavaFileObject fo, ClassFile cf, byte[] digest, int size) {
this.fo = fo; this.fo = fo;
...@@ -684,7 +741,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { ...@@ -684,7 +741,7 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
} }
private JavaFileManager getDefaultFileManager(final DiagnosticListener<? super JavaFileObject> dl, PrintWriter log) { private JavaFileManager getDefaultFileManager(final DiagnosticListener<? super JavaFileObject> dl, PrintWriter log) {
return JavapFileManager.create(dl, log, options); return JavapFileManager.create(dl, log);
} }
private JavaFileObject getClassFileObject(String className) throws IOException { private JavaFileObject getClassFileObject(String className) throws IOException {
...@@ -738,10 +795,23 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { ...@@ -738,10 +795,23 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
} }
} }
private Diagnostic<JavaFileObject> createDiagnostic(final String key, final Object... args) { private void reportError(String key, Object... args) {
diagnosticListener.report(createDiagnostic(Diagnostic.Kind.ERROR, key, args));
}
private void reportNote(String key, Object... args) {
diagnosticListener.report(createDiagnostic(Diagnostic.Kind.NOTE, key, args));
}
private void reportWarning(String key, Object... args) {
diagnosticListener.report(createDiagnostic(Diagnostic.Kind.WARNING, key, args));
}
private Diagnostic<JavaFileObject> createDiagnostic(
final Diagnostic.Kind kind, final String key, final Object... args) {
return new Diagnostic<JavaFileObject>() { return new Diagnostic<JavaFileObject>() {
public Kind getKind() { public Kind getKind() {
return Diagnostic.Kind.ERROR; return kind;
} }
public JavaFileObject getSource() { public JavaFileObject getSource() {
...@@ -776,6 +846,11 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages { ...@@ -776,6 +846,11 @@ public class JavapTask implements DisassemblerTool.DisassemblerTask, Messages {
return JavapTask.this.getMessage(locale, key, args); return JavapTask.this.getMessage(locale, key, args);
} }
@Override
public String toString() {
return getClass().getName() + "[key=" + key + ",args=" + Arrays.asList(args) + "]";
}
}; };
} }
......
...@@ -85,6 +85,7 @@ public class Options { ...@@ -85,6 +85,7 @@ public class Options {
public boolean showAllAttrs; public boolean showAllAttrs;
public boolean showConstants; public boolean showConstants;
public boolean sysInfo; public boolean sysInfo;
public boolean showInnerClasses;
public boolean compat; // bug-for-bug compatibility mode with old javap public boolean compat; // bug-for-bug compatibility mode with old javap
public boolean jsr277; public boolean jsr277;
......
/*
* Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.tools.javap;
import com.sun.tools.classfile.Attribute;
import com.sun.tools.classfile.Code_attribute;
import com.sun.tools.classfile.ExtendedAnnotation;
import com.sun.tools.classfile.ExtendedAnnotation.Position;
import com.sun.tools.classfile.Instruction;
import com.sun.tools.classfile.Method;
import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute;
import com.sun.tools.classfile.RuntimeTypeAnnotations_attribute;
import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Annotate instructions with details about type annotations.
*
* <p><b>This is NOT part of any API supported by Sun Microsystems. If
* you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class TypeAnnotationWriter extends InstructionDetailWriter {
public enum NoteKind { VISIBLE, INVISIBLE };
public static class Note {
Note(NoteKind kind, ExtendedAnnotation anno) {
this.kind = kind;
this.anno = anno;
}
public final NoteKind kind;
public final ExtendedAnnotation anno;
}
static TypeAnnotationWriter instance(Context context) {
TypeAnnotationWriter instance = context.get(TypeAnnotationWriter.class);
if (instance == null)
instance = new TypeAnnotationWriter(context);
return instance;
}
protected TypeAnnotationWriter(Context context) {
super(context);
context.put(TypeAnnotationWriter.class, this);
annotationWriter = AnnotationWriter.instance(context);
classWriter = ClassWriter.instance(context);
}
public void reset(Code_attribute attr) {
Method m = classWriter.getMethod();
pcMap = new HashMap<Integer, List<Note>>();
check(NoteKind.VISIBLE, (RuntimeVisibleTypeAnnotations_attribute) m.attributes.get(Attribute.RuntimeVisibleTypeAnnotations));
check(NoteKind.INVISIBLE, (RuntimeInvisibleTypeAnnotations_attribute) m.attributes.get(Attribute.RuntimeInvisibleTypeAnnotations));
}
private void check(NoteKind kind, RuntimeTypeAnnotations_attribute attr) {
if (attr == null)
return;
for (ExtendedAnnotation anno: attr.annotations) {
Position p = anno.position;
Note note = null;
if (p.offset != -1)
addNote(p.offset, note = new Note(kind, anno));
if (p.lvarOffset != null) {
for (int i = 0; i < p.lvarOffset.length; i++) {
if (note == null)
note = new Note(kind, anno);
addNote(p.lvarOffset[i], note);
}
}
}
}
private void addNote(int pc, Note note) {
List<Note> list = pcMap.get(pc);
if (list == null)
pcMap.put(pc, list = new ArrayList<Note>());
list.add(note);
}
@Override
void writeDetails(Instruction instr) {
String indent = space(2); // get from Options?
int pc = instr.getPC();
List<Note> notes = pcMap.get(pc);
if (notes != null) {
for (Note n: notes) {
print(indent);
print("@");
annotationWriter.write(n.anno, false, true);
print(", ");
println(n.kind.toString().toLowerCase());
}
}
}
private AnnotationWriter annotationWriter;
private ClassWriter classWriter;
private Map<Integer, List<Note>> pcMap;
}
...@@ -18,12 +18,22 @@ err.unknown.option=unknown option: {0} ...@@ -18,12 +18,22 @@ err.unknown.option=unknown option: {0}
err.verify.not.supported=-verify not supported err.verify.not.supported=-verify not supported
err.no.SourceFile.attribute=no SourceFile attribute err.no.SourceFile.attribute=no SourceFile attribute
err.source.file.not.found=source file not found err.source.file.not.found=source file not found
err.bad.innerclasses.attribute=bad InnerClasses attribute for {0}
warn.Xold.not.supported=-Xold is no longer available warn.Xold.not.supported=-Xold is no longer available
main.usage.summary=\ main.usage.summary=\
Usage: {0} <options> <classes>\n\ Usage: {0} <options> <classes>\n\
use -help for a list of possible options use -help for a list of possible options
warn.prefix=Warning:
warn.unexpected.class=Binary file {0} contains {1}
note.prefix=Note:
main.usage.summary=\
Usage: {0} <options> <classes>\n\
use -help for a list of possible options
main.usage=\ main.usage=\
Usage: {0} <options> <classes>\n\ Usage: {0} <options> <classes>\n\
where possible options include: where possible options include:
......
/*
* Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/**
* @test
* @bug 6862608
* @summary rich diagnostic sometimes contain wrong type variable numbering
* @author mcimadamore
* @compile/fail/ref=T6862608a.out -XDrawDiagnostics -XDdiags=disambiguateTvars,where T6862608a.java
*/
import java.util.*;
class T6862608a {
<T> Comparator<T> compound(Iterable<? extends Comparator<? super T>> it) {
return null;
}
public void test(List<Comparator<?>> x) {
Comparator<String> c3 = compound(x);
}
}
T6862608a.java:42:41: compiler.err.invalid.inferred.types: T, (compiler.misc.inferred.do.not.conform.to.params: java.lang.Iterable<? extends java.util.Comparator<? super java.lang.String>>, java.util.List<java.util.Comparator<?>>)
- compiler.misc.where.description.typevar: T,{(compiler.misc.where.typevar: T, java.lang.Object, kindname.method, <T>compound(java.lang.Iterable<? extends java.util.Comparator<? super T>>))}
1 error
/*
* Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/**
* @test
* @bug 6862608
* @summary rich diagnostic sometimes contain wrong type variable numbering
* @author mcimadamore
* @compile/fail/ref=T6862608b.out -XDrawDiagnostics -XDdiags=disambiguateTvars,where T6862608b.java
*/
class T66862608b<T extends String, S> {
<S, T extends S> void foo(T t) {
test(t);
}
void test(T t) {}
}
T6862608b.java:34:7: compiler.err.cant.apply.symbol: kindname.method, test, compiler.misc.type.var: T, 1, compiler.misc.type.var: T, 2, kindname.class, T66862608b<compiler.misc.type.var: T, 1,compiler.misc.type.var: S, 2>, null
- compiler.misc.where.description.typevar.1: compiler.misc.type.var: T, 1,compiler.misc.type.var: T, 2,compiler.misc.type.var: S, 1,compiler.misc.type.var: S, 2,{(compiler.misc.where.typevar: compiler.misc.type.var: T, 1, java.lang.String, kindname.class, T66862608b),(compiler.misc.where.typevar: compiler.misc.type.var: T, 2, compiler.misc.type.var: S, 1, kindname.method, <compiler.misc.type.var: S, 1,compiler.misc.type.var: T, 2>foo(compiler.misc.type.var: T, 2)),(compiler.misc.where.typevar: compiler.misc.type.var: S, 1, java.lang.Object, kindname.method, <compiler.misc.type.var: S, 1,compiler.misc.type.var: T, 2>foo(compiler.misc.type.var: T, 2)),(compiler.misc.where.typevar: compiler.misc.type.var: S, 2, java.lang.Object, kindname.class, T66862608b)}
1 error
/*
* Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/**
* @test
* @bug 6864382
* @summary NullPointerException when compiling a negative java source
* @author mcimadamore
* @compile/fail/ref=T6864382.out -XDrawDiagnostics T6864382.java
*/
class T6864382<T> extends T {}
T6864382.java:32:27: compiler.err.type.found.req: (compiler.misc.type.parameter: T), (compiler.misc.type.req.class)
1 error
...@@ -30,9 +30,30 @@ ...@@ -30,9 +30,30 @@
*/ */
class InnerClass { class InnerClass {
InnerClass() {}
InnerClass(Object o) {}
private void a() { private void a() {
new Object() { new Object() {
public <R> void method() { } public <R> void method() { }
}; };
} }
Object f1 = new InnerClass() {
<R> void method() { }
};
Object f2 = new InnerClass() {
<@A R> void method() { }
};
Object f3 = new InnerClass(null) {
<R> void method() { }
};
Object f4 = new InnerClass(null) {
<@A R> void method() { }
};
@interface A { }
} }
/*
* Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
import java.io.*;
import java.util.*;
import javax.tools.*;
import com.sun.tools.javap.*;
/*
* @test
* @bug 4777949
* @summary Warn javap usage on package with simple name
*/
public class T4777949 {
public static void main(String... args) throws Exception {
new T4777949().run();
}
void run() throws Exception {
File javaFile = writeTestFile();
File classFile = compileTestFile(javaFile);
test(".", "p.q.r.Test", false);
test("p", "q.r.Test", true);
test("p/q", "r.Test", true);
test("p/q/r", "Test", true);
test(".", "p.q.r.Test.Inner", false);
test(".", "p.q.r.Test$Inner", false);
test("p", "q.r.Test.Inner", true);
test("p", "q.r.Test$Inner", true);
if (errors > 0)
throw new Exception(errors + " errors found");
}
void test(String classPath, String className, boolean expectWarnings) {
List<Diagnostic<? extends JavaFileObject>> diags =
javap(Arrays.asList("-classpath", classPath), Arrays.asList(className));
boolean foundWarnings = false;
for (Diagnostic<? extends JavaFileObject> d: diags) {
if (d.getKind() == Diagnostic.Kind.WARNING)
foundWarnings = true;
}
}
File writeTestFile() throws IOException {
File f = new File("Test.java");
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f)));
out.println("package p.q.r;");
out.println("class Test { class Inner { } }");
out.close();
return f;
}
File compileTestFile(File f) {
int rc = com.sun.tools.javac.Main.compile(new String[] { "-d", ".", f.getPath() });
if (rc != 0)
throw new Error("compilation failed. rc=" + rc);
String path = f.getPath();
return new File(path.substring(0, path.length() - 5) + ".class");
}
List<Diagnostic<? extends JavaFileObject>> javap(List<String> args, List<String> classes) {
DiagnosticCollector<JavaFileObject> dc = new DiagnosticCollector<JavaFileObject>();
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
JavaFileManager fm = JavapFileManager.create(dc, pw);
JavapTask t = new JavapTask(pw, fm, dc, args, classes);
boolean ok = t.run();
List<Diagnostic<? extends JavaFileObject>> diags = dc.getDiagnostics();
if (!ok)
error("javap failed unexpectedly");
System.err.println("args=" + args + " classes=" + classes + "\n"
+ diags + "\n"
+ sw);
return diags;
}
void error(String msg) {
System.err.println("error: " + msg);
errors++;
}
int errors;
}
/*
* Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 4880672
* @summary javap does not output inner interfaces of an interface
*/
import java.io.*;
import java.util.*;
public class T4880672
{
public static void main(String... args) {
new T4880672().run();
}
void run() {
verify("java.util.Map", "public interface java.util.Map$Entry");
verify("T4880672", "class T4880672$A$B extends java.lang.Object");
verify("C", ""); // must not give error if no InnerClasses attribute
if (errors > 0)
throw new Error(errors + " found.");
}
void verify(String className, String... expects) {
String output = javap(className);
for (String expect: expects) {
if (output.indexOf(expect)< 0)
error(expect + " not found");
}
}
void error(String msg) {
System.err.println(msg);
errors++;
}
int errors;
String javap(String className) {
String testClasses = System.getProperty("test.classes", ".");
StringWriter sw = new StringWriter();
PrintWriter out = new PrintWriter(sw);
String[] args = { "-XDinner", "-classpath", testClasses, className };
int rc = com.sun.tools.javap.Main.run(args, out);
out.close();
String output = sw.toString();
System.out.println("class " + className);
System.out.println(output);
if (rc != 0)
throw new Error("javap failed. rc=" + rc);
if (output.indexOf("Error:") != -1)
throw new Error("javap reported error.");
return output;
}
class A {
class B { }
}
}
class C { }
/*
* Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6866657
* @summary add byteLength() method to primary classfile types
*/
import java.io.*;
import java.util.*;
import javax.tools.*;
import com.sun.tools.javap.*;
public class T6866657
{
public static void main(String... args) {
new T6866657().run();
}
void run() {
verify("java.lang.Object");
verify("java.lang.String");
verify("java.util.List");
verify("java.util.ArrayList");
if (errors > 0)
throw new Error(errors + " found.");
}
void verify(String className) {
try {
PrintWriter log = new PrintWriter(System.out);
JavaFileManager fileManager = JavapFileManager.create(null, log);
JavaFileObject fo = fileManager.getJavaFileForInput(StandardLocation.PLATFORM_CLASS_PATH, className, JavaFileObject.Kind.CLASS);
if (fo == null) {
error("Can't find " + className);
} else {
JavapTask t = new JavapTask(log, fileManager, null);
t.handleOptions(new String[] { "-sysinfo", className });
JavapTask.ClassFileInfo cfInfo = t.read(fo);
expectEqual(cfInfo.cf.byteLength(), cfInfo.size);
}
} catch (Exception e) {
e.printStackTrace();
error("Exception: " + e);
}
}
void expectEqual(int found, int expected) {
if (found != expected)
error("bad value found: " + found + " expected: " + expected);
}
void error(String msg) {
System.err.println(msg);
errors++;
}
int errors;
}
/*
* Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
import java.io.*;
/*
* @test
* @bug 6855990
* @summary InstructionDetailWriter should support new 308 annotations attribute
*/
public class T6855990 {
public static void main(String[] args) throws Exception {
new T6855990().run();
}
public void run() throws Exception {
@Simple String[] args = { "-c", "-XDdetails:typeAnnotations", "T6855990" };
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
int rc = com.sun.tools.javap.Main.run(args, pw);
pw.close();
String out = sw.toString();
System.out.println(out);
if (out.indexOf("@Simple: LOCAL_VARIABLE") == -1)
throw new Exception("expected output not found");
}
}
@interface Simple { }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册