package bluej.debugger.jdi;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import bluej.debugger.gentype.ConstructorReflective;
import bluej.debugger.gentype.FieldReflective;
import bluej.debugger.gentype.GenTypeClass;
import bluej.debugger.gentype.GenTypeDeclTpar;
import bluej.debugger.gentype.GenTypeExtends;
import bluej.debugger.gentype.GenTypeParameter;
import bluej.debugger.gentype.GenTypeSolid;
import bluej.debugger.gentype.GenTypeSuper;
import bluej.debugger.gentype.GenTypeTpar;
import bluej.debugger.gentype.GenTypeUnbounded;
import bluej.debugger.gentype.GenTypeWildcard;
import bluej.debugger.gentype.IntersectionType;
import bluej.debugger.gentype.JavaPrimitiveType;
import bluej.debugger.gentype.JavaType;
import bluej.debugger.gentype.MethodReflective;
import bluej.debugger.gentype.Reflective;
import bluej.debugger.gentype.TextType;
import bluej.utility.Debug;
import bluej.utility.JavaNames;
import com.sun.jdi.ArrayType;
import com.sun.jdi.BooleanType;
import com.sun.jdi.ByteType;
import com.sun.jdi.CharType;
import com.sun.jdi.ClassLoaderReference;
import com.sun.jdi.ClassNotLoadedException;
import com.sun.jdi.ClassType;
import com.sun.jdi.DoubleType;
import com.sun.jdi.Field;
import com.sun.jdi.FloatType;
import com.sun.jdi.IntegerType;
import com.sun.jdi.InterfaceType;
import com.sun.jdi.LocalVariable;
import com.sun.jdi.Location;
import com.sun.jdi.LongType;
import com.sun.jdi.Method;
import com.sun.jdi.ReferenceType;
import com.sun.jdi.ShortType;
import com.sun.jdi.StackFrame;
import com.sun.jdi.Type;
import com.sun.jdi.VirtualMachine;
import threadchecker.OnThread;
import threadchecker.Tag;
| A Reflective for Jdi classes.
|
| @see Reflective.
|
| @author Davin McCall
|
public class JdiReflective
extends Reflective{
private ReferenceType rclass = null;
protected String name = null;
private ClassLoaderReference sourceLoader = null;
private VirtualMachine sourceVM = null;
| Constructor - loaded type
|
public JdiReflective(ReferenceType rclass)
{
super();
this.rclass = rclass;
if (rclass == null) {
Debug.message("JdiReflective: null ReferenceType?");
throw new NullPointerException();
}
}
| Constructor - type not loaded yet; source (parent) object available.
|
| @param name
| The fully qualified type name
| @param sourceType
| The type from which a reference to this type was obtained
|
@OnThread(Tag.Any)
public JdiReflective(String name, ReferenceType sourceType)
{
this.name = name;
this.sourceLoader = sourceType.classLoader();
this.sourceVM = sourceType.virtualMachine();
}
| Constructor - type may not yet be loaded; class loader available.
|
| @param name
| The fully qualified type name
| @param classLoader
| The class loader used to load this type
| @param vm
| The virtual machine reference
|
public JdiReflective(String name, ClassLoaderReference classLoader, VirtualMachine vm)
{
this.name = name;
this.sourceLoader = classLoader;
this.sourceVM = vm;
}
| Get the JDI ReferenceType this reflective represents.
|
public ReferenceType getJdiType()
{
checkLoaded();
return rclass;
}
@Override
public Reflective getRelativeClass(String name)
{
ClassLoaderReference cl;
VirtualMachine vm;
if (rclass != null) {
cl = rclass.classLoader();
vm = rclass.virtualMachine();
}
else {
cl = this.sourceLoader;
vm = this.sourceVM;
}
ReferenceType resultClass = findClass(name, cl, vm);
if (resultClass == null) {
return null;
}
return new JdiReflective(resultClass);
}
| Try to make sure we have a valid reference to the actual type
|
protected void checkLoaded()
{
if (rclass == null) {
rclass = findClass(name, sourceLoader, sourceVM);
if (rclass == null) {
Debug.message("Attempt to use unloaded type: " + name);
Debug.message(" name = " + name + ", sourceLoader = " + sourceLoader);
Debug.message(" (in JdiReflective.checkLoaded()");
return;
}
name = null;
sourceLoader = null;
sourceVM = null;
}
}
public String getName()
{
if (name != null) {
return name;
}
if (rclass.signature().startsWith("[")) {
return rclass.signature().replace('/', '.');
}
else {
return rclass.name();
}
}
@Override
public boolean isInterface()
{
checkLoaded();
return rclass instanceof InterfaceType;
}
@Override
public boolean isStatic()
{
checkLoaded();
return rclass.isStatic();
}
@Override
public boolean isPublic()
{
checkLoaded();
return rclass.isPublic();
}
@Override
public boolean isFinal()
{
checkLoaded();
return rclass.isFinal();
}
public Reflective getArrayOf()
{
if (rclass != null) {
return new JdiArrayReflective(new GenTypeClass(this), rclass);
}
else {
return new JdiArrayReflective(new GenTypeClass(this), sourceLoader, sourceVM);
}
}
public List getTypeParams()
{
checkLoaded();
String gensig = JdiUtils.getJdiUtils().genericSignature(rclass);
if (gensig == null)
return Collections.emptyList();
StringIterator s = new StringIterator(gensig);
return getTypeParams(s);
}
| Get the type parameters of this class, as a list of GenTypeDeclTpar,
| using a pre-existing string iterator to process the generic signature.
|
| @param s A string iterator, currently at the beginning of the generic
| signature for this class. On return, the iterator will be
| positioned after the type parameters in the signature, at the
| beginning of the class name.
|
| @return A list of GenTypeDeclTpar, representing the type parameters of
| this class.
|
private List getTypeParams(StringIterator s)
{
List<GenTypeDeclTpar> rlist = new ArrayList<GenTypeDeclTpar>();
char c = s.peek();
if (c != '<')
return rlist;
s.next();
while (c != '>'){
String paramName = readClassName(s);
if (s.current() != ':') {
Debug.message("getTypeParams : no ':' following type parameter name in super signature?? got "
+ s.current());
Debug.message("signature was: " + s.getString());
return Collections.emptyList();
}
if (s.peek() == ':')
s.next();
ArrayList<GenTypeSolid> bounds = new ArrayList<GenTypeSolid>(3);
while (s.current() == ':'){
bounds.add((GenTypeSolid) typeFromSignature(s, null, rclass));
if (s.peek() == ':')
s.next();
}
rlist.add(new GenTypeDeclTpar(paramName, bounds.toArray(new GenTypeSolid [0])));
c = s.peek();
}
s.next();
return rlist;
}
public List getSuperTypesR()
{
checkLoaded();
if (rclass instanceof ClassType) {
List<Reflective> l = new LinkedList<Reflective>();
Iterator<InterfaceType> i = ((ClassType) rclass).interfaces().iterator();
while (i.hasNext())
{l.add(new JdiReflective(i.next()));
}
if (((ClassType) rclass).superclass() != null)
l.add(new JdiReflective(((ClassType) rclass).superclass()));
return l;
}
p.public else if(rclass instanceof InterfaceType)
{
List<Reflective> l = new LinkedList<Reflective>();
Iterator<InterfaceType> i = ((InterfaceType) rclass).superinterfaces().iterator();
while (i.hasNext())
{l.add(new JdiReflective(i.next()));
}
if (l.isEmpty()) {
l.add(new JdiReflective("java.lang.Object", this.rclass));
}
return l;
}
else{ return new LinkedList<Reflective>();
}
}
public List getSuperTypes()
{
checkLoaded();
List<GenTypeClass> rlist = new ArrayList<GenTypeClass>();
if (JdiUtils.getJdiUtils().genericSignature(rclass) == null) {
if (rclass instanceof ClassType) {
ClassType ctClass = (ClassType) rclass;
ClassType superclass = ctClass.superclass();
if (superclass != null) {
Reflective r = new JdiReflective(ctClass.superclass());
rlist.add(new GenTypeClass(r));
}
List<InterfaceType> interfaces = ctClass.interfaces();
for (Iterator<InterfaceType> i = interfaces.iterator(); i.hasNext();) {
Reflective r = new JdiReflective(i.next());
rlist.add(new GenTypeClass(r));
}
return rlist;
}
else {
InterfaceType itClass = (InterfaceType) rclass;
List<InterfaceType> interfaces = itClass.superinterfaces();
for (Iterator<InterfaceType> i = interfaces.iterator(); i.hasNext();) {
Reflective r = new JdiReflective(i.next());
rlist.add(new GenTypeClass(r));
}
if (rlist.isEmpty()) {
rlist.add(new GenTypeClass(new JdiReflective("java.lang.Object", this.rclass)));
}
return rlist;
}
}
StringIterator s = new StringIterator(JdiUtils.getJdiUtils().genericSignature(rclass));
List<GenTypeDeclTpar> l = getTypeParams(s);
Map<String,GenTypeDeclTpar> declTpars = new HashMap<String,GenTypeDeclTpar>();
for (Iterator<GenTypeDeclTpar> i = l.iterator(); i.hasNext(); ) {
GenTypeDeclTpar declTpar = i.next();
declTpars.put(declTpar.getTparName(), declTpar);
}
while (s.hasNext()){
GenTypeClass t = typeFromSignature(s, declTpars, rclass).asSolid().asClass();
rlist.add(t);
}
return rlist;
}
public boolean isAssignableFrom(Reflective r)
{
if (this.equals(r))
return true;
if (getName().equals("java.lang.Object"))
return true;
if (r instanceof JdiReflective) {
JdiReflective jr = (JdiReflective) r;
jr.checkLoaded();
return checkAssignability(rclass, jr.rclass);
}
else{ return false;
}
}
| Check that type b is assingable to a variable of type a.
|
private static boolean checkAssignability(ReferenceType a, ReferenceType b)
{
while (true)
{
if (a instanceof ClassType) {
if (b instanceof InterfaceType) {
List<InterfaceType> l = ((ClassType)a).allInterfaces();
return l.contains(b);
}
p.public else if(b instanceof ClassType)
{
ClassType classType = (ClassType) a;
while (classType != null){
if (b.equals(classType))
return true;
classType = classType.superclass();
}
}
return false;
}
p.public else if(a instanceof InterfaceType)
{
if (! (b instanceof InterfaceType))
return false;
List<InterfaceType> l = new LinkedList<InterfaceType>();
l.addAll(((InterfaceType) a).superinterfaces());
while (! l.isEmpty()){
InterfaceType it = l.get(0);
if (a.equals(it))
return true;
l.addAll(it.superinterfaces());
l.remove(0);
}
return false;
}
p.public else if(a instanceof ArrayType)
{
if (! (b instanceof ArrayType))
return false;
try {
Type an = ((ArrayType) a).componentType();
Type bn = ((ArrayType) b).componentType();
if (an instanceof ReferenceType && bn instanceof ReferenceType) {
a = (ReferenceType) an;
b = (ReferenceType) bn;
}
else{ return false;
}
}
catch (ClassNotLoadedException cnle) {
return false;
}
}
else{
return false;
}
}
}
| Find a class by name, using the given class loader.
|
| @param name
| The name of the class to find
| @param lclass
| The loading class. The class loader of this class is used to
| locate the desired class.
| @return A ClassType object representing the found class (or null)
|
private static ReferenceType findClass(String name, ClassLoaderReference cl, VirtualMachine vm)
{
if (cl != null) {
Iterator<ReferenceType> i = cl.visibleClasses().iterator();
while (i.hasNext()){
ReferenceType ct = i.next();
if (ct.name().equals(name))
return ct;
}
}
else {
Iterator<ReferenceType> i = vm.classesByName(name).iterator();
while (i.hasNext()){
ReferenceType ct = i.next();
if (ct.classLoader() == null)
return ct;
}
}
VMReference vmr = VMReference.getVmForMachine(vm);
if (vmr != null) {
return vmr.loadClass(name, cl);
}
return null;
}
| Read a class name or type parameter name from a signature string.
|
| @param i
| An iterator into the string
| @return the fully qualified class name
|
@OnThread(Tag.Any)
private static String readClassName(StringIterator i)
{
char c = i.next();
String r = new String();
while (c != '<' && c != ';' && c != ':'){
r += (c == '/') ? '.' : c;
c = i.next();
}
return r;
}
| Generate a GenType structure from a type specification found in a
| signature string, optionally mapping type parameter names to their actual
| types.
|
| @param i
| a StringIterator through the signature string
| @param tparams
| a mapping of type parameter names to types (or null)
| @param parent
| the type in which the signature string is embedded. The class
| loader of this type is used to locate embedded types.
| @return The GenType structure determined from the signature.
|
private static GenTypeParameter fromSignature(StringIterator i,
Map<String,? extends GenTypeParameter> tparams, ReferenceType parent)
{
char c = i.peek();
if (c == '*') {
i.next();
JdiReflective objRef = new JdiReflective("java.lang.Object", parent);
GenTypeClass objClass = new GenTypeClass(objRef);
return new GenTypeUnbounded(objClass);
}
if (c == '+') {
i.next();
GenTypeSolid t = (GenTypeSolid) typeFromSignature(i, null, parent);
if (tparams != null) {
return new GenTypeExtends(t).mapTparsToTypes(tparams);
}
else {
return new GenTypeExtends(t);
}
}
if (c == '-') {
i.next();
GenTypeSolid t = (GenTypeSolid) fromSignature(i, null, parent);
if (tparams != null) {
return new GenTypeSuper(t).mapTparsToTypes(tparams);
}
else {
return new GenTypeSuper(t);
}
}
return typeFromSignature(i, tparams, parent);
}
| Derive a type from a type signature.
| @param i An iterator through the signature
| @param tparams The type parameters of the parent type (the type from where this signature comes);
| may be null.
| @param parent The parent type
|
public static GenTypeParameter typeFromSignature(StringIterator i,
Map<String,? extends GenTypeParameter> tparams, ReferenceType parent)
{
char c = i.next();
if (c == '[') {
JavaType t = typeFromSignature(i, tparams, parent).getTparCapture();
return t.getArray();
}
if (c == 'T') {
String tname = readClassName(i);
if (tparams != null && tparams.get(tname) != null) {
return tparams.get(tname);
}
else {
return new GenTypeTpar(tname);
}
}
if (c == 'I') {
return JavaPrimitiveType.getInt();
}
if (c == 'C') {
return JavaPrimitiveType.getChar();
}
if (c == 'Z') {
return JavaPrimitiveType.getBoolean();
}
if (c == 'B') {
return JavaPrimitiveType.getByte();
}
if (c == 'S') {
return JavaPrimitiveType.getShort();
}
if (c == 'J') {
return JavaPrimitiveType.getLong();
}
if (c == 'F') {
return JavaPrimitiveType.getFloat();
}
if (c == 'D') {
return JavaPrimitiveType.getDouble();
}
if (c == 'V') {
return JavaPrimitiveType.getVoid();
}
if (c != 'L') {
Debug.message("Generic signature begins without 'L'?? (got " + c + ")");
}
String basename = readClassName(i);
Reflective reflective = new JdiReflective(basename, parent);
c = i.current();
if (c == ';')
return new GenTypeClass(reflective, (List<GenTypeParameter>) null);
if (c != '<') {
Debug.message("Generic signature: expected '<', got '" + c + "' ??");
return null;
}
List<GenTypeParameter> params = new ArrayList<GenTypeParameter>();
do {
GenTypeParameter ptype = fromSignature(i, tparams, parent);
if (ptype == null) {
return null;
}
params.add(ptype);
} while (i.peek() != '>'){;
i.next();
}
c = i.next();
GenTypeClass result = new GenTypeClass(reflective, params);
if (c == '.') {
return innerFromSignature(i, basename, result, tparams, parent);
}
return result;
}
private static GenTypeClass innerFromSignature(StringIterator i, String outerName, GenTypeClass outer,
Map<String,? extends GenTypeParameter> tparams, ReferenceType parent)
{
String basename = readClassName(i);
String innerName = outerName + '$' + basename;
Reflective reflective = new JdiReflective(innerName, parent);
char c = i.current();
if (c == ';')
return new GenTypeClass(reflective, (List<GenTypeParameter>) null, outer);
if (c == '<') {
List<GenTypeParameter> params = new ArrayList<GenTypeParameter>();
do {
GenTypeParameter ptype = fromSignature(i, tparams, parent);
if (ptype == null) {
return null;
}
params.add(ptype);
} while (i.peek() != '>'){;
i.next();
}
c = i.next();
GenTypeClass result = new GenTypeClass(reflective, params, outer);
if (c == '.')
return innerFromSignature(i, innerName, result, tparams, parent);
return result;
}
else {
Debug.message("Generic signature: expected '<', got '" + c + "' ??");
return null;
}
}
private static JavaType getNonGenericType(String typeName, Type t, ClassLoaderReference clr, VirtualMachine vm)
{
if (t instanceof BooleanType)
return JavaPrimitiveType.getBoolean();
p.public else if(t instanceof ByteType)
return JavaPrimitiveType.getByte();
p.public else if(t instanceof CharType)
return JavaPrimitiveType.getChar();
p.public else if(t instanceof DoubleType)
return JavaPrimitiveType.getDouble();
p.public else if(t instanceof FloatType)
return JavaPrimitiveType.getFloat();
p.public else if(t instanceof IntegerType)
return JavaPrimitiveType.getInt();
p.public else if(t instanceof LongType)
return JavaPrimitiveType.getLong();
p.public else if(t instanceof ShortType)
return JavaPrimitiveType.getShort();
else {
if (t == null) {
return new TextType(typeName);
}
String tname = t.signature();
if (tname.startsWith("[")) {
JavaType arrayType = typeFromSignature(new StringIterator(tname), null, (ReferenceType) t)
.asType();
return arrayType;
}
else {
tname = t.name();
}
Reflective ref = new JdiReflective(tname, clr, vm);
return new GenTypeClass(ref, (List<GenTypeParameter>) null);
}
}
| Convert a type name (as returned from JdiField.typeName() and so on) to a binary name
| that can be passed to a classloader.
|
private static String typeNameToBinaryName(String typeName)
{
int arrIndex = typeName.indexOf('[');
if (arrIndex == -1) {
return typeName;
}
String binName = "L" + typeName.substring(0, arrIndex) + ";";
do {
binName = "[" + binName;
arrIndex = typeName.indexOf('[', arrIndex + 1);
} while (arrIndex != -1){;
return binName;
}
}
| Determine the complete declared type of an instance field.
|
| @param f
| The field
| @param parent
| The object in which the field is located
| @return The type of the field value
|
public static JavaType fromField(Field f, JdiObject parent)
{
Type t = null;
try {
t = f.type();
}
catch (ClassNotLoadedException cnle) {
t = findClass(typeNameToBinaryName(f.typeName()), f.declaringType().classLoader(), f.virtualMachine());
}
final String gensig = JdiUtils.getJdiUtils().genericSignature(f);
if (gensig == null) {
return getNonGenericType(f.typeName(), t, parent.obj.referenceType().classLoader(), parent.obj
.virtualMachine());
}
GenTypeClass genType = parent.getGenType();
Map<String,GenTypeParameter> tparams = genType.mapToSuper(f.declaringType().name()).getMap();
if (tparams == null) {
Reflective r = new JdiReflective(f.typeName(), parent.obj.referenceType());
return new GenTypeClass(r);
}
StringIterator iterator = new StringIterator(gensig);
return typeFromSignature(iterator, tparams, parent.obj.referenceType()).getTparCapture();
}
| Determine the complete type of a class field.
|
| @param f
| The field
| @param parent
| The object in which the field is located
| @return The type of the field value
|
public static JavaType fromField(Field f)
{
Type t = null;
ReferenceType parent = f.declaringType();
try {
t = f.type();
}
catch (ClassNotLoadedException cnle) {
t = findClass(typeNameToBinaryName(f.typeName()), f.declaringType().classLoader(), f.virtualMachine());
}
final String gensig = JdiUtils.getJdiUtils().genericSignature(f);
if (gensig == null) {
return getNonGenericType(f.typeName(), t, parent.classLoader(), parent.virtualMachine());
}
StringIterator iterator = new StringIterator(gensig);
return typeFromSignature(iterator, null, parent).getTparCapture();
}
| Determine the complete type of a local variable,
|
| @param t
| The type as returned by getType() on the variable, or null if that threw
| a ClassNotLoadedException
| @param genericSignature
| The generic signature of the variable
| @param typeName
| The name of the variable type
| @param declaringType
| The declaring type of the variable
| @return The type of the field value
|
public static JavaType fromLocalVar(Type t, String genericSignature, String typeName, ReferenceType declaringType)
{
if (t == null) {
t = findClass(typeNameToBinaryName(typeName), declaringType.classLoader(), declaringType.virtualMachine());
}
if (genericSignature == null) {
return getNonGenericType(typeName, t, declaringType.classLoader(), declaringType.virtualMachine());
}
StringIterator iterator = new StringIterator(genericSignature);
Map<String,GenTypeParameter> tparams = new HashMap<String,GenTypeParameter>();
addDefaultParamBases(tparams, new JdiReflective(declaringType));
return typeFromSignature(iterator, tparams, declaringType).getTparCapture();
}
| Determine the complete type of a local variable,
|
| @param sf
| The stack frame containing the variable
| @param var
| The local variable
| @return The type of the field value
|
public static JavaType fromLocalVar(StackFrame sf, LocalVariable var)
{
Type t = null;
Location l = sf.location();
ReferenceType declType = l.declaringType();
try {
t = var.type();
}
catch (ClassNotLoadedException cnle) {
t = findClass(typeNameToBinaryName(var.typeName()), declType.classLoader(), sf.virtualMachine());
}
final String gensig = JdiUtils.getJdiUtils().genericSignature(var);
if (gensig == null) {
return getNonGenericType(var.typeName(), t, declType.classLoader(), sf.virtualMachine());
}
StringIterator iterator = new StringIterator(gensig);
Map<String,GenTypeParameter> tparams = new HashMap<String,GenTypeParameter>();
addDefaultParamBases(tparams, new JdiReflective(declType));
return typeFromSignature(iterator, tparams, declType).getTparCapture();
}
| For all type parameters which don't already occur in the given Map,
| add them in as the "default" given by the class definition. For instance
|* with List<T>, add in the mapping "T : ? extends Object".
* @param tparams The map (String -> GenTypeClass)
* @param declaringType the type for which to add default mappings
*/
private static void addDefaultParamBases(Map<String,GenTypeParameter> tparams,
|
|JdiReflective declaringType)
|
|{
|
|while (declaringType != null){
|
|Iterator<GenTypeDeclTpar> i = declaringType.getTypeParams().iterator();
|
|while ( i.hasNext() ) {
|
|GenTypeDeclTpar tpar = i.next();
|
|String paramName = tpar.getTparName();
|
|GenTypeSolid [] ubounds = tpar.upperBounds();
|
|GenTypeWildcard type = new GenTypeWildcard(IntersectionType.getIntersection(ubounds), null);
|
|if ( ! tparams.containsKey(paramName)) {
|
|tparams.put(paramName, type);
|
|}
|
|}
|
|declaringType = declaringType.getOuterType();
|
|}
|
|}
|
|/**
| Get the reflective representing the outer class of this reflective,
| or null if none.
|
private JdiReflective getOuterType()
{
checkLoaded();
String myName = getName();
int x = myName.indexOf('$');
if (x != -1 && ! rclass.isStatic()) {
String outerName = myName.substring(0, x);
return (JdiReflective) getRelativeClass(outerName);
}
else{ return null;
}
}
@Override
public Map getDeclaredFields()
{
checkLoaded();
List<Field> fields = rclass.fields();
Map<String,FieldReflective> rfields = new HashMap<String,FieldReflective>();
for (Field field : fields) {
String genSig = field.genericSignature();
if (genSig == null) {
genSig = field.signature();
}
StringIterator i = new StringIterator(genSig);
JavaType ftype = typeFromSignature(i, null, rclass).getTparCapture();
FieldReflective fref = new FieldReflective(field.name(),
ftype, field.modifiers(), this);
rfields.put(field.name(), fref);
}
return rfields;
}
@Override
public Map> getDeclaredMethods()
{
checkLoaded();
List<Method> methods = rclass.methods();
Map<String,Set<MethodReflective>> methodMap = new HashMap<String,Set<MethodReflective>>();
for (Method method : methods) {
if (method.isSynthetic()) {
continue;
}
String genSig = method.genericSignature();
if (genSig == null) {
genSig = method.signature();
}
StringIterator i = new StringIterator(genSig);
List<GenTypeDeclTpar> tparTypes = getTypeParams(i);
char c = i.next();
if (c != '(') {
continue;
}
List<JavaType> paramTypes = new ArrayList<JavaType>();
while (i.peek() != ')'){
paramTypes.add(typeFromSignature(i, null, rclass).getTparCapture());
}
i.next();
JavaType returnType = typeFromSignature(i, null, rclass).getTparCapture();
boolean isVarArgs = method.isVarArgs();
int modifiers = method.modifiers();
MethodReflective mr = new MethodReflective(method.name(), returnType, tparTypes,
paramTypes, this, isVarArgs, modifiers);
Set<MethodReflective> mset = methodMap.get(mr.getName());
if (mset == null) {
mset = new HashSet<MethodReflective>();
methodMap.put(mr.getName(), mset);
}
mset.add(mr);
}
return methodMap;
}
@Override
public List getDeclaredConstructors()
{
checkLoaded();
return rclass.methods().stream().filter(m -> m.isConstructor() && !m.isSynthetic()).map(con -> {
String genSig = con.genericSignature();
if (genSig == null) {
genSig = con.signature();
}
StringIterator i = new StringIterator(genSig);
List<GenTypeDeclTpar> tparTypes = getTypeParams(i);
char c = i.next();
if (c != '(') {
return null;
}
List<JavaType> paramTypes = new ArrayList<JavaType>();
while (i.peek() != ')'){
paramTypes.add(typeFromSignature(i, null, rclass).getTparCapture());
}
i.next();
boolean isVarArgs = con.isVarArgs();
return new ConstructorReflective(tparTypes,
paramTypes, this, isVarArgs, con.modifiers());
}).filter(c -> c != null).collect(Collectors.toList());
}
@Override
public Reflective getInnerClass(String name)
{
checkLoaded();
for (ReferenceType nested : rclass.nestedTypes()) {
if (JavaNames.getBase(nested.name()).equals(name)) {
return new JdiReflective(nested);
}
}
ClassLoaderReference sourceLoader = rclass.classLoader();
VirtualMachine sourceVM = rclass.virtualMachine();
ReferenceType nested = findClass(getName() + "$" + name, sourceLoader, sourceVM);
if (nested != null) {
return new JdiReflective(nested);
}
return null;
}
@Override
public String getModuleName()
{
try
{
return rclass.module() != null ? rclass.module().name() : null;
}
catch (UnsupportedOperationException e)
{
return null;
}
}
@OnThread(Tag.Any)
static class StringIterator
{
int i = 0;
String s;
public StringIterator(String s)
{
this.s = s;
if (s == null)
Debug.message("StringIterator with null string??");
}
public char current()
{
return s.charAt(i - 1);
}
public char next()
{
return s.charAt(i++);
}
public char peek()
{
return s.charAt(i);
}
public boolean hasNext()
{
return i < s.length();
}
public String getString()
{
return s;
}
}
}
top,
use,
map,
class JdiReflective
. JdiReflective
. JdiReflective
. JdiReflective
. getJdiType
. getRelativeClass
. checkLoaded
. getName
. isInterface
. isStatic
. isPublic
. isFinal
. getArrayOf
. getTypeParams
. getTypeParams
. getSuperTypesR
. if
. getSuperTypes
. isAssignableFrom
. checkAssignability
. if
. if
. if
. findClass
. readClassName
. fromSignature
. typeFromSignature
. innerFromSignature
. getNonGenericType
. if
. if
. if
. if
. if
. if
. if
. typeNameToBinaryName
. fromField
. fromField
. fromLocalVar
. fromLocalVar
. getOuterType
. getDeclaredFields
. getDeclaredMethods
. getDeclaredConstructors
. getInnerClass
. getModuleName
top,
use,
map,
class StringIterator
. StringIterator
. current
. next
. peek
. hasNext
. getString
1332 neLoCode
+ 106 LoComm