blob: 49d4b1beb57ccb2a3d5cf7be70543b0de89d1abf [file] [log] [blame]
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.jack.dx.dex.file;
import static com.android.jack.dx.rop.annotation.AnnotationVisibility.SYSTEM;
import com.android.jack.dx.rop.annotation.Annotation;
import com.android.jack.dx.rop.annotation.NameValuePair;
import com.android.jack.dx.rop.cst.Constant;
import com.android.jack.dx.rop.cst.CstAnnotation;
import com.android.jack.dx.rop.cst.CstArray;
import com.android.jack.dx.rop.cst.CstInteger;
import com.android.jack.dx.rop.cst.CstKnownNull;
import com.android.jack.dx.rop.cst.CstMethodRef;
import com.android.jack.dx.rop.cst.CstString;
import com.android.jack.dx.rop.type.Type;
import com.android.jack.dx.rop.type.TypeList;
/**
* Utility class for dealing with annotations.
*/
public final class AnnotationUtils {
/** {@code non-null;} type for {@code AnnotationDefault} annotations */
private static final Type ANNOTATION_DEFAULT_TYPE =
Type.intern("Ldalvik/annotation/AnnotationDefault;");
/** {@code non-null;} type for {@code EnclosingClass} annotations */
private static final Type ENCLOSING_CLASS_TYPE =
Type.intern("Ldalvik/annotation/EnclosingClass;");
/** {@code non-null;} type for {@code EnclosingMethod} annotations */
private static final Type ENCLOSING_METHOD_TYPE =
Type.intern("Ldalvik/annotation/EnclosingMethod;");
/** {@code non-null;} type for {@code InnerClass} annotations */
private static final Type INNER_CLASS_TYPE = Type.intern("Ldalvik/annotation/InnerClass;");
/** {@code non-null;} type for {@code MemberClasses} annotations */
private static final Type MEMBER_CLASSES_TYPE = Type.intern("Ldalvik/annotation/MemberClasses;");
/** {@code non-null;} type for {@code Throws} annotations */
private static final Type THROWS_TYPE = Type.intern("Ldalvik/annotation/Throws;");
/** {@code non-null;} the UTF-8 constant {@code "accessFlags"} */
private static final CstString ACCESS_FLAGS_STRING = new CstString("accessFlags");
/** {@code non-null;} the UTF-8 constant {@code "name"} */
private static final CstString NAME_STRING = new CstString("name");
/** {@code non-null;} the UTF-8 constant {@code "value"} */
private static final CstString VALUE_STRING = new CstString("value");
/**
* This class is uninstantiable.
*/
private AnnotationUtils() {
// This space intentionally left blank.
}
/**
* Constructs a standard {@code AnnotationDefault} annotation.
*
* @param defaults {@code non-null;} the defaults, itself as an annotation
* @return {@code non-null;} the constructed annotation
*/
public static Annotation makeAnnotationDefault(Annotation defaults) {
Annotation result = new Annotation(ANNOTATION_DEFAULT_TYPE, SYSTEM);
result.put(new NameValuePair(VALUE_STRING, new CstAnnotation(defaults)));
result.setImmutable();
return result;
}
/**
* Constructs a standard {@code EnclosingClass} annotation.
*
* @param clazz {@code non-null;} the enclosing class
* @return {@code non-null;} the annotation
*/
public static Annotation makeEnclosingClass(Type clazz) {
Annotation result = new Annotation(ENCLOSING_CLASS_TYPE, SYSTEM);
result.put(new NameValuePair(VALUE_STRING, clazz));
result.setImmutable();
return result;
}
/**
* Constructs a standard {@code EnclosingMethod} annotation.
*
* @param method {@code non-null;} the enclosing method
* @return {@code non-null;} the annotation
*/
public static Annotation makeEnclosingMethod(CstMethodRef method) {
Annotation result = new Annotation(ENCLOSING_METHOD_TYPE, SYSTEM);
result.put(new NameValuePair(VALUE_STRING, method));
result.setImmutable();
return result;
}
/**
* Constructs a standard {@code InnerClass} annotation.
*
* @param name {@code null-ok;} the original name of the class, or
* {@code null} to represent an anonymous class
* @param accessFlags the original access flags
* @return {@code non-null;} the annotation
*/
public static Annotation makeInnerClass(CstString name, int accessFlags) {
Annotation result = new Annotation(INNER_CLASS_TYPE, SYSTEM);
Constant nameCst = (name != null) ? name : CstKnownNull.THE_ONE;
result.put(new NameValuePair(NAME_STRING, nameCst));
result.put(new NameValuePair(ACCESS_FLAGS_STRING, CstInteger.make(accessFlags)));
result.setImmutable();
return result;
}
/**
* Constructs a standard {@code MemberClasses} annotation.
*
* @param types {@code non-null;} the list of (the types of) the member classes
* @return {@code non-null;} the annotation
*/
public static Annotation makeMemberClasses(TypeList types) {
CstArray array = makeCstArray(types);
Annotation result = new Annotation(MEMBER_CLASSES_TYPE, SYSTEM);
result.put(new NameValuePair(VALUE_STRING, array));
result.setImmutable();
return result;
}
/**
* Constructs a standard {@code Throws} annotation.
*
* @param types {@code non-null;} the list of thrown types
* @return {@code non-null;} the annotation
*/
public static Annotation makeThrows(TypeList types) {
CstArray array = makeCstArray(types);
Annotation result = new Annotation(THROWS_TYPE, SYSTEM);
result.put(new NameValuePair(VALUE_STRING, array));
result.setImmutable();
return result;
}
/**
* Converts a {@link TypeList} to a {@link CstArray}.
*
* @param types {@code non-null;} the type list
* @return {@code non-null;} the corresponding array constant
*/
private static CstArray makeCstArray(TypeList types) {
int size = types.size();
CstArray.List list = new CstArray.List(size);
for (int i = 0; i < size; i++) {
list.set(i, types.getType(i));
}
list.setImmutable();
return new CstArray(list);
}
}