private static @NotNull FirstPassData fromReader(@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) {
        String suffix = ".groovy";
        if (source != null && source.length() > suffix.length() &&
            source.regionMatches(true, source.length() - suffix.length(), suffix, 0, suffix.length())) {
          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);
  }
private static @NotNull FirstPassData fromReader(@NotNull ClassReader reader)