org.robovm.compiler.Annotations Maven / Gradle / Ivy
/*
* Copyright (C) 2012 RoboVM AB
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package org.robovm.compiler;
import static soot.tagkit.AnnotationConstants.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import soot.SootClass;
import soot.SootMethod;
import soot.SootResolver;
import soot.tagkit.AnnotationAnnotationElem;
import soot.tagkit.AnnotationArrayElem;
import soot.tagkit.AnnotationElem;
import soot.tagkit.AnnotationIntElem;
import soot.tagkit.AnnotationStringElem;
import soot.tagkit.AnnotationTag;
import soot.tagkit.Host;
import soot.tagkit.Tag;
import soot.tagkit.VisibilityAnnotationTag;
import soot.tagkit.VisibilityParameterAnnotationTag;
/**
* @author niklas
*
*/
public class Annotations {
public enum Visibility { RuntimeVisible, RuntimeInvisible, SourceVisible, Any }
public static final String BRIDGE = "Lorg/robovm/rt/bro/annotation/Bridge;";
public static final String CALLBACK = "Lorg/robovm/rt/bro/annotation/Callback;";
public static final String STRUCT_MEMBER = "Lorg/robovm/rt/bro/annotation/StructMember;";
public static final String VECTORISED = "Lorg/robovm/rt/bro/annotation/Vectorised;";
public static final String STRUCT_PACKED = "Lorg/robovm/rt/bro/annotation/Packed;";
public static final String GLOBAL_VALUE = "Lorg/robovm/rt/bro/annotation/GlobalValue;";
public static final String ARRAY = "Lorg/robovm/rt/bro/annotation/Array;";
public static final String BASE_TYPE = "Lorg/robovm/rt/bro/annotation/BaseType;";
public static final String STRUCT_RET = "Lorg/robovm/rt/bro/annotation/StructRet;";
public static final String POINTER = "Lorg/robovm/rt/bro/annotation/Pointer;";
public static final String MACHINE_SIZED_FLOAT = "Lorg/robovm/rt/bro/annotation/MachineSizedFloat;";
public static final String MACHINE_SIZED_S_INT = "Lorg/robovm/rt/bro/annotation/MachineSizedSInt;";
public static final String MACHINE_SIZED_U_INT = "Lorg/robovm/rt/bro/annotation/MachineSizedUInt;";
public static final String MARSHALER = "Lorg/robovm/rt/bro/annotation/Marshaler;";
public static final String MARSHALERS = "Lorg/robovm/rt/bro/annotation/Marshalers;";
public static final String MARSHALS_POINTER = "Lorg/robovm/rt/bro/annotation/MarshalsPointer;";
public static final String MARSHALS_VALUE = "Lorg/robovm/rt/bro/annotation/MarshalsValue;";
public static final String MARSHALS_ARRAY = "Lorg/robovm/rt/bro/annotation/MarshalsArray;";
public static final String AFTER_BRIDGE_CALL = "Lorg/robovm/rt/bro/annotation/AfterBridgeCall;";
public static final String AFTER_CALLBACK_CALL = "Lorg/robovm/rt/bro/annotation/AfterCallbackCall;";
public static final String BY_VAL = "Lorg/robovm/rt/bro/annotation/ByVal;";
public static final String BY_REF = "Lorg/robovm/rt/bro/annotation/ByRef;";
public static final String VARIADIC = "Lorg/robovm/rt/bro/annotation/Variadic;";
public static final String WEAKLY_LINKED = "Lorg/robovm/rt/annotation/WeaklyLinked;";
public static final String STRONGLY_LINKED = "Lorg/robovm/rt/annotation/StronglyLinked;";
public static boolean hasAnnotation(Host host, String annotationType) {
return getAnnotation(host, annotationType) != null;
}
public static boolean hasParameterAnnotation(SootMethod method, int paramIndex, String annotationType) {
return getParameterAnnotation(method, paramIndex, annotationType) != null;
}
public static List getAnnotations(Host host, Visibility visibility) {
if (host instanceof SootClass) {
SootResolver.v().bringToHierarchy((SootClass) host);
}
List result = new ArrayList<>();
for (Tag tag : host.getTags()) {
if (tag instanceof VisibilityAnnotationTag) {
if (visibility == Visibility.Any
|| ((VisibilityAnnotationTag) tag).getVisibility() == visibility.ordinal()) {
result.addAll(((VisibilityAnnotationTag) tag).getAnnotations());
}
}
}
return result;
}
public static AnnotationTag getAnnotation(Host host, String annotationType) {
for (AnnotationTag tag : getAnnotations(host, Visibility.Any)) {
if (annotationType.equals(tag.getType())) {
return tag;
}
}
return null;
}
public static List getParameterAnnotations(SootMethod method, int paramIndex, Visibility visibility) {
List result = new ArrayList<>();
for (Tag tag : method.getTags()) {
if (tag instanceof VisibilityParameterAnnotationTag) {
if (visibility == Visibility.Any
|| ((VisibilityParameterAnnotationTag) tag).getKind() == visibility.ordinal()) {
ArrayList l =
((VisibilityParameterAnnotationTag) tag).getVisibilityAnnotations();
if (l != null && paramIndex < l.size()) {
ArrayList annotations = l.get(paramIndex).getAnnotations();
if (annotations != null) {
result.addAll(annotations);
}
}
}
}
}
return result;
}
public static List[] getParameterAnnotations(SootMethod method, Visibility visibility) {
@SuppressWarnings("unchecked")
ArrayList[] result = new ArrayList[method.getParameterCount()];
for (int i = 0; i < result.length; i++) {
result[i] = new ArrayList<>();
}
for (Tag tag : method.getTags()) {
if (tag instanceof VisibilityParameterAnnotationTag) {
if (visibility == Visibility.Any
|| ((VisibilityParameterAnnotationTag) tag).getKind() == visibility.ordinal()) {
ArrayList l =
((VisibilityParameterAnnotationTag) tag).getVisibilityAnnotations();
if (l != null) {
int i = 0;
for (VisibilityAnnotationTag t : l) {
ArrayList annotations = t.getAnnotations();
if (annotations != null) {
result[i].addAll(annotations);
}
i++;
}
}
}
}
}
return result;
}
public static AnnotationTag getParameterAnnotation(SootMethod method, int paramIndex, String annotationType) {
for (AnnotationTag tag : getParameterAnnotations(method, paramIndex, Visibility.Any)) {
if (annotationType.equals(tag.getType())) {
return tag;
}
}
return null;
}
public static boolean hasBridgeAnnotation(SootMethod method) {
return hasAnnotation(method, BRIDGE);
}
public static boolean hasCallbackAnnotation(SootMethod method) {
return hasAnnotation(method, CALLBACK);
}
public static boolean hasStructMemberAnnotation(SootMethod method) {
return hasAnnotation(method, STRUCT_MEMBER);
}
public static boolean hasGlobalValueAnnotation(SootMethod method) {
return hasAnnotation(method, GLOBAL_VALUE);
}
public static boolean hasArrayAnnotation(SootMethod method) {
return hasAnnotation(method, ARRAY);
}
public static boolean hasArrayAnnotation(SootMethod method, int paramIndex) {
return hasParameterAnnotation(method, paramIndex, ARRAY);
}
public static boolean hasPointerAnnotation(SootMethod method) {
return hasAnnotation(method, POINTER);
}
public static boolean hasMachineSizedFloatAnnotation(SootMethod method) {
return hasAnnotation(method, MACHINE_SIZED_FLOAT);
}
public static boolean hasMachineSizedSIntAnnotation(SootMethod method) {
return hasAnnotation(method, MACHINE_SIZED_S_INT);
}
public static boolean hasMachineSizedUIntAnnotation(SootMethod method) {
return hasAnnotation(method, MACHINE_SIZED_U_INT);
}
public static boolean hasByValAnnotation(SootMethod method) {
return hasAnnotation(method, BY_VAL);
}
public static boolean hasByRefAnnotation(SootMethod method) {
return hasAnnotation(method, BY_REF);
}
public static boolean hasStructRetAnnotation(SootMethod method, int paramIndex) {
return hasParameterAnnotation(method, paramIndex, STRUCT_RET);
}
public static boolean hasPointerAnnotation(SootMethod method, int paramIndex) {
return hasParameterAnnotation(method, paramIndex, POINTER);
}
public static boolean hasMachineSizedFloatAnnotation(SootMethod method, int paramIndex) {
return hasParameterAnnotation(method, paramIndex, MACHINE_SIZED_FLOAT);
}
public static boolean hasMachineSizedSIntAnnotation(SootMethod method, int paramIndex) {
return hasParameterAnnotation(method, paramIndex, MACHINE_SIZED_S_INT);
}
public static boolean hasMachineSizedUIntAnnotation(SootMethod method, int paramIndex) {
return hasParameterAnnotation(method, paramIndex, MACHINE_SIZED_U_INT);
}
public static boolean hasByValAnnotation(SootMethod method, int paramIndex) {
return hasParameterAnnotation(method, paramIndex, BY_VAL);
}
public static boolean hasByRefAnnotation(SootMethod method, int paramIndex) {
return hasParameterAnnotation(method, paramIndex, BY_REF);
}
public static boolean hasVariadicAnnotation(SootMethod method) {
return hasAnnotation(method, VARIADIC);
}
public static boolean hasWeaklyLinkedAnnotation(Host host) {
return hasAnnotation(host, WEAKLY_LINKED);
}
public static boolean hasStronglyLinkedAnnotation(Host host) {
return hasAnnotation(host, STRONGLY_LINKED);
}
public static int getVariadicParameterIndex(SootMethod method) {
AnnotationTag annotation = getAnnotation(method, VARIADIC);
return readIntElem(annotation, "value", 0);
}
public static boolean hasAfterBridgeCallAnnotation(SootMethod method) {
return hasAnnotation(method, AFTER_BRIDGE_CALL);
}
public static boolean hasAfterCallbackCallAnnotation(SootMethod method) {
return hasAnnotation(method, AFTER_CALLBACK_CALL);
}
public static AnnotationTag getMarshalerAnnotation(SootMethod method, int paramIndex) {
return getParameterAnnotation(method, paramIndex, MARSHALER);
}
public static AnnotationTag getMarshalerAnnotation(SootMethod method) {
return getAnnotation(method, MARSHALER);
}
public static List getMarshalerAnnotations(SootClass clazz) {
List tags = new ArrayList();
AnnotationTag marshaler = getAnnotation(clazz, MARSHALER);
if (marshaler != null) {
tags.add(marshaler);
} else {
AnnotationTag marshalers = getAnnotation(clazz, MARSHALERS);
if (marshalers != null) {
for (AnnotationElem e : ((AnnotationArrayElem) marshalers.getElemAt(0)).getValues()) {
AnnotationAnnotationElem elem = (AnnotationAnnotationElem) e;
tags.add(elem.getValue());
}
}
}
return tags;
}
public static AnnotationTag getMarshalsPointerAnnotation(SootMethod method) {
return getAnnotation(method, MARSHALS_POINTER);
}
public static AnnotationTag getMarshalsValueAnnotation(SootMethod method) {
return getAnnotation(method, MARSHALS_VALUE);
}
public static AnnotationTag getMarshalsArrayAnnotation(SootMethod method) {
return getAnnotation(method, MARSHALS_ARRAY);
}
public static AnnotationTag getStructMemberAnnotation(SootMethod method) {
return getAnnotation(method, STRUCT_MEMBER);
}
public static AnnotationTag getStructVectorisedAnnotation(SootClass clazz) {
return getAnnotation(clazz, VECTORISED);
}
public static AnnotationTag getStructPackedAnnotation(SootClass clazz) {
return getAnnotation(clazz, STRUCT_PACKED);
}
public static AnnotationTag getArrayAnnotation(SootMethod method) {
return getAnnotation(method, ARRAY);
}
public static AnnotationTag getArrayAnnotation(SootMethod method, int paramIndex) {
return getParameterAnnotation(method, paramIndex, ARRAY);
}
public static AnnotationTag getBaseTypeAnnotation(SootMethod method) {
return getAnnotation(method, BASE_TYPE);
}
public static boolean hasByValAnnotation(SootClass clazz) {
while (!clazz.isPhantom() && clazz.hasSuperclass()) {
if (hasAnnotation(clazz, BY_VAL)) {
return true;
}
if (hasAnnotation(clazz, BY_REF)) {
return false;
}
clazz = clazz.getSuperclass();
}
return false;
}
public static boolean hasByRefAnnotation(SootClass clazz) {
while (!clazz.isPhantom() && clazz.hasSuperclass()) {
if (hasAnnotation(clazz, BY_REF)) {
return true;
}
if (hasAnnotation(clazz, BY_VAL)) {
return false;
}
clazz = clazz.getSuperclass();
}
return false;
}
public static AnnotationElem getElemByName(AnnotationTag annotation, String name) {
for (int i = 0; i < annotation.getNumElems(); i++) {
AnnotationElem elem = annotation.getElemAt(i);
if (name.equals(elem.getName())) {
return elem;
}
}
return null;
}
public static String readStringElem(AnnotationTag annotation, String name, String def) {
AnnotationStringElem elem = (AnnotationStringElem) getElemByName(annotation, name);
return elem != null ? elem.getValue() : def;
}
public static boolean readBooleanElem(AnnotationTag annotation, String name, boolean def) {
AnnotationIntElem elem = (AnnotationIntElem) getElemByName(annotation, name);
return elem != null ? elem.getValue() == 1 : def;
}
public static int readIntElem(AnnotationTag annotation, String name, int def) {
AnnotationIntElem elem = (AnnotationIntElem) getElemByName(annotation, name);
return elem != null ? elem.getValue() : def;
}
public static VisibilityAnnotationTag getOrCreateRuntimeVisibilityAnnotationTag(Host host) {
for (Tag tag : host.getTags()) {
if (tag instanceof VisibilityAnnotationTag) {
if (((VisibilityAnnotationTag) tag).getVisibility() == RUNTIME_VISIBLE) {
return (VisibilityAnnotationTag) tag;
}
}
}
VisibilityAnnotationTag tag = new VisibilityAnnotationTag(RUNTIME_VISIBLE);
host.addTag(tag);
return tag;
}
public static void addRuntimeVisibleAnnotation(Host host, String annotationType) {
if (!hasAnnotation(host, annotationType)) {
VisibilityAnnotationTag tag = getOrCreateRuntimeVisibilityAnnotationTag(host);
tag.addAnnotation(new AnnotationTag(annotationType, 0));
}
}
public static void addRuntimeVisibleAnnotation(Host host, AnnotationTag annoTag) {
removeAnnotation(host, annoTag.getType());
VisibilityAnnotationTag tag = getOrCreateRuntimeVisibilityAnnotationTag(host);
tag.addAnnotation(annoTag);
}
public static void removeAnnotation(Host host, String annotationType) {
for (Tag tag : host.getTags()) {
if (tag instanceof VisibilityAnnotationTag) {
ArrayList l = ((VisibilityAnnotationTag) tag).getAnnotations();
for (Iterator it = l.iterator(); it.hasNext();) {
AnnotationTag annoTag = it.next();
if (annoTag.getType().equals(annotationType)) {
it.remove();
}
}
}
}
}
public static void removeParameterAnnotation(SootMethod method, int paramIndex, String annotationType) {
for (Tag tag : method.getTags()) {
if (tag instanceof VisibilityParameterAnnotationTag) {
ArrayList l =
((VisibilityParameterAnnotationTag) tag).getVisibilityAnnotations();
if (l != null && paramIndex < l.size()) {
ArrayList annotations = l.get(paramIndex).getAnnotations();
if (annotations != null) {
for (Iterator it = annotations.iterator(); it.hasNext();) {
AnnotationTag annoTag = it.next();
if (annoTag.getType().equals(annotationType)) {
it.remove();
}
}
}
}
}
}
}
private static void copyAnnotations(SootMethod fromMethod, SootMethod toMethod, int visibility) {
for (Tag tag : fromMethod.getTags()) {
if (tag instanceof VisibilityAnnotationTag) {
if (((VisibilityAnnotationTag) tag).getVisibility() == visibility) {
VisibilityAnnotationTag copy = new VisibilityAnnotationTag(visibility);
for (AnnotationTag annoTag : ((VisibilityAnnotationTag) tag).getAnnotations()) {
copy.addAnnotation(annoTag);
}
toMethod.addTag(copy);
}
}
}
}
public static void copyAnnotations(SootMethod fromMethod, SootMethod toMethod, Visibility visibility) {
if (visibility == Visibility.Any) {
copyAnnotations(fromMethod, toMethod, RUNTIME_VISIBLE);
copyAnnotations(fromMethod, toMethod, RUNTIME_INVISIBLE);
copyAnnotations(fromMethod, toMethod, SOURCE_VISIBLE);
} else {
copyAnnotations(fromMethod, toMethod, visibility.ordinal());
}
}
private static void copyParameterAnnotations(SootMethod fromMethod, SootMethod toMethod, int start, int end, int shift, int visibility) {
List[] fromAnnos = getParameterAnnotations(fromMethod, Visibility.values()[visibility]);
List[] toAnnos = getParameterAnnotations(toMethod, Visibility.values()[visibility]);
for (int i = start; i < end; i++) {
toAnnos[i + shift].addAll(fromAnnos[i]);
}
for (Iterator it = toMethod.getTags().iterator(); it.hasNext();) {
Tag tag = it.next();
if (tag instanceof VisibilityParameterAnnotationTag) {
if (((VisibilityParameterAnnotationTag) tag).getKind() == visibility) {
it.remove();
}
}
}
VisibilityParameterAnnotationTag vpaTag = new VisibilityParameterAnnotationTag(toAnnos.length, visibility);
for (List annos : toAnnos) {
VisibilityAnnotationTag vaTag = new VisibilityAnnotationTag(visibility);
for (AnnotationTag anno : annos) {
vaTag.addAnnotation(anno);
}
vpaTag.addVisibilityAnnotation(vaTag);
}
toMethod.addTag(vpaTag);
}
public static void copyParameterAnnotations(SootMethod fromMethod, SootMethod toMethod, int start, int end, int shift, Visibility visibility) {
if (visibility == Visibility.Any) {
copyParameterAnnotations(fromMethod, toMethod, start, end, shift, RUNTIME_VISIBLE);
copyParameterAnnotations(fromMethod, toMethod, start, end, shift, RUNTIME_INVISIBLE);
copyParameterAnnotations(fromMethod, toMethod, start, end, shift, SOURCE_VISIBLE);
} else {
copyParameterAnnotations(fromMethod, toMethod, start, end, shift, visibility.ordinal());
}
}
public static VisibilityAnnotationTag getOrCreateRuntimeVisibilityAnnotationTag(SootMethod method, int paramIndex) {
for (Tag tag : method.getTags()) {
if (tag instanceof VisibilityParameterAnnotationTag) {
ArrayList l =
((VisibilityParameterAnnotationTag) tag).getVisibilityAnnotations();
if (l != null && paramIndex < l.size()) {
if ((l.get(paramIndex)).getVisibility() == RUNTIME_VISIBLE) {
return l.get(paramIndex);
}
}
}
}
VisibilityParameterAnnotationTag ptag =
new VisibilityParameterAnnotationTag(method.getParameterCount(), RUNTIME_VISIBLE);
for (int i = 0; i < method.getParameterCount(); i++) {
ptag.addVisibilityAnnotation(new VisibilityAnnotationTag(RUNTIME_VISIBLE));
}
method.addTag(ptag);
return ptag.getVisibilityAnnotations().get(paramIndex);
}
public static void addRuntimeVisibleParameterAnnotation(SootMethod method, int paramIndex, String annotationType) {
if (!hasParameterAnnotation(method, paramIndex, annotationType)) {
VisibilityAnnotationTag tag = getOrCreateRuntimeVisibilityAnnotationTag(method, paramIndex);
tag.addAnnotation(new AnnotationTag(annotationType, 0));
}
}
public static void addRuntimeVisibleParameterAnnotation(SootMethod method, int paramIndex, AnnotationTag annoTag) {
removeParameterAnnotation(method, paramIndex, annoTag.getType());
VisibilityAnnotationTag tag = getOrCreateRuntimeVisibilityAnnotationTag(method, paramIndex);
tag.addAnnotation(annoTag);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy