FirstPassData (@NotNull ClassReader reader) { class FirstPassVisitor extends ClassVisitor { final Map<String, ClassEntry> mapping = new HashMap<>(); Set<String> varArgConstructors; Set<ObjectMethod> syntheticSignatures; StringBuilder canonicalSignature; String lastComponent; String name; boolean trustInnerClasses = true; boolean sealed = false; FirstPassVisitor() { super(Opcodes.API_VERSION); } @Override public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { if (isSet(access, Opcodes.ACC_RECORD)) { varArgConstructors = new HashSet<>(); canonicalSignature = new StringBuilder("("); syntheticSignatures = EnumSet.noneOf(ObjectMethod.class); } this.name = name; } @Override public void visitSource(String source, String debug) { if (source != null && StringUtil.endsWithIgnoreCase(source, ".groovy")) { trustInnerClasses = false; } super.visitSource(source, debug); } @Override public void visitPermittedSubclass(String permittedSubclass) { sealed = true; } @Override public RecordComponentVisitor visitRecordComponent(String name, String descriptor, String signature) { if (isRecord()) { canonicalSignature.append(descriptor); lastComponent = name; } return null; } private boolean isRecord() { return varArgConstructors != null; } @Override public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { if (isRecord()) { if (name.equals("<init>") && isSet(access, Opcodes.ACC_VARARGS)) { varArgConstructors.add(descriptor); } ObjectMethod method = ObjectMethod.from(name, descriptor); if (method != null) { return new MethodVisitor(Opcodes.API_VERSION) { @Override public void visitInvokeDynamicInsn(String indyName, String indyDescriptor, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) { if (indyName.equals(name) && bootstrapMethodHandle.getName().equals("bootstrap") && bootstrapMethodHandle.getOwner().equals("java/lang/runtime/ObjectMethods")) { syntheticSignatures.add(method); } } }; } } return null; } @Override public void visitInnerClass(String name, String outerName, String innerName, int access) { if (outerName != null && innerName != null) { mapping.put(name, new StringInnerClassEntry(outerName, innerName, isSet(access, Opcodes.ACC_STATIC))); } } } FirstPassVisitor visitor = new FirstPassVisitor(); try { reader.accept(visitor, ClsFileImpl.EMPTY_ATTRIBUTES, ClassReader.SKIP_FRAMES); } catch (Exception ex) { LOG.debug(ex); } String varArgComponent = null; if (visitor.isRecord()) { visitor.canonicalSignature.append(")V"); if (visitor.varArgConstructors.contains(visitor.canonicalSignature.toString())) { varArgComponent = visitor.lastComponent; } } Set<ObjectMethod> syntheticMethods = visitor.syntheticSignatures == null ? Collections.emptySet() : visitor.syntheticSignatures; return new FirstPassData(visitor.mapping, visitor.name, varArgComponent, syntheticMethods, visitor.trustInnerClasses, visitor.sealed); }