/* *******************************************************************
* Copyright (c) 2006 Contributors
* All rights reserved.
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Andy Clement initial implementation
* ******************************************************************/
package org.aspectj.ajdt.internal.compiler.lookup;
import org.aspectj.apache.bcel.classfile.annotation.ElementValue;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MarkerAnnotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.BooleanConstant;
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.Constant;
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.IntConstant;
import org.aspectj.org.eclipse.jdt.internal.compiler.impl.StringConstant;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TagBits;
import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.aspectj.weaver.AnnotationAJ;
import org.aspectj.weaver.AnnotationNameValuePair;
import org.aspectj.weaver.AnnotationValue;
import org.aspectj.weaver.ArrayAnnotationValue;
import org.aspectj.weaver.EnumAnnotationValue;
import org.aspectj.weaver.ResolvedType;
import org.aspectj.weaver.SimpleAnnotationValue;
import org.aspectj.weaver.StandardAnnotation;
import org.aspectj.weaver.World;
// not yet used...
public class EclipseAnnotationConvertor {
/**
* Convert one eclipse annotation into an AnnotationX object containing an AnnotationAJ object.
*
* This code and the helper methods used by it will go *BANG* if they encounter anything not currently supported - this is safer
* than limping along with a malformed annotation. When the *BANG* is encountered the bug reporter should indicate the kind of
* annotation they were working with and this code can be enhanced to support it.
*/
public static AnnotationAJ convertEclipseAnnotation(Annotation eclipseAnnotation, World w, EclipseFactory factory) {
// TODO if it is sourcevisible, we shouldn't let it through!!!!!!!!!
// testcase!
ResolvedType annotationType = factory.fromTypeBindingToRTX(eclipseAnnotation.type.resolvedType);
// long bs = (eclipseAnnotation.bits & TagBits.AnnotationRetentionMASK);
boolean isRuntimeVisible = (eclipseAnnotation.bits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationRuntimeRetention;
StandardAnnotation annotationAJ = new StandardAnnotation(annotationType, isRuntimeVisible);
generateAnnotation(eclipseAnnotation, annotationAJ);
return annotationAJ;
}
static class MissingImplementationException extends RuntimeException {
MissingImplementationException(String reason) {
super(reason);
}
}
private static void generateAnnotation(Annotation annotation, StandardAnnotation annotationAJ) {
if (annotation instanceof NormalAnnotation) {
NormalAnnotation normalAnnotation = (NormalAnnotation) annotation;
MemberValuePair[] memberValuePairs = normalAnnotation.memberValuePairs;
if (memberValuePairs != null) {
int memberValuePairsLength = memberValuePairs.length;
for (int i = 0; i < memberValuePairsLength; i++) {
MemberValuePair memberValuePair = memberValuePairs[i];
MethodBinding methodBinding = memberValuePair.binding;
if (methodBinding == null) {
// is this just a marker annotation?
throw new MissingImplementationException(
"Please raise an AspectJ bug. AspectJ does not know how to convert this annotation [" + annotation
+ "]");
} else {
AnnotationValue av = generateElementValue(memberValuePair.value, methodBinding.returnType);
AnnotationNameValuePair anvp = new AnnotationNameValuePair(new String(memberValuePair.name), av);
annotationAJ.addNameValuePair(anvp);
}
}
} else {
throw new MissingImplementationException(
"Please raise an AspectJ bug. AspectJ does not know how to convert this annotation [" + annotation + "]");
}
} else if (annotation instanceof SingleMemberAnnotation) {
// this is a single member annotation (one member value)
SingleMemberAnnotation singleMemberAnnotation = (SingleMemberAnnotation) annotation;
MethodBinding methodBinding = singleMemberAnnotation.memberValuePairs()[0].binding;
if (methodBinding == null) {
throw new MissingImplementationException(
"Please raise an AspectJ bug. AspectJ does not know how to convert this annotation [" + annotation + "]");
} else {
AnnotationValue av = generateElementValue(singleMemberAnnotation.memberValue, methodBinding.returnType);
annotationAJ.addNameValuePair(new AnnotationNameValuePair(new String(
singleMemberAnnotation.memberValuePairs()[0].name), av));
}
} else if (annotation instanceof MarkerAnnotation) {
MarkerAnnotation markerAnnotation = (MarkerAnnotation) annotation;
} else {
// this is a marker annotation (no member value pairs)
throw new MissingImplementationException(
"Please raise an AspectJ bug. AspectJ does not know how to convert this annotation [" + annotation + "]");
}
}
private static AnnotationValue generateElementValue(Expression defaultValue, TypeBinding memberValuePairReturnType) {
Constant constant = defaultValue.constant;
TypeBinding defaultValueBinding = defaultValue.resolvedType;
if (defaultValueBinding == null) {
throw new MissingImplementationException(
"Please raise an AspectJ bug. AspectJ does not know how to convert this annotation value [" + defaultValue
+ "]");
} else {
if (memberValuePairReturnType.isArrayType() && !defaultValueBinding.isArrayType()) {
if (constant != null && constant != Constant.NotAConstant) {
throw new MissingImplementationException(
"Please raise an AspectJ bug. AspectJ does not know how to convert this annotation value ["
+ defaultValue + "]");
// generateElementValue(attributeOffset, defaultValue,
// constant, memberValuePairReturnType.leafComponentType());
} else {
AnnotationValue av = generateElementValueForNonConstantExpression(defaultValue, defaultValueBinding);
return new ArrayAnnotationValue(new AnnotationValue[] { av });
}
} else {
if (constant != null && constant != Constant.NotAConstant) {
if (constant instanceof IntConstant || constant instanceof BooleanConstant) {
AnnotationValue av = generateElementValueForConstantExpression(defaultValue, defaultValueBinding);
return av;
}
throw new MissingImplementationException(
"Please raise an AspectJ bug. AspectJ does not know how to convert this annotation value ["
+ defaultValue + "]");
// generateElementValue(attributeOffset, defaultValue,
// constant, memberValuePairReturnType.leafComponentType());
} else {
AnnotationValue av = generateElementValueForNonConstantExpression(defaultValue, defaultValueBinding);
return av;
}
}
}
}
public static AnnotationValue generateElementValueForConstantExpression(Expression defaultValue, TypeBinding defaultValueBinding) {
if (defaultValueBinding != null) {
Constant c = defaultValue.constant;
if (c instanceof IntConstant) {
IntConstant iConstant = (IntConstant) c;
return new SimpleAnnotationValue(ElementValue.PRIMITIVE_INT, new Integer(iConstant.intValue()));
} else if (c instanceof BooleanConstant) {
BooleanConstant iConstant = (BooleanConstant) c;
return new SimpleAnnotationValue(ElementValue.PRIMITIVE_BOOLEAN, new Boolean(iConstant.booleanValue()));
} else if (c instanceof StringConstant) {
StringConstant sConstant = (StringConstant) c;
return new SimpleAnnotationValue(ElementValue.STRING, sConstant.stringValue());
}
}
return null;
}
private static AnnotationValue generateElementValueForNonConstantExpression(Expression defaultValue,
TypeBinding defaultValueBinding) {
if (defaultValueBinding != null) {
if (defaultValueBinding.isEnum()) {
FieldBinding fieldBinding = null;
if (defaultValue instanceof QualifiedNameReference) {
QualifiedNameReference nameReference = (QualifiedNameReference) defaultValue;
fieldBinding = (FieldBinding) nameReference.binding;
} else if (defaultValue instanceof SingleNameReference) {
SingleNameReference nameReference = (SingleNameReference) defaultValue;
fieldBinding = (FieldBinding) nameReference.binding;
} else {
throw new MissingImplementationException(
"Please raise an AspectJ bug. AspectJ does not know how to convert this annotation value ["
+ defaultValue + "]");
}
if (fieldBinding != null) {
String sig = new String(fieldBinding.type.signature());
AnnotationValue enumValue = new EnumAnnotationValue(sig, new String(fieldBinding.name));
return enumValue;
}
throw new MissingImplementationException(
"Please raise an AspectJ bug. AspectJ does not know how to convert this annotation value [" + defaultValue
+ "]");
} else if (defaultValueBinding.isAnnotationType()) {
throw new MissingImplementationException(
"Please raise an AspectJ bug. AspectJ does not know how to convert this annotation value [" + defaultValue
+ "]");
// contents[contentsOffset++] = (byte) '@';
// generateAnnotation((Annotation) defaultValue,
// attributeOffset);
} else if (defaultValueBinding.isArrayType()) {
// array type
if (defaultValue instanceof ArrayInitializer) {
ArrayInitializer arrayInitializer = (ArrayInitializer) defaultValue;
int arrayLength = arrayInitializer.expressions != null ? arrayInitializer.expressions.length : 0;
AnnotationValue[] values = new AnnotationValue[arrayLength];
for (int i = 0; i < arrayLength; i++) {
values[i] = generateElementValue(arrayInitializer.expressions[i], defaultValueBinding.leafComponentType());// ,
// attributeOffset
// )
// ;
}
ArrayAnnotationValue aav = new ArrayAnnotationValue(values);
return aav;
} else {
throw new MissingImplementationException(
"Please raise an AspectJ bug. AspectJ does not know how to convert this annotation value ["
+ defaultValue + "]");
}
} else {
// class type
throw new MissingImplementationException(
"Please raise an AspectJ bug. AspectJ does not know how to convert this annotation value [" + defaultValue
+ "]");
// if (contentsOffset + 3 >= this.contents.length) {
// resizeContents(3);
// }
// contents[contentsOffset++] = (byte) 'c';
// if (defaultValue instanceof ClassLiteralAccess) {
// ClassLiteralAccess classLiteralAccess = (ClassLiteralAccess)
// defaultValue;
// final int classInfoIndex =
// constantPool.literalIndex(classLiteralAccess
// .targetType.signature());
// contents[contentsOffset++] = (byte) (classInfoIndex >> 8);
// contents[contentsOffset++] = (byte) classInfoIndex;
// } else {
// contentsOffset = attributeOffset;
// }
}
} else {
throw new MissingImplementationException(
"Please raise an AspectJ bug. AspectJ does not know how to convert this annotation value [" + defaultValue
+ "]");
// contentsOffset = attributeOffset;
}
}
}