content: package org.aion.avm.core.miscvisitors;
  
  import org.aion.avm.core.ClassToolchain;
  import org.objectweb.asm.FieldVisitor;
  import org.objectweb.asm.MethodVisitor;
  import org.objectweb.asm.Opcodes;
  
  import java.util.Map;
  
  import static org.objectweb.asm.Opcodes.ACC_INTERFACE;
  
  /**
   * A visitor which updates PUT_FIELD and GET_FIELD corresponding to an interface field (issue-208) based on the mapping generated by
   * InterfaceFieldClassGeneratorVisitor.
   */
  public class InterfaceFieldNameMappingVisitor extends ClassToolchain.ToolChainClassVisitor {
  
      private boolean isInterface = false;
      private Map<String, String> interfaceFieldClassNames;
  
      /**
       * Create an InterfaceFieldNameMappingVisitor instance.
       *
       * @param interfaceFieldClassNames HashMap containing the mapping between class name and generated FIELDS class
       */
      public InterfaceFieldNameMappingVisitor(Map<String, String> interfaceFieldClassNames) {
          super(Opcodes.ASM6);
          this.interfaceFieldClassNames = interfaceFieldClassNames;
  
      }
  
      @Override
      public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
          if ((access & ACC_INTERFACE) != 0) {
              this.isInterface = true;
          }
          super.visit(version, access, name, signature, superName, interfaces);
      }
  
      @Override
      public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
          MethodVisitor mv;
          if (isInterface && "<clinit>".equals(name)) {
              // remove the clinit from interface. clinit has been written to the generated class in InterfaceFieldClassGeneratorVisitor.
              return null;
          } else {
              mv = super.visitMethod(access, name, descriptor, signature, exceptions);
              // update the owner of all interface fields
              return new MethodVisitor(Opcodes.ASM6, mv) {
                  public void visitFieldInsn(int opcode, String owner, String name, String descriptor) {
                      if (interfaceFieldClassNames.keySet().contains(owner)) {
                          owner = interfaceFieldClassNames.get(owner);
                      }
                      super.visitFieldInsn(opcode, owner, name, descriptor);
                  }
              };
          }
      }
  
      @Override
      public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) {
          if (isInterface) {
              // Interface fields can be removed, since they have been placed in the generated class in InterfaceFieldClassGeneratorVisitor.
              return null;
          } else {
              return super.visitField(access, name, descriptor, signature, value);
          }
      }
  
  
  }
  