public static MethodInfo createAnnotationMethod(
      byte classFileBytes[], int offsets[], int offset) {
    MethodInfo methodInfo = new MethodInfo(classFileBytes, offsets, offset);
    int attributesCount = methodInfo.u2At(6);
    int readOffset = 8;
    AnnotationInfo[] annotations = null;
    Object defaultValue = null;
    for (int i = 0; i < attributesCount; i++) {
      // check the name of each attribute
      int utf8Offset =
          methodInfo.constantPoolOffsets[methodInfo.u2At(readOffset)] - methodInfo.structOffset;
      char[] attributeName = methodInfo.utf8At(utf8Offset + 3, methodInfo.u2At(utf8Offset + 1));
      if (attributeName.length > 0) {
        switch (attributeName[0]) {
          case 'A':
            if (CharOperation.equals(
                attributeName, AttributeNamesConstants.AnnotationDefaultName)) {
              // readOffset + 6 so the offset is at the start of the 'member_value' entry
              // u2 attribute_name_index + u4 attribute_length = + 6
              AnnotationInfo info =
                  new AnnotationInfo(
                      methodInfo.reference,
                      methodInfo.constantPoolOffsets,
                      readOffset + 6 + methodInfo.structOffset);
              defaultValue = info.decodeDefaultValue();
            }
            break;
          case 'S':
            if (CharOperation.equals(AttributeNamesConstants.SignatureName, attributeName))
              methodInfo.signatureUtf8Offset =
                  methodInfo.constantPoolOffsets[methodInfo.u2At(readOffset + 6)]
                      - methodInfo.structOffset;
            break;
          case 'R':
            AnnotationInfo[] methodAnnotations = null;
            if (CharOperation.equals(
                attributeName, AttributeNamesConstants.RuntimeVisibleAnnotationsName)) {
              methodAnnotations = decodeMethodAnnotations(readOffset, true, methodInfo);
            } else if (CharOperation.equals(
                attributeName, AttributeNamesConstants.RuntimeInvisibleAnnotationsName)) {
              methodAnnotations = decodeMethodAnnotations(readOffset, false, methodInfo);
            }
            if (methodAnnotations != null) {
              if (annotations == null) {
                annotations = methodAnnotations;
              } else {
                int length = annotations.length;
                AnnotationInfo[] newAnnotations =
                    new AnnotationInfo[length + methodAnnotations.length];
                System.arraycopy(annotations, 0, newAnnotations, 0, length);
                System.arraycopy(
                    methodAnnotations, 0, newAnnotations, length, methodAnnotations.length);
                annotations = newAnnotations;
              }
            }
            break;
        }
      }
      readOffset += (6 + methodInfo.u4At(readOffset + 2));
    }
    methodInfo.attributeBytes = readOffset;

    if (defaultValue != null) {
      if (annotations != null) {
        return new AnnotationMethodInfoWithAnnotations(methodInfo, defaultValue, annotations);
      }
      return new AnnotationMethodInfo(methodInfo, defaultValue);
    }
    if (annotations != null) return new MethodInfoWithAnnotations(methodInfo, annotations);
    return methodInfo;
  }