FileDocCategorySizeDatePackage
AttributeTranslator.javaAPI DocAndroid 1.5 API15709Wed May 06 22:41:02 BST 2009com.android.dx.dex.cf

AttributeTranslator

public class AttributeTranslator extends Object
Utility methods that translate various classfile attributes into forms suitable for use in creating dex files.

Fields Summary
Constructors Summary
private AttributeTranslator()
This class is uninstantiable.

        // This space intentionally left blank.
    
Methods Summary
public static com.android.dx.rop.annotation.AnnotationsgetAnnotations(com.android.dx.cf.iface.AttributeList attribs)
Gets the annotations out of a given {@link AttributeList}. This combines both visible and invisible annotations into a single result set and also adds in a system annotation for the Signature attribute if present.

param
attribs non-null; the attributes list to search in
return
non-null; the set of annotations, which may be empty

        Annotations result = getAnnotations0(attribs);
        Annotation signature = getSignature(attribs);

        if (signature != null) {
            result = Annotations.combine(result, signature);
        }

        return result;
    
private static com.android.dx.rop.annotation.AnnotationsgetAnnotations0(com.android.dx.cf.iface.AttributeList attribs)
Helper method for {@link #getAnnotations} which just gets the existing annotations, per se.

param
attribs non-null; the attributes list to search in
return
non-null; the set of annotations, which may be empty

        AttRuntimeVisibleAnnotations visible =
            (AttRuntimeVisibleAnnotations)
            attribs.findFirst(AttRuntimeVisibleAnnotations.ATTRIBUTE_NAME);
        AttRuntimeInvisibleAnnotations invisible =
            (AttRuntimeInvisibleAnnotations)
            attribs.findFirst(AttRuntimeInvisibleAnnotations.ATTRIBUTE_NAME);

        if (visible == null) {
            if (invisible == null) {
                return Annotations.EMPTY;
            }
            return invisible.getAnnotations();
        }

        if (invisible == null) {
            return visible.getAnnotations();
        }

        // Both are non-null, so combine them.

        return Annotations.combine(visible.getAnnotations(),
                invisible.getAnnotations());
    
public static com.android.dx.rop.annotation.AnnotationsgetClassAnnotations(com.android.dx.cf.direct.DirectClassFile cf, CfOptions args)
Gets the annotations out of a given class, similar to {@link #getAnnotations}, also including annotations for translations of class-level attributes EnclosingMethod and InnerClasses, if present. Additionally, if the class is an annotation class, then this also includes a representation of all the AnnotationDefault values.

param
cf non-null; the class in question
param
args non-null; the high-level options
return
non-null; the set of annotations, which may be empty

        CstType thisClass = cf.getThisClass();
        AttributeList attribs = cf.getAttributes();
        Annotations result = getAnnotations(attribs);
        Annotation enclosingMethod = translateEnclosingMethod(attribs);

        try {
            Annotations innerClassAnnotations =
                translateInnerClasses(thisClass, attribs,
                        enclosingMethod == null);
            if (innerClassAnnotations != null) {
                result = Annotations.combine(result, innerClassAnnotations);
            }
        } catch (Warning warn) {
            args.warn.println("warning: " + warn.getMessage());
        }

        if (enclosingMethod != null) {
            result = Annotations.combine(result, enclosingMethod);
        }

        if (AccessFlags.isAnnotation(cf.getAccessFlags())) {
            Annotation annotationDefault =
                translateAnnotationDefaults(cf);
            if (annotationDefault != null) {
                result = Annotations.combine(result, annotationDefault);
            }
        }

        return result;
    
public static com.android.dx.rop.type.TypeListgetExceptions(com.android.dx.cf.iface.Method method)
Gets the list of thrown exceptions for a given method.

param
method non-null; the method in question
return
non-null; the list of thrown exceptions

        AttributeList attribs = method.getAttributes();
        AttExceptions exceptions = (AttExceptions)
            attribs.findFirst(AttExceptions.ATTRIBUTE_NAME);

        if (exceptions == null) {
            return StdTypeList.EMPTY;
        }

        return exceptions.getExceptions();
    
public static com.android.dx.rop.annotation.AnnotationsgetMethodAnnotations(com.android.dx.cf.iface.Method method)
Gets the annotations out of a given method, similar to {@link #getAnnotations}, also including an annotation for the translation of the method-specific attribute Exceptions.

param
method non-null; the method in question
return
non-null; the set of annotations, which may be empty

        Annotations result = getAnnotations(method.getAttributes());
        TypeList exceptions = getExceptions(method);

        if (exceptions.size() != 0) {
            Annotation throwsAnnotation = 
                AnnotationUtils.makeThrows(exceptions);
            result = Annotations.combine(result, throwsAnnotation);
        }

        return result;
    
public static com.android.dx.rop.annotation.AnnotationsListgetParameterAnnotations(com.android.dx.cf.iface.Method method)
Gets the parameter annotations out of a given method. This combines both visible and invisible annotations into a single result set.

param
method non-null; the method in question
return
non-null; the list of annotation sets, which may be empty

        AttributeList attribs = method.getAttributes();
        AttRuntimeVisibleParameterAnnotations visible =
            (AttRuntimeVisibleParameterAnnotations)
            attribs.findFirst(
                    AttRuntimeVisibleParameterAnnotations.ATTRIBUTE_NAME);
        AttRuntimeInvisibleParameterAnnotations invisible =
            (AttRuntimeInvisibleParameterAnnotations)
            attribs.findFirst(
                    AttRuntimeInvisibleParameterAnnotations.ATTRIBUTE_NAME);

        if (visible == null) {
            if (invisible == null) {
                return AnnotationsList.EMPTY;
            }
            return invisible.getParameterAnnotations();
        }

        if (invisible == null) {
            return visible.getParameterAnnotations();
        }

        // Both are non-null, so combine them.

        return AnnotationsList.combine(visible.getParameterAnnotations(),
                invisible.getParameterAnnotations());
    
private static com.android.dx.rop.annotation.AnnotationgetSignature(com.android.dx.cf.iface.AttributeList attribs)
Gets the Signature attribute out of a given {@link AttributeList}, if any, translating it to an annotation.

param
attribs non-null; the attributes list to search in
return
null-ok; the converted Signature annotation, if there was an attribute to translate

        AttSignature signature = (AttSignature)
            attribs.findFirst(AttSignature.ATTRIBUTE_NAME);

        if (signature == null) {
            return null;
        }

        return AnnotationUtils.makeSignature(signature.getSignature());
    
private static com.android.dx.rop.annotation.AnnotationtranslateAnnotationDefaults(com.android.dx.cf.direct.DirectClassFile cf)
Gets the AnnotationDefault attributes out of a given class, if any, reforming them as an AnnotationDefault annotation.

param
cf non-null; the class in question
return
null-ok; an appropriately-constructed AnnotationDefault annotation, if there were any annotation defaults in the class, or null if not

        CstType thisClass = cf.getThisClass();
        MethodList methods = cf.getMethods();
        int sz = methods.size();
        Annotation result =
            new Annotation(thisClass, AnnotationVisibility.EMBEDDED);
        boolean any = false;

        for (int i = 0; i < sz; i++) {
            Method one = methods.get(i);
            AttributeList attribs = one.getAttributes();
            AttAnnotationDefault oneDefault = (AttAnnotationDefault)
                attribs.findFirst(AttAnnotationDefault.ATTRIBUTE_NAME);

            if (oneDefault != null) {
                NameValuePair pair = new NameValuePair(
                        one.getNat().getName(),
                        oneDefault.getValue());
                result.add(pair);
                any = true;
            }
        }

        if (! any) {
            return null;
        }

        result.setImmutable();
        return AnnotationUtils.makeAnnotationDefault(result);
    
private static com.android.dx.rop.annotation.AnnotationtranslateEnclosingMethod(com.android.dx.cf.iface.AttributeList attribs)
Gets the EnclosingMethod attribute out of a given {@link AttributeList}, if any, translating it to an annotation. If the class really has an enclosing method, this returns an EnclosingMethod annotation; if not, this returns an EnclosingClass annotation.

param
attribs non-null; the attributes list to search in
return
null-ok; the converted EnclosingMethod or EnclosingClass annotation, if there was an attribute to translate

        AttEnclosingMethod enclosingMethod = (AttEnclosingMethod)
            attribs.findFirst(AttEnclosingMethod.ATTRIBUTE_NAME);

        if (enclosingMethod == null) {
            return null;
        }

        CstType enclosingClass = enclosingMethod.getEnclosingClass();
        CstNat nat = enclosingMethod.getMethod();

        if (nat == null) {
            /*
             * Dalvik doesn't use EnclosingMethod annotations unless
             * there really is an enclosing method. Anonymous classes
             * are unambiguously identified by having an InnerClass
             * annotation with an empty name along with an appropriate
             * EnclosingClass.
             */
            return AnnotationUtils.makeEnclosingClass(enclosingClass);
        }

        return AnnotationUtils.makeEnclosingMethod(
                new CstMethodRef(enclosingClass, nat));
    
private static com.android.dx.rop.annotation.AnnotationstranslateInnerClasses(com.android.dx.rop.cst.CstType thisClass, com.android.dx.cf.iface.AttributeList attribs, boolean needEnclosingClass)
Gets the InnerClasses attribute out of a given {@link AttributeList}, if any, translating it to one or more of an InnerClass, EnclosingClass, or MemberClasses annotation.

param
thisClass non-null; type representing the class being processed
param
attribs non-null; the attributes list to search in
param
needEnclosingClass whether to include an EnclosingClass annotation
return
null-ok; the converted list of annotations, if there was an attribute to translate

        AttInnerClasses innerClasses = (AttInnerClasses)
            attribs.findFirst(AttInnerClasses.ATTRIBUTE_NAME);

        if (innerClasses == null) {
            return null;
        }

        /*
         * Search the list for the element representing the current class
         * as well as for any named member classes.
         */

        InnerClassList list = innerClasses.getInnerClasses();
        int size = list.size();
        InnerClassList.Item foundThisClass = null;
        ArrayList<Type> membersList = new ArrayList<Type>();

        for (int i = 0; i < size; i++) {
            InnerClassList.Item item = list.get(i);
            CstType innerClass = item.getInnerClass();
            if (innerClass.equals(thisClass)) {
                foundThisClass = item;
            } else if (thisClass.equals(item.getOuterClass())) {
                membersList.add(innerClass.getClassType());
            }
        }

        int membersSize = membersList.size();
        
        if ((foundThisClass == null) && (membersSize == 0)) {
            return null;
        }

        Annotations result = new Annotations();

        if (foundThisClass != null) {
            result.add(AnnotationUtils.makeInnerClass(
                               foundThisClass.getInnerName(),
                               foundThisClass.getAccessFlags()));
            if (needEnclosingClass) {
                CstType outer = foundThisClass.getOuterClass();
                if (outer == null) {
                    throw new Warning(
                            "Ignoring InnerClasses attribute for an " +
                            "anonymous inner class that doesn't come with " +
                            "an associated EnclosingMethod attribute. " +
                            "(This class was probably produced by a broken " +
                            "compiler.)");
                }
                result.add(AnnotationUtils.makeEnclosingClass(
                                   foundThisClass.getOuterClass()));
            }
        }

        if (membersSize != 0) {
            StdTypeList typeList = new StdTypeList(membersSize);
            for (int i = 0; i < membersSize; i++) {
                typeList.set(i, membersList.get(i));
            }
            typeList.setImmutable();
            result.add(AnnotationUtils.makeMemberClasses(typeList));
        }

        result.setImmutable();
        return result;