use of com.android.dx.rop.annotation.Annotations in project buck by facebook.
the class AttributeTranslator method getAnnotations.
/**
* 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
* {@code Signature} attribute if present.
*
* @param attribs {@code non-null;} the attributes list to search in
* @return {@code non-null;} the set of annotations, which may be empty
*/
public static Annotations getAnnotations(AttributeList attribs) {
Annotations result = getAnnotations0(attribs);
Annotation signature = getSignature(attribs);
if (signature != null) {
result = Annotations.combine(result, signature);
}
return result;
}
use of com.android.dx.rop.annotation.Annotations in project buck by facebook.
the class AttributeTranslator method getClassAnnotations.
/**
* Gets the annotations out of a given class, similar to {@link
* #getAnnotations}, also including annotations for translations
* of class-level attributes {@code EnclosingMethod} and
* {@code InnerClasses}, if present. Additionally, if the
* class is an annotation class, then this also includes a
* representation of all the {@code AnnotationDefault}
* values.
*
* @param cf {@code non-null;} the class in question
* @param args {@code non-null;} the high-level options
* @return {@code non-null;} the set of annotations, which may be empty
*/
public static Annotations getClassAnnotations(DirectClassFile cf, CfOptions args) {
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;
}
use of com.android.dx.rop.annotation.Annotations in project buck by facebook.
the class AttributeTranslator method translateInnerClasses.
/**
* Gets the {@code InnerClasses} attribute out of a given
* {@link AttributeList}, if any, translating it to one or more of an
* {@code InnerClass}, {@code EnclosingClass}, or
* {@code MemberClasses} annotation.
*
* @param thisClass {@code non-null;} type representing the class being
* processed
* @param attribs {@code non-null;} the attributes list to search in
* @param needEnclosingClass whether to include an
* {@code EnclosingClass} annotation
* @return {@code null-ok;} the converted list of annotations, if there
* was an attribute to translate
*/
private static Annotations translateInnerClasses(CstType thisClass, AttributeList attribs, boolean needEnclosingClass) {
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\n" + "(" + thisClass.toHuman() + ") that doesn't come with an\n" + "associated EnclosingMethod attribute. " + "This class was probably produced by a\n" + "compiler that did not target the modern " + ".class file format. The recommended\n" + "solution is to recompile the class from " + "source, using an up-to-date compiler\n" + "and without specifying any \"-target\" type " + "options. The consequence of ignoring\n" + "this warning is that reflective operations " + "on this class will incorrectly\n" + "indicate that it is *not* an inner class.");
}
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;
}
use of com.android.dx.rop.annotation.Annotations in project buck by facebook.
the class AttributeTranslator method getMethodAnnotations.
/**
* Gets the annotations out of a given method, similar to {@link
* #getAnnotations}, also including an annotation for the translation
* of the method-specific attribute {@code Exceptions}.
*
* @param method {@code non-null;} the method in question
* @return {@code non-null;} the set of annotations, which may be empty
*/
public static Annotations getMethodAnnotations(Method method) {
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;
}
use of com.android.dx.rop.annotation.Annotations in project buck by facebook.
the class CfTranslator method processMethods.
/**
* Processes the methods of the given class.
*
* @param context
* @param cf {@code non-null;} class being translated
* @param cfOptions {@code non-null;} options for class translation
* @param dexOptions {@code non-null;} options for dex output
* @param out {@code non-null;} output class
* @param dexFile {@code non-null;} dex output
*/
private static void processMethods(DxContext context, DirectClassFile cf, CfOptions cfOptions, DexOptions dexOptions, ClassDefItem out, DexFile dexFile) {
CstType thisClass = cf.getThisClass();
MethodList methods = cf.getMethods();
int sz = methods.size();
for (int i = 0; i < sz; i++) {
Method one = methods.get(i);
try {
CstMethodRef meth = new CstMethodRef(thisClass, one.getNat());
int accessFlags = one.getAccessFlags();
boolean isStatic = AccessFlags.isStatic(accessFlags);
boolean isPrivate = AccessFlags.isPrivate(accessFlags);
boolean isNative = AccessFlags.isNative(accessFlags);
boolean isAbstract = AccessFlags.isAbstract(accessFlags);
boolean isConstructor = meth.isInstanceInit() || meth.isClassInit();
DalvCode code;
if (isNative || isAbstract) {
// There's no code for native or abstract methods.
code = null;
} else {
ConcreteMethod concrete = new ConcreteMethod(one, cf, (cfOptions.positionInfo != PositionList.NONE), cfOptions.localInfo);
TranslationAdvice advice;
advice = DexTranslationAdvice.THE_ONE;
RopMethod rmeth = Ropper.convert(concrete, advice, methods);
RopMethod nonOptRmeth = null;
int paramSize;
paramSize = meth.getParameterWordCount(isStatic);
String canonicalName = thisClass.getClassType().getDescriptor() + "." + one.getName().getString();
if (cfOptions.optimize && context.optimizerOptions.shouldOptimize(canonicalName)) {
if (DEBUG) {
System.err.println("Optimizing " + canonicalName);
}
nonOptRmeth = rmeth;
rmeth = Optimizer.optimize(rmeth, paramSize, isStatic, cfOptions.localInfo, advice);
if (DEBUG) {
context.optimizerOptions.compareOptimizerStep(nonOptRmeth, paramSize, isStatic, cfOptions, advice, rmeth);
}
if (cfOptions.statistics) {
context.codeStatistics.updateRopStatistics(nonOptRmeth, rmeth);
}
}
LocalVariableInfo locals = null;
if (cfOptions.localInfo) {
locals = LocalVariableExtractor.extract(rmeth);
}
code = RopTranslator.translate(rmeth, cfOptions.positionInfo, locals, paramSize, dexOptions);
if (cfOptions.statistics && nonOptRmeth != null) {
updateDexStatistics(context, cfOptions, dexOptions, rmeth, nonOptRmeth, locals, paramSize, concrete.getCode().size());
}
}
// Preserve the synchronized flag as its "declared" variant...
if (AccessFlags.isSynchronized(accessFlags)) {
accessFlags |= AccessFlags.ACC_DECLARED_SYNCHRONIZED;
/*
* ...but only native methods are actually allowed to be
* synchronized.
*/
if (!isNative) {
accessFlags &= ~AccessFlags.ACC_SYNCHRONIZED;
}
}
if (isConstructor) {
accessFlags |= AccessFlags.ACC_CONSTRUCTOR;
}
TypeList exceptions = AttributeTranslator.getExceptions(one);
EncodedMethod mi = new EncodedMethod(meth, accessFlags, code, exceptions);
if (meth.isInstanceInit() || meth.isClassInit() || isStatic || isPrivate) {
out.addDirectMethod(mi);
} else {
out.addVirtualMethod(mi);
}
Annotations annotations = AttributeTranslator.getMethodAnnotations(one);
if (annotations.size() != 0) {
out.addMethodAnnotations(meth, annotations, dexFile);
}
AnnotationsList list = AttributeTranslator.getParameterAnnotations(one);
if (list.size() != 0) {
out.addParameterAnnotations(meth, list, dexFile);
}
dexFile.getMethodIds().intern(meth);
} catch (RuntimeException ex) {
String msg = "...while processing " + one.getName().toHuman() + " " + one.getDescriptor().toHuman();
throw ExceptionWithContext.withContext(ex, msg);
}
}
}
Aggregations