8006345: Report Synthesized Parameters in java.lang.reflect.Parameter API
8006896: ClassReader doesn't see MethodParameters attr for method of anon inner class 8007098: Output Synthesized Parameters to MethodParameters Attributes Correctly report synthesized and mandated parameters Reviewed-by: mcimadamore, jjg
This commit is contained in:
parent
14c0c8eed8
commit
8ccde1a96e
@ -56,7 +56,7 @@ public class AccessFlags {
|
||||
public static final int ACC_SYNTHETIC = 0x1000; // class, inner, field, method
|
||||
public static final int ACC_ANNOTATION = 0x2000; // class, inner
|
||||
public static final int ACC_ENUM = 0x4000; // class, inner, field
|
||||
public static final int ACC_MODULE = 0x8000; // class, inner, field, method
|
||||
public static final int ACC_MANDATED = 0x8000; // class, inner, field, method
|
||||
|
||||
public static enum Kind { Class, InnerClass, Field, Method};
|
||||
|
||||
@ -81,12 +81,12 @@ public class AccessFlags {
|
||||
}
|
||||
|
||||
private static final int[] classModifiers = {
|
||||
ACC_PUBLIC, ACC_FINAL, ACC_ABSTRACT, ACC_MODULE
|
||||
ACC_PUBLIC, ACC_FINAL, ACC_ABSTRACT
|
||||
};
|
||||
|
||||
private static final int[] classFlags = {
|
||||
ACC_PUBLIC, ACC_FINAL, ACC_SUPER, ACC_INTERFACE, ACC_ABSTRACT,
|
||||
ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM, ACC_MODULE
|
||||
ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM
|
||||
};
|
||||
|
||||
public Set<String> getClassModifiers() {
|
||||
@ -100,12 +100,12 @@ public class AccessFlags {
|
||||
|
||||
private static final int[] innerClassModifiers = {
|
||||
ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
|
||||
ACC_ABSTRACT, ACC_MODULE
|
||||
ACC_ABSTRACT
|
||||
};
|
||||
|
||||
private static final int[] innerClassFlags = {
|
||||
ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL, ACC_SUPER,
|
||||
ACC_INTERFACE, ACC_ABSTRACT, ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM, ACC_MODULE
|
||||
ACC_INTERFACE, ACC_ABSTRACT, ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM
|
||||
};
|
||||
|
||||
public Set<String> getInnerClassModifiers() {
|
||||
@ -119,12 +119,12 @@ public class AccessFlags {
|
||||
|
||||
private static final int[] fieldModifiers = {
|
||||
ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
|
||||
ACC_VOLATILE, ACC_TRANSIENT, ACC_MODULE
|
||||
ACC_VOLATILE, ACC_TRANSIENT
|
||||
};
|
||||
|
||||
private static final int[] fieldFlags = {
|
||||
ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
|
||||
ACC_VOLATILE, ACC_TRANSIENT, ACC_SYNTHETIC, ACC_ENUM, ACC_MODULE
|
||||
ACC_VOLATILE, ACC_TRANSIENT, ACC_SYNTHETIC, ACC_ENUM
|
||||
};
|
||||
|
||||
public Set<String> getFieldModifiers() {
|
||||
@ -137,13 +137,13 @@ public class AccessFlags {
|
||||
|
||||
private static final int[] methodModifiers = {
|
||||
ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
|
||||
ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT, ACC_STRICT, ACC_MODULE
|
||||
ACC_SYNCHRONIZED, ACC_NATIVE, ACC_ABSTRACT, ACC_STRICT
|
||||
};
|
||||
|
||||
private static final int[] methodFlags = {
|
||||
ACC_PUBLIC, ACC_PRIVATE, ACC_PROTECTED, ACC_STATIC, ACC_FINAL,
|
||||
ACC_SYNCHRONIZED, ACC_BRIDGE, ACC_VARARGS, ACC_NATIVE, ACC_ABSTRACT,
|
||||
ACC_STRICT, ACC_SYNTHETIC, ACC_MODULE
|
||||
ACC_STRICT, ACC_SYNTHETIC
|
||||
};
|
||||
|
||||
public Set<String> getMethodModifiers() {
|
||||
@ -208,8 +208,8 @@ public class AccessFlags {
|
||||
return "abstract";
|
||||
case ACC_STRICT:
|
||||
return "strictfp";
|
||||
case ACC_MODULE:
|
||||
return "module";
|
||||
case ACC_MANDATED:
|
||||
return "mandated";
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
@ -247,8 +247,8 @@ public class AccessFlags {
|
||||
return "ACC_ANNOTATION";
|
||||
case ACC_ENUM:
|
||||
return "ACC_ENUM";
|
||||
case ACC_MODULE:
|
||||
return "ACC_MODULE";
|
||||
case ACC_MANDATED:
|
||||
return "ACC_MANDATED";
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
@ -74,6 +74,7 @@ public class Flags {
|
||||
if ((mask&DEPRECATED) != 0) flags.add(Flag.DEPRECATED);
|
||||
if ((mask&HASINIT) != 0) flags.add(Flag.HASINIT);
|
||||
if ((mask&ENUM) != 0) flags.add(Flag.ENUM);
|
||||
if ((mask&MANDATED) != 0) flags.add(Flag.MANDATED);
|
||||
if ((mask&IPROXY) != 0) flags.add(Flag.IPROXY);
|
||||
if ((mask&NOOUTERTHIS) != 0) flags.add(Flag.NOOUTERTHIS);
|
||||
if ((mask&EXISTS) != 0) flags.add(Flag.EXISTS);
|
||||
@ -114,6 +115,9 @@ public class Flags {
|
||||
* classfile v49.0. */
|
||||
public static final int ENUM = 1<<14;
|
||||
|
||||
/** Added in SE8, represents constructs implicitly declared in source. */
|
||||
public static final int MANDATED = 1<<15;
|
||||
|
||||
public static final int StandardFlags = 0x0fff;
|
||||
public static final int ModifierFlags = StandardFlags & ~INTERFACE;
|
||||
|
||||
@ -342,6 +346,7 @@ public class Flags {
|
||||
DEPRECATED("deprecated"),
|
||||
HASINIT("hasinit"),
|
||||
ENUM("enum"),
|
||||
MANDATED("mandated"),
|
||||
IPROXY("iproxy"),
|
||||
NOOUTERTHIS("noouterthis"),
|
||||
EXISTS("exists"),
|
||||
|
@ -217,6 +217,14 @@ public abstract class Symbol implements Element {
|
||||
return (flags() & INTERFACE) != 0;
|
||||
}
|
||||
|
||||
public boolean isPrivate() {
|
||||
return (flags_field & Flags.AccessFlags) == PRIVATE;
|
||||
}
|
||||
|
||||
public boolean isEnum() {
|
||||
return (flags() & ENUM) != 0;
|
||||
}
|
||||
|
||||
/** Is this symbol declared (directly or indirectly) local
|
||||
* to a method or variable initializer?
|
||||
* Also includes fields of inner classes which are in
|
||||
@ -1082,6 +1090,9 @@ public abstract class Symbol implements Element {
|
||||
/** The code of the method. */
|
||||
public Code code = null;
|
||||
|
||||
/** The extra (synthetic/mandated) parameters of the method. */
|
||||
public List<VarSymbol> extraParams = List.nil();
|
||||
|
||||
/** The parameters of the method. */
|
||||
public List<VarSymbol> params = null;
|
||||
|
||||
|
@ -1445,24 +1445,51 @@ public class Lower extends TreeTranslator {
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Definition for this$n field.
|
||||
* @param pos The source code position of the definition.
|
||||
* @param owner The class in which the definition goes.
|
||||
*/
|
||||
JCVariableDecl outerThisDef(int pos, Symbol owner) {
|
||||
long flags = FINAL | SYNTHETIC;
|
||||
private VarSymbol makeOuterThisVarSymbol(Symbol owner, long flags) {
|
||||
if (owner.kind == TYP &&
|
||||
target.usePrivateSyntheticFields())
|
||||
flags |= PRIVATE;
|
||||
Type target = types.erasure(owner.enclClass().type.getEnclosingType());
|
||||
VarSymbol outerThis = new VarSymbol(
|
||||
flags, outerThisName(target, owner), target, owner);
|
||||
VarSymbol outerThis =
|
||||
new VarSymbol(flags, outerThisName(target, owner), target, owner);
|
||||
outerThisStack = outerThisStack.prepend(outerThis);
|
||||
JCVariableDecl vd = make.at(pos).VarDef(outerThis, null);
|
||||
return outerThis;
|
||||
}
|
||||
|
||||
private JCVariableDecl makeOuterThisVarDecl(int pos, VarSymbol sym) {
|
||||
JCVariableDecl vd = make.at(pos).VarDef(sym, null);
|
||||
vd.vartype = access(vd.vartype);
|
||||
return vd;
|
||||
}
|
||||
|
||||
/** Definition for this$n field.
|
||||
* @param pos The source code position of the definition.
|
||||
* @param owner The method in which the definition goes.
|
||||
*/
|
||||
JCVariableDecl outerThisDef(int pos, MethodSymbol owner) {
|
||||
ClassSymbol c = owner.enclClass();
|
||||
boolean isMandated =
|
||||
// Anonymous constructors
|
||||
(owner.isConstructor() && owner.isAnonymous()) ||
|
||||
// Constructors of non-private inner member classes
|
||||
(owner.isConstructor() && c.isInner() &&
|
||||
!c.isPrivate() && !c.isStatic());
|
||||
long flags =
|
||||
FINAL | (isMandated ? MANDATED : SYNTHETIC);
|
||||
VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
|
||||
owner.extraParams = owner.extraParams.prepend(outerThis);
|
||||
return makeOuterThisVarDecl(pos, outerThis);
|
||||
}
|
||||
|
||||
/** Definition for this$n field.
|
||||
* @param pos The source code position of the definition.
|
||||
* @param owner The class in which the definition goes.
|
||||
*/
|
||||
JCVariableDecl outerThisDef(int pos, ClassSymbol owner) {
|
||||
VarSymbol outerThis = makeOuterThisVarSymbol(owner, FINAL | SYNTHETIC);
|
||||
return makeOuterThisVarDecl(pos, outerThis);
|
||||
}
|
||||
|
||||
/** Return a list of trees that load the free variables in given list,
|
||||
* in reverse order.
|
||||
* @param pos The source code position to be used for the trees.
|
||||
@ -2568,7 +2595,6 @@ public class Lower extends TreeTranslator {
|
||||
"enum" + target.syntheticNameChar() + "name"),
|
||||
syms.stringType, tree.sym);
|
||||
nameParam.mods.flags |= SYNTHETIC; nameParam.sym.flags_field |= SYNTHETIC;
|
||||
|
||||
JCVariableDecl ordParam = make.
|
||||
Param(names.fromString(target.syntheticNameChar() +
|
||||
"enum" + target.syntheticNameChar() +
|
||||
@ -2579,6 +2605,8 @@ public class Lower extends TreeTranslator {
|
||||
tree.params = tree.params.prepend(ordParam).prepend(nameParam);
|
||||
|
||||
MethodSymbol m = tree.sym;
|
||||
m.extraParams = m.extraParams.prepend(ordParam.sym);
|
||||
m.extraParams = m.extraParams.prepend(nameParam.sym);
|
||||
Type olderasure = m.erasure(types);
|
||||
m.erasure_field = new MethodType(
|
||||
olderasure.getParameterTypes().prepend(syms.intType).prepend(syms.stringType),
|
||||
|
@ -465,7 +465,8 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
names.valueOf,
|
||||
make.Type(tree.sym.type),
|
||||
List.<JCTypeParameter>nil(),
|
||||
List.of(make.VarDef(make.Modifiers(Flags.PARAMETER),
|
||||
List.of(make.VarDef(make.Modifiers(Flags.PARAMETER |
|
||||
Flags.MANDATED),
|
||||
names.fromString("name"),
|
||||
make.Type(syms.stringType), null)),
|
||||
List.<JCExpression>nil(), // thrown
|
||||
|
@ -728,14 +728,24 @@ public class ClassWriter extends ClassFile {
|
||||
* Write method parameter names attribute.
|
||||
*/
|
||||
int writeMethodParametersAttr(MethodSymbol m) {
|
||||
if (m.params != null && 0 != m.params.length()) {
|
||||
int attrIndex = writeAttr(names.MethodParameters);
|
||||
databuf.appendByte(m.params.length());
|
||||
MethodType ty = m.externalType(types).asMethodType();
|
||||
final int allparams = ty.argtypes.size();
|
||||
if (m.params != null && allparams != 0) {
|
||||
final int attrIndex = writeAttr(names.MethodParameters);
|
||||
databuf.appendByte(allparams);
|
||||
// Write extra parameters first
|
||||
for (VarSymbol s : m.extraParams) {
|
||||
final int flags =
|
||||
((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) |
|
||||
((int) m.flags() & SYNTHETIC);
|
||||
databuf.appendChar(pool.put(s.name));
|
||||
databuf.appendInt(flags);
|
||||
}
|
||||
// Now write the real parameters
|
||||
for (VarSymbol s : m.params) {
|
||||
// TODO: expand to cover synthesized, once we figure out
|
||||
// how to represent that.
|
||||
final int flags = (int) s.flags() & (FINAL | SYNTHETIC);
|
||||
// output parameter info
|
||||
final int flags =
|
||||
((int) s.flags() & (FINAL | SYNTHETIC | MANDATED)) |
|
||||
((int) m.flags() & SYNTHETIC);
|
||||
databuf.appendChar(pool.put(s.name));
|
||||
databuf.appendInt(flags);
|
||||
}
|
||||
|
@ -400,12 +400,14 @@ public class AttributeWriter extends BasicWriter
|
||||
println(header);
|
||||
for (MethodParameters_attribute.Entry entry :
|
||||
attr.method_parameter_table) {
|
||||
String namestr =
|
||||
entry.name_index != 0 ?
|
||||
constantWriter.stringValue(entry.name_index) : "<no name>";
|
||||
String flagstr =
|
||||
(0 != (entry.flags & ACC_FINAL) ? " final" : "") +
|
||||
(0 != (entry.flags & ACC_SYNTHETIC) ? " synthetic" : "");
|
||||
println(String.format(format,
|
||||
constantWriter.stringValue(entry.name_index),
|
||||
flagstr));
|
||||
(0 != (entry.flags & ACC_FINAL) ? "final " : "") +
|
||||
(0 != (entry.flags & ACC_MANDATED) ? "mandated " : "") +
|
||||
(0 != (entry.flags & ACC_SYNTHETIC) ? "synthetic" : "");
|
||||
println(String.format(format, namestr, flagstr));
|
||||
}
|
||||
indent(-1);
|
||||
return null;
|
||||
|
Loading…
Reference in New Issue
Block a user