code: package org.pitest.rv;
  
  import org.pitest.reloc.asm.MethodVisitor;
  import org.pitest.reloc.asm.Opcodes;
  import org.pitest.bytecode.ASMVersion;
  import org.pitest.mutationtest.engine.MutationIdentifier;
  import org.pitest.mutationtest.engine.gregor.MethodInfo;
  import org.pitest.mutationtest.engine.gregor.MethodMutatorFactory;
  import org.pitest.mutationtest.engine.gregor.MutationContext;
  
  /**
   * Mutator designed to insert (-) in front of Integer, Float, Long, Double
   * variable values.
   *
   * Applicable for array values, static and non static fields and local
   * variables.
   */
  public enum ABSMutator implements MethodMutatorFactory {
  
      ABS;
  
      public MethodVisitor create(final MutationContext context, final MethodInfo methodInfo,
                                  final MethodVisitor methodVisitor) {
          return new ABSMethodVisitor(this, context, methodVisitor);
      }
  
      @Override
      public String getGloballyUniqueId() {
          return this.getClass().getName();
      }
  
      public String getName() {
          return name();
      }
  }
  
  class ABSMethodVisitor extends MethodVisitor {
  
      private final MethodMutatorFactory factory;
      private final MutationContext context;
  
      ABSMethodVisitor(final MethodMutatorFactory factory, final MutationContext context,
                       final MethodVisitor delegateMethodVisitor) {
          super(ASMVersion.ASM_VERSION, delegateMethodVisitor);
          this.factory = factory;
          this.context = context;
      }
  
      private boolean shouldMutate(String message) {
          if (this.context.getClassInfo().isEnum()) {
              return false;
          }
          final MutationIdentifier newId = this.context.registerMutation(this.factory, message);
          return this.context.shouldMutate(newId);
      }
  
      // Local variables
      @Override
      public void visitVarInsn(int opcode, int var) {
          mv.visitVarInsn(opcode, var); // push the variable.
  
          switch (opcode) {
              case Opcodes.ILOAD:
                  if (this.shouldMutate("Negated integer local variable number " + var)) {
                      mv.visitInsn(Opcodes.INEG);
                  }
                  break;
  
              case Opcodes.FLOAD:
                  if (this.shouldMutate("Negated float local variable number " + var)) {
                      mv.visitInsn(Opcodes.FNEG);
                  }
                  break;
  
              case Opcodes.LLOAD:
                  if (this.shouldMutate("Negated long local variable number " + var)) {
                      mv.visitInsn(Opcodes.LNEG);
                  }
                  break;
  
              case Opcodes.DLOAD:
                  if (this.shouldMutate("Negated double local variable number " + var)) {
                      mv.visitInsn(Opcodes.DNEG);
                  }
                  break;
              default:
                  break;
          }
      }
  
      // Fields, static or not.
      @Override
      public void visitFieldInsn(int opcode, String owner, String name, String desc) {
  
          mv.visitFieldInsn(opcode, owner, name, desc);
  
          // non static
          if (opcode == Opcodes.GETFIELD) {
              if (desc.equals("I")) {
                  if (this.shouldMutate("Negated integer field " + name)) {
                      mv.visitInsn(Opcodes.INEG);
                      return;
                  }
              }
              if (desc.equals("F")) {
                  if (this.shouldMutate("Negated float field " + name)) {
                      mv.visitInsn(Opcodes.FNEG);
                      return;
                  }
              }
              if (desc.equals("J")) {
                  if (this.shouldMutate("Negated long field " + name)) {
                      mv.visitInsn(Opcodes.LNEG);
                      return;
                  }
              }
              if (desc.equals("D")) {
                  if (this.shouldMutate("Negated double field " + name)) {
                      mv.visitInsn(Opcodes.DNEG);
                      return;
                  }
              }
              if (desc.equals("B")) {
                  if (this.shouldMutate("Negated byte field " + name)) {
                      mv.visitInsn(Opcodes.INEG);
                      mv.visitInsn(Opcodes.I2B);
                      return;
                  }
              }
              if (desc.equals("S")) {
                  if (this.shouldMutate("Negated short field " + name)) {
                      mv.visitInsn(Opcodes.INEG);
                      mv.visitInsn(Opcodes.I2S);
                      return;
                  }
              }
          }
  
          // static
          if (opcode == Opcodes.GETSTATIC) {
              if (desc.equals("I")) {
                  if (this.shouldMutate("Negated integer static field " + name)) {
                      mv.visitInsn(Opcodes.INEG);
                      return;
                  }
              }
              if (desc.equals("F")) {
                  if (this.shouldMutate("Negated float static field " + name)) {
                      mv.visitInsn(Opcodes.FNEG);
                      return;
                  }
              }
              if (desc.equals("J")) {
                  if (this.shouldMutate("Negated long static field " + name)) {
                      mv.visitInsn(Opcodes.LNEG);
                      return;
                  }
              }
              if (desc.equals("D")) {
                  if (this.shouldMutate("Negated double static field " + name)) {
                      mv.visitInsn(Opcodes.DNEG);
                      return;
                  }
              }
              if (desc.equals("B")) {
                  if (this.shouldMutate("Negated byte static field " + name)) {
                      mv.visitInsn(Opcodes.INEG);
                      mv.visitInsn(Opcodes.I2B);
                      return;
                  }
              }
              if (desc.equals("S")) {
                  if (this.shouldMutate("Negated short static field " + name)) {
                      mv.visitInsn(Opcodes.INEG);
                      mv.visitInsn(Opcodes.I2S);
                      return;
                  }
              }
          }
      }
  
      @Override
      public void visitInsn(final int opcode) {
          mv.visitInsn(opcode);
          switch (opcode) {
              // ARRAYS I F L D , loading
              case Opcodes.IALOAD:
                  if (this.shouldMutate("Negated integer array field")) {
                      mv.visitInsn(Opcodes.INEG);
                  }
                  break;
  
              case Opcodes.FALOAD:
                  if (this.shouldMutate("Negated float array field")) {
                      mv.visitInsn(Opcodes.FNEG);
                  }
                  break;
  
              case Opcodes.LALOAD:
                  if (this.shouldMutate("Negated long array field")) {
                      mv.visitInsn(Opcodes.LNEG);
                  }
                  break;
  
              case Opcodes.DALOAD:
                  if (this.shouldMutate("Negated double array field")) {
                      mv.visitInsn(Opcodes.DNEG);
                  }
                  break;
  
              case Opcodes.BALOAD:
                  if (this.shouldMutate("Negated byte array field")) {
                      mv.visitInsn(Opcodes.INEG);
                      mv.visitInsn(Opcodes.I2B);
                  }
                  break;
  
              case Opcodes.SALOAD:
                  if (this.shouldMutate("Negated short array field")) {
                      mv.visitInsn(Opcodes.INEG);
                      mv.visitInsn(Opcodes.I2S);
                  }
                  break;
  
              default:
                  break;
          }
      }
  }