// Path: src/org/jf/dexlib2/iface/Annotation.java
// public interface Annotation extends BasicAnnotation, Comparable<Annotation> {
//     /**
//      * Gets the visibility of this annotation.
//      *
//      * This will be one of the AnnotationVisibility.* constants.
//      *
//      * @return The visibility of this annotation
//      */
//     int getVisibility();
// 
//     /**
//      * Gets the type of this annotation.
//      *
//      * This will be the type descriptor of the class that defines this annotation.
//      *
//      * @return The type of this annotation
//      */
//     @Nonnull @Override String getType();
// 
//     /**
//      * Gets a set of the name/value elements associated with this annotation.
//      *
//      * The elements in the returned set will be unique with respect to the element name.
//      *
//      * @return A set of AnnotationElements
//      */
//     @Nonnull @Override Set<? extends AnnotationElement> getElements();
// 
//     /**
//      * Returns a hashcode for this Annotation.
//      *
//      * This hashCode is defined to be the following:
//      *
//      * <pre>
//      * {@code
//      * int hashCode = getVisibility();
//      * hashCode = hashCode*31 + getType().hashCode();
//      * hashCode = hashCode*31 + getElements().hashCode();
//      * }</pre>
//      *
//      * @return The hash code value for this Annotation
//      */
//     @Override int hashCode();
// 
//     /**
//      * Compares this Annotation to another Annotation for equality.
//      *
//      * This Annotation is equal to another Annotation if all of it's "fields" are equal. That is, if the return values
//      * of getVisibility(), getType(), and getElements() are all equal.
//      *
//      * @param o The object to be compared for equality with this Annotation
//      * @return true if the specified object is equal to this Annotation
//      */
//     @Override boolean equals(@Nullable Object o);
// 
//     /**
//      * Compares this Annotation to another Annotation.
//      *
//      * The comparison is based on the value of getVisibility(), getType() and getElements(), in that order. When
//      * comparing the set of elements, the comparison is done with the semantics of
//      * org.jf.util.CollectionUtils.compareAsSet(), using the natural ordering of AnnotationElement.
//      *
//      * @param o The Annotation to compare with this Annotation
//      * @return An integer representing the result of the comparison
//      */
//     @Override int compareTo(Annotation o);
// }
// 
// Path: src/org/jf/dexlib2/iface/Method.java
// public interface Method extends MethodReference, Member {
//     /**
//      * Gets the type of the class that defines this method.
//      *
//      * @return The type of the class that defines this method
//      */
//     @Override @Nonnull String getDefiningClass();
// 
//     /**
//      * Gets the name of this method.
//      *
//      * @return The name of this method
//      */
//     @Override @Nonnull String getName();
// 
//     /**
//      * Gets a list of the parameters of this method.
//      *
//      * As per the MethodReference interface, the MethodParameter objects contained in the returned list also act
//      * as a simple reference to the type of the parameter. However, the MethodParameter object can also contain
//      * additional information about the parameter.
//      *
//      * Note: In some implementations, the returned list is likely to *not* provide efficient random access.
//      *
//      * @return A list of MethodParameter objects, representing the parameters of this method.
//      */
//     @Nonnull List<? extends MethodParameter> getParameters();
// 
//     /**
//      * Gets the return type of this method.
//      *
//      * @return The return type of this method.
//      */
//     @Override @Nonnull String getReturnType();
// 
//     /**
//      * Gets the access flags for this method.
//      *
//      * This will be a combination of the AccessFlags.* flags that are marked as compatible for use with a method.
//      *
//      * @return The access flags for this method
//      */
//     @Override int getAccessFlags();
// 
//     /**
//      * Gets a set of the annotations that are applied to this method.
//      *
//      * The annotations in the returned set are guaranteed to have unique types.
//      *
//      * @return A set of the annotations that are applied to this method
//      */
//     @Override @Nonnull Set<? extends Annotation> getAnnotations();
// 
//     /**
//      * Gets a MethodImplementation object that defines the implementation of the method.
//      *
//      * If this is an abstract method in an abstract class, or an interface method in an interface definition, then the
//      * method has no implementation, and this will return null.
//      *
//      * @return A MethodImplementation object defining the implementation of this method, or null if the method has no
//      * implementation
//      */
//     @Nullable MethodImplementation getImplementation();
// }


import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.jf.dexlib2.base.reference.BaseMethodReference;
import org.jf.dexlib2.dexbacked.raw.MethodIdItem;
import org.jf.dexlib2.dexbacked.raw.ProtoIdItem;
import org.jf.dexlib2.dexbacked.raw.TypeListItem;
import org.jf.dexlib2.dexbacked.util.AnnotationsDirectory;
import org.jf.dexlib2.dexbacked.util.FixedSizeList;
import org.jf.dexlib2.dexbacked.util.ParameterIterator;
import org.jf.dexlib2.iface.Annotation;
import org.jf.dexlib2.iface.Method;
import org.jf.dexlib2.iface.MethodParameter;
import org.jf.util.AbstractForwardSequentialList;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

                @Override public int size() {
                    return parameterTypes.size();
                }
            };
        }
        return ImmutableList.of();
    }

    @Nonnull
    public List<? extends Set<? extends DexBackedAnnotation>> getParameterAnnotations() {
        return AnnotationsDirectory.getParameterAnnotations(dexFile, parameterAnnotationSetListOffset);
    }

    @Nonnull
    public Iterator<String> getParameterNames() {
        DexBackedMethodImplementation methodImpl = getImplementation();
        if (methodImpl != null) {
            return methodImpl.getParameterNames(null);
        }
        return ImmutableSet.<String>of().iterator();
    }

    @Nonnull
    @Override
    public List<String> getParameterTypes() {
        final int parametersOffset = getParametersOffset();
        if (parametersOffset > 0) {
            final int parameterCount = dexFile.readSmallUint(parametersOffset + TypeListItem.SIZE_OFFSET);
            final int paramListStart = parametersOffset + TypeListItem.LIST_OFFSET;
// Path: src/org/jf/dexlib2/iface/Annotation.java
// public interface Annotation extends BasicAnnotation, Comparable<Annotation> {
//     /**
//      * Gets the visibility of this annotation.
//      *
//      * This will be one of the AnnotationVisibility.* constants.
//      *
//      * @return The visibility of this annotation
//      */
//     int getVisibility();
// 
//     /**
//      * Gets the type of this annotation.
//      *
//      * This will be the type descriptor of the class that defines this annotation.
//      *
//      * @return The type of this annotation
//      */
//     @Nonnull @Override String getType();
// 
//     /**
//      * Gets a set of the name/value elements associated with this annotation.
//      *
//      * The elements in the returned set will be unique with respect to the element name.
//      *
//      * @return A set of AnnotationElements
//      */
//     @Nonnull @Override Set<? extends AnnotationElement> getElements();
// 
//     /**
//      * Returns a hashcode for this Annotation.
//      *
//      * This hashCode is defined to be the following:
//      *
//      * <pre>
//      * {@code
//      * int hashCode = getVisibility();
//      * hashCode = hashCode*31 + getType().hashCode();
//      * hashCode = hashCode*31 + getElements().hashCode();
//      * }</pre>
//      *
//      * @return The hash code value for this Annotation
//      */
//     @Override int hashCode();
// 
//     /**
//      * Compares this Annotation to another Annotation for equality.
//      *
//      * This Annotation is equal to another Annotation if all of it's "fields" are equal. That is, if the return values
//      * of getVisibility(), getType(), and getElements() are all equal.
//      *
//      * @param o The object to be compared for equality with this Annotation
//      * @return true if the specified object is equal to this Annotation
//      */
//     @Override boolean equals(@Nullable Object o);
// 
//     /**
//      * Compares this Annotation to another Annotation.
//      *
//      * The comparison is based on the value of getVisibility(), getType() and getElements(), in that order. When
//      * comparing the set of elements, the comparison is done with the semantics of
//      * org.jf.util.CollectionUtils.compareAsSet(), using the natural ordering of AnnotationElement.
//      *
//      * @param o The Annotation to compare with this Annotation
//      * @return An integer representing the result of the comparison
//      */
//     @Override int compareTo(Annotation o);
// }
// 
// Path: src/org/jf/dexlib2/iface/Method.java
// public interface Method extends MethodReference, Member {
//     /**
//      * Gets the type of the class that defines this method.
//      *
//      * @return The type of the class that defines this method
//      */
//     @Override @Nonnull String getDefiningClass();
// 
//     /**
//      * Gets the name of this method.
//      *
//      * @return The name of this method
//      */
//     @Override @Nonnull String getName();
// 
//     /**
//      * Gets a list of the parameters of this method.
//      *
//      * As per the MethodReference interface, the MethodParameter objects contained in the returned list also act
//      * as a simple reference to the type of the parameter. However, the MethodParameter object can also contain
//      * additional information about the parameter.
//      *
//      * Note: In some implementations, the returned list is likely to *not* provide efficient random access.
//      *
//      * @return A list of MethodParameter objects, representing the parameters of this method.
//      */
//     @Nonnull List<? extends MethodParameter> getParameters();
// 
//     /**
//      * Gets the return type of this method.
//      *
//      * @return The return type of this method.
//      */
//     @Override @Nonnull String getReturnType();
// 
//     /**
//      * Gets the access flags for this method.
//      *
//      * This will be a combination of the AccessFlags.* flags that are marked as compatible for use with a method.
//      *
//      * @return The access flags for this method
//      */
//     @Override int getAccessFlags();
// 
//     /**
//      * Gets a set of the annotations that are applied to this method.
//      *
//      * The annotations in the returned set are guaranteed to have unique types.
//      *
//      * @return A set of the annotations that are applied to this method
//      */
//     @Override @Nonnull Set<? extends Annotation> getAnnotations();
// 
//     /**
//      * Gets a MethodImplementation object that defines the implementation of the method.
//      *
//      * If this is an abstract method in an abstract class, or an interface method in an interface definition, then the
//      * method has no implementation, and this will return null.
//      *
//      * @return A MethodImplementation object defining the implementation of this method, or null if the method has no
//      * implementation
//      */
//     @Nullable MethodImplementation getImplementation();
// }


// Path: src/org/jf/dexlib2/dexbacked/DexBackedMethod.java
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.jf.dexlib2.base.reference.BaseMethodReference;
import org.jf.dexlib2.dexbacked.raw.MethodIdItem;
import org.jf.dexlib2.dexbacked.raw.ProtoIdItem;
import org.jf.dexlib2.dexbacked.raw.TypeListItem;
import org.jf.dexlib2.dexbacked.util.AnnotationsDirectory;
import org.jf.dexlib2.dexbacked.util.FixedSizeList;
import org.jf.dexlib2.dexbacked.util.ParameterIterator;
import org.jf.dexlib2.iface.Annotation;
import org.jf.dexlib2.iface.Method;
import org.jf.dexlib2.iface.MethodParameter;
import org.jf.util.AbstractForwardSequentialList;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;


                @Override public int size() {
                    return parameterTypes.size();
                }
            };
        }
        return ImmutableList.of();
    }

    @Nonnull
    public List<? extends Set<? extends DexBackedAnnotation>> getParameterAnnotations() {
        return AnnotationsDirectory.getParameterAnnotations(dexFile, parameterAnnotationSetListOffset);
    }

    @Nonnull
    public Iterator<String> getParameterNames() {
        DexBackedMethodImplementation methodImpl = getImplementation();
        if (methodImpl != null) {
            return methodImpl.getParameterNames(null);
        }
        return ImmutableSet.<String>of().iterator();
    }

    @Nonnull
    @Override
    public List<String> getParameterTypes() {
        final int parametersOffset = getParametersOffset();
        if (parametersOffset > 0) {
            final int parameterCount = dexFile.readSmallUint(parametersOffset + TypeListItem.SIZE_OFFSET);
            final int paramListStart = parametersOffset + TypeListItem.LIST_OFFSET;
            return new FixedSizeList<String>() {