Collection<TraitFieldDescriptor> (byte[] fileContents) { final Collection<TraitFieldDescriptor> values = new ArrayList<>(); new ClassReader(fileContents).accept(new ClassVisitor(Opcodes.API_VERSION) { @Override public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { return new FieldVisitor(Opcodes.API_VERSION) { private final List<String> annotations = new SmartList<>(); @Override public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { return StubBuildingVisitor.getAnnotationTextCollector(descriptor, annotations::add); } @Override public void visitEnd() { processField(access, name, desc, signature, annotations); } }; } private void processField(int access, String name, String desc, String signature, List<String> annotations) { if ((access & ACC_SYNTHETIC) == 0) return; final boolean isStatic; final boolean isPublic; Pair<Boolean, String> p; if ((p = parse(STATIC_PREFIX, INSTANCE_PREFIX, name)).first != null) { isStatic = p.first; name = p.second; } else { return; } if ((p = parse(PUBLIC_PREFIX, PRIVATE_PREFIX, name)).first != null) { isPublic = p.first; name = p.second; } else { return; } final String typeString = fieldType(desc, signature); if (typeString == null) return; final int delimiter = name.indexOf(DELIMITER); if (delimiter > -1) { name = name.substring(delimiter + DELIMITER.length()); } byte flags = (byte)((isPublic ? TraitFieldDescriptor.PUBLIC : 0) | (isStatic ? TraitFieldDescriptor.STATIC : 0)); values.add(new TraitFieldDescriptor(flags, typeString, name, annotations)); } private static Pair<Boolean, String> parse(String prefix, String prefix2, String input) { if (input.startsWith(prefix)) { return Pair.create(true, input.substring(prefix.length())); } else if (input.startsWith(prefix2)) { return Pair.create(false, input.substring(prefix2.length())); } else { return Pair.create(null, input); } } private static String fieldType(String desc, String signature) { if (signature != null) { try { return SignatureParsing.parseTypeStringToTypeInfo(new SignatureParsing.CharIterator(signature), StubBuildingVisitor.GUESSING_PROVIDER).text(); } catch (ClsFormatException ignored) { } } String raw = Type.getType(desc).getClassName(); return StubBuildingVisitor.GUESSING_MAPPER.fun(raw); } }, EMPTY_ATTRIBUTES, ClassReader.SKIP_CODE); return values; }