private void valuePairPrefix(final String name) {
      if (!hasParams) {
        hasParams = true;
        if (myDesc != null) {
          myBuilder.append('(');
        }
      } else {
        myBuilder.append(',');
      }

      if (name != null) {
        myBuilder.append(name).append('=');
      }
    }
 @Override
 public void visitEnd() {
   if (hasParams && myDesc != null) {
     myBuilder.append(')');
   }
   myCallback.callback(myBuilder.toString());
 }
    public AnnotationTextCollector(@Nullable String desc, AnnotationResultCallback callback) {
      super(Opcodes.ASM4);
      myCallback = callback;

      myDesc = desc;
      if (desc != null) {
        myBuilder.append('@').append(getTypeText(Type.getType(desc)));
      }
    }
 @Override
 public AnnotationVisitor visitArray(final String name) {
   valuePairPrefix(name);
   myBuilder.append("{");
   return new AnnotationTextCollector(
       null,
       new AnnotationResultCallback() {
         @Override
         public void callback(final String text) {
           myBuilder.append(text).append('}');
         }
       });
 }
  @Nullable
  private static String constToString(@Nullable Object value, @Nullable String type, boolean anno) {
    if (value == null) return null;

    if (value instanceof String) {
      return "\"" + StringUtil.escapeStringCharacters((String) value) + "\"";
    }

    if (value instanceof Boolean || value instanceof Short || value instanceof Byte) {
      return value.toString();
    }

    if (value instanceof Character) {
      return "'" + StringUtil.escapeCharCharacters(value.toString()) + "'";
    }

    if (value instanceof Long) {
      return value.toString() + "L";
    }

    if (value instanceof Integer) {
      if ("boolean".equals(type)) {
        if (value.equals(0)) return "false";
        if (value.equals(1)) return "true";
      }
      if ("char".equals(type)) {
        char ch = (char) ((Integer) value).intValue();
        return "'" + StringUtil.escapeCharCharacters(String.valueOf(ch)) + "'";
      }
      return value.toString();
    }

    if (value instanceof Double) {
      final double d = ((Double) value).doubleValue();
      if (Double.isInfinite(d)) {
        return d > 0 ? DOUBLE_POSITIVE_INF : DOUBLE_NEGATIVE_INF;
      } else if (Double.isNaN(d)) {
        return DOUBLE_NAN;
      }
      return Double.toString(d);
    }

    if (value instanceof Float) {
      final float v = ((Float) value).floatValue();

      if (Float.isInfinite(v)) {
        return v > 0 ? FLOAT_POSITIVE_INF : FLOAT_NEGATIVE_INF;
      } else if (Float.isNaN(v)) {
        return FLOAT_NAN;
      } else {
        return Float.toString(v) + "f";
      }
    }

    if (value.getClass().isArray()) {
      StringBuilder buffer = new StringBuilder();
      buffer.append('{');
      for (int i = 0, length = Array.getLength(value); i < length; i++) {
        if (i > 0) buffer.append(", ");
        buffer.append(Array.get(value, i));
      }
      buffer.append('}');
      return buffer.toString();
    }

    if (anno && value instanceof Type) {
      return getTypeText((Type) value) + ".class";
    }

    return null;
  }
 @Override
 public void visitEnum(final String name, final String desc, final String value) {
   valuePairPrefix(name);
   myBuilder.append(getTypeText(Type.getType(desc))).append(".").append(value);
 }
 @Override
 public void visit(final String name, final Object value) {
   valuePairPrefix(name);
   myBuilder.append(constToString(value, null, true));
 }