/** Returns a shrunk descriptor or signature of the given method. */
  private String shrinkDescriptor(Method method, String descriptor) {
    // All parameters of non-static methods are shifted by one in the local
    // variable frame.
    int parameterIndex =
        (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 ? 0 : 1;

    // Go over the parameters.
    InternalTypeEnumeration internalTypeEnumeration = new InternalTypeEnumeration(descriptor);

    StringBuffer newDescriptorBuffer = new StringBuffer();

    newDescriptorBuffer.append(internalTypeEnumeration.formalTypeParameters());
    newDescriptorBuffer.append(ClassConstants.INTERNAL_METHOD_ARGUMENTS_OPEN);

    while (internalTypeEnumeration.hasMoreTypes()) {
      String type = internalTypeEnumeration.nextType();
      if (ParameterUsageMarker.isParameterUsed(method, parameterIndex)) {
        newDescriptorBuffer.append(type);
      } else if (DEBUG) {
        System.out.println("  Deleting parameter #" + parameterIndex + " [" + type + "]");
      }

      parameterIndex += ClassUtil.isInternalCategory2Type(type) ? 2 : 1;
    }

    newDescriptorBuffer.append(ClassConstants.INTERNAL_METHOD_ARGUMENTS_CLOSE);
    newDescriptorBuffer.append(internalTypeEnumeration.returnType());

    return newDescriptorBuffer.toString();
  }
예제 #2
0
  public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute) {
    // Process the generic definitions, superclass, and implemented
    // interfaces.
    String signature = clazz.getString(signatureAttribute.u2signatureIndex);

    // Count the signature types.
    InternalTypeEnumeration internalTypeEnumeration = new InternalTypeEnumeration(signature);

    int count = 0;
    int interfacesCount = -1;
    while (internalTypeEnumeration.hasMoreTypes()) {
      String internalType = internalTypeEnumeration.nextType();

      count++;

      if (ClassUtil.isInternalClassType(internalType)) {
        interfacesCount++;
      }
    }

    // Put the signature types in an array.
    internalTypeEnumeration = new InternalTypeEnumeration(signature);

    String[] internalTypes = new String[count];

    for (int index = 0; index < count; index++) {
      String internalType = internalTypeEnumeration.nextType();

      internalTypes[index] = internalType;
    }

    // Sort the interface types in the array.
    Arrays.sort(internalTypes, count - interfacesCount, count);

    // Recompose the signature types in a string.
    StringBuffer newSignatureBuffer = new StringBuffer();

    for (int index = 0; index < count; index++) {
      // Is this not an interface type, or an interface type that isn't
      // a duplicate of the previous interface type?
      if (index < count - interfacesCount
          || !internalTypes[index].equals(internalTypes[index - 1])) {
        newSignatureBuffer.append(internalTypes[index]);
      }
    }

    String newSignature = newSignatureBuffer.toString();

    // Did the signature change?
    if (!newSignature.equals(signature)) {
      // Update the signature.
      ((Utf8Constant) ((ProgramClass) clazz).constantPool[signatureAttribute.u2signatureIndex])
          .setString(newSignatureBuffer.toString());

      // Clear the referenced classes.
      // TODO: Properly update the referenced classes.
      signatureAttribute.referencedClasses = null;
    }
  }
  /** Shrinks the array of referenced classes of the given method. */
  private Clazz[] shrinkReferencedClasses(
      Method method, String descriptor, Clazz[] referencedClasses) {
    if (referencedClasses != null) {
      // All parameters of non-static methods are shifted by one in the local
      // variable frame.
      int parameterIndex =
          (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 ? 0 : 1;

      int referencedClassIndex = 0;
      int newReferencedClassIndex = 0;

      // Go over the parameters.
      InternalTypeEnumeration internalTypeEnumeration = new InternalTypeEnumeration(descriptor);

      // Also look at the formal type parameters.
      String type = internalTypeEnumeration.formalTypeParameters();
      int count = new DescriptorClassEnumeration(type).classCount();
      for (int counter = 0; counter < count; counter++) {
        referencedClasses[newReferencedClassIndex++] = referencedClasses[referencedClassIndex++];
      }

      while (internalTypeEnumeration.hasMoreTypes()) {
        // Consider the classes referenced by this parameter type.
        type = internalTypeEnumeration.nextType();
        count = new DescriptorClassEnumeration(type).classCount();

        if (ParameterUsageMarker.isParameterUsed(method, parameterIndex)) {
          // Copy the referenced classes.
          for (int counter = 0; counter < count; counter++) {
            referencedClasses[newReferencedClassIndex++] =
                referencedClasses[referencedClassIndex++];
          }
        } else {
          // Skip the referenced classes.
          referencedClassIndex += count;
        }

        parameterIndex += ClassUtil.isInternalCategory2Type(type) ? 2 : 1;
      }

      // Also look at the return value.
      type = internalTypeEnumeration.returnType();
      count = new DescriptorClassEnumeration(type).classCount();
      for (int counter = 0; counter < count; counter++) {
        referencedClasses[newReferencedClassIndex++] = referencedClasses[referencedClassIndex++];
      }

      // Clear the unused entries.
      while (newReferencedClassIndex < referencedClassIndex) {
        referencedClasses[newReferencedClassIndex++] = null;
      }
    }

    return referencedClasses;
  }
  public void visitAnyParameterAnnotationsAttribute(
      Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute) {
    int[] annotationsCounts = parameterAnnotationsAttribute.u2parameterAnnotationsCount;
    Annotation[][] annotations = parameterAnnotationsAttribute.parameterAnnotations;

    // All parameters of non-static methods are shifted by one in the local
    // variable frame.
    int parameterIndex =
        (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0 ? 0 : 1;

    int annotationIndex = 0;
    int newAnnotationIndex = 0;

    // Go over the parameters.
    String descriptor = method.getDescriptor(clazz);
    InternalTypeEnumeration internalTypeEnumeration = new InternalTypeEnumeration(descriptor);

    while (internalTypeEnumeration.hasMoreTypes()) {
      String type = internalTypeEnumeration.nextType();
      if (ParameterUsageMarker.isParameterUsed(method, parameterIndex)) {
        annotationsCounts[newAnnotationIndex] = annotationsCounts[annotationIndex];
        annotations[newAnnotationIndex++] = annotations[annotationIndex];
      }

      annotationIndex++;

      parameterIndex += ClassUtil.isInternalCategory2Type(type) ? 2 : 1;
    }

    // Update the number of parameters.
    parameterAnnotationsAttribute.u2parametersCount = newAnnotationIndex;

    // Clear the unused entries.
    while (newAnnotationIndex < annotationIndex) {
      annotationsCounts[newAnnotationIndex] = 0;
      annotations[newAnnotationIndex++] = null;
    }
  }