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